Refresh _NEXT.md with May 10 batch (audio + LAN + UI polish)
Some checks failed
CI / build-and-test (push) Failing after 59s

This commit is contained in:
Zac Gaetano 2026-05-10 13:37:20 -04:00
parent d8adb44a8f
commit dc25fe1eef

View file

@ -96,14 +96,52 @@ Spec at `docs/superpowers/specs/2026-05-08-embedded-teams-orchestration.md`. All
### Tests ### Tests
- 78 unit tests passing; 9 NDI integration tests gated behind `--filter requires=ndi` (runtime probe, finder + sender lifecycle on default and custom groups, loopback discovery, full pipeline frame round-trip asserting 1080p normalization). - 78 unit tests passing; 9 NDI integration tests gated behind `--filter requires=ndi` (runtime probe, finder + sender lifecycle on default and custom groups, loopback discovery, full pipeline frame round-trip asserting 1080p normalization).
## Done since May 10 hand-off
### Engine
- **Audio peak metering wired end-to-end.** `IsoHealthStats.PeakAudioLevel`
now reports real values from a sibling NDI audio capture loop in
`NdiReceiver`. New `INdiInterop.CaptureAudioPeak` method (default-
implemented for FakeNdiInterop, overridden in NdiInteropPInvoke).
`AudioPeakComputer` handles FLTP / FLT / PCM s16 with 14 unit tests
covering edge cases. UI VU bars in the participants DataGrid now
animate; the existing decay logic in `ParticipantViewModel` was
already in place waiting for real values.
### Control surface
- **LAN-reachable mode.** New checkbox in DISPLAY tab toggles whether the
REST/WebSocket surface and OSC bridge bind to `127.0.0.1` only or to all
interfaces (`http://+:port/`, `IPAddress.Any`). Settings panel surfaces
the routable URL with a Copy button (picker prefers physical NICs and
skips Tailscale / VPN tunnels / APIPA addresses). Use case: headless
host PC + thin client on the same LAN — operator runs Teams + TeamsISO
on a quiet machine, drives it from anywhere on the production network.
No auth — documented as a trusted-LAN-only mode. First-time bind
requires a one-shot `netsh http add urlacl`; the diagnostic warning
fires the exact remediation command if the bind fails.
### UI polish
- Visible hover affordances on every themed button (Ghost / Caption /
RailIcon / IsoToggle / Primary). Cyan accent borders + brighter fills
so mouse-hover and tab-focus give an unmistakable affordance regardless
of which dark surface the button sits on.
- Keyboard focus rings (`IsKeyboardFocused` triggers) so tab-cycling
through the UI gives visual feedback (was nothing — `FocusVisualStyle`
was `x:Null` with no replacement).
- ScrollBar restyled to slim transparent track + tinted thumb (Edge / VS
Code pattern) in place of the chunky Win9x default.
- ContextMenu / MenuItem styled to match the dark canvas — right-click on
a participant row no longer shows the cream-colored Notepad popup.
- ToolTip restyled: SurfaceElevated card with rounded corner + 320px
text wrap, replacing the cream Win98 popup.
- Wd.Button.Primary disabled state distinct (was identical to enabled).
## Next ## Next
1. **Smoke-test on real Teams.** Most of May's work hasn't run against a live meeting yet: the UIA in-call commands (mute / camera / share / leave) need their candidate-Name lists validated against the current Teams build, and the auto-apply-on-launch flow needs a real recurring meeting to confirm the 30-second grace window is right. Pin the AutomationIds for buttons we find — Name-based lookup is a starting point, AutomationId is what survives Teams UI updates. 1. **Smoke-test on real Teams.** Most of May's work hasn't run against a live meeting yet: the UIA in-call commands (mute / camera / share / leave) need their candidate-Name lists validated against the current Teams build, and the auto-apply-on-launch flow needs a real recurring meeting to confirm the 30-second grace window is right. Pin the AutomationIds for buttons we find — Name-based lookup is a starting point, AutomationId is what survives Teams UI updates. Now also includes: validate the audio peak metering against real Teams audio (check that FLTP decoding is correct for whatever sample rate Teams is broadcasting; the `--filter requires=ndi` integration tests don't exercise audio).
2. **Acquire a code-signing cert.** Pipeline is wired (see "CI / Release / Docs" above); just needs `SIGN_CERT_PFX_BASE64` + `SIGN_CERT_PASSWORD` set in Forgejo Secrets. OV cert (~$200/yr) gets us signed but SmartScreen builds reputation slowly; EV cert (~$300/yr, hardware token) is SmartScreen-trusted immediately. Azure Trusted Signing is the cloud-native path if a token-on-runner is fiddly. 2. **Acquire a code-signing cert.** Pipeline is wired (see "CI / Release / Docs" above); just needs `SIGN_CERT_PFX_BASE64` + `SIGN_CERT_PASSWORD` set in Forgejo Secrets. OV cert (~$200/yr) gets us signed but SmartScreen builds reputation slowly; EV cert (~$300/yr, hardware token) is SmartScreen-trusted immediately. Azure Trusted Signing is the cloud-native path if a token-on-runner is fiddly.
3. **Activate `MediaFoundationRecorderSink`.** Scaffold + activation docs at `docs/REAL-TIME-RECORDING.md` ship in this batch (gated behind `MF_AVAILABLE` build symbol). To enable: `dotnet add Vortice.MediaFoundation`, define `MF_AVAILABLE`, swap one line in `IsoController.EnableIsoAsync`. Rough ~10× disk-pressure reduction. 3. **Activate `MediaFoundationRecorderSink`.** Scaffold + activation docs at `docs/REAL-TIME-RECORDING.md` ship in this batch (gated behind `MF_AVAILABLE` build symbol). To enable: `dotnet add Vortice.MediaFoundation`, define `MF_AVAILABLE`, swap one line in `IsoController.EnableIsoAsync`. Rough ~10× disk-pressure reduction.
4. **Wire engine audio capture.** The UI's audio level VU bar (in the Live column) is in place but inert — `IsoHealthStats.PeakAudioLevel` always reads 0.0. Engine work needed: extend `INdiInterop.CaptureFrame` to also surface audio frames, parse based on FourCC (FLTp, PCMs16, etc), compute peak per pipeline tick, publish through `IsoPipeline.GetStats`. Once that's done the UI bar starts animating with no further changes. 4. **Forward Teams keyboard shortcuts via SendInput.** Phase E.2 hides the Teams window but doesn't forward Ctrl+Shift+M / Ctrl+Shift+O / Ctrl+Shift+H to it. UIA covers mute/camera/share/leave/raise-hand/chat/background already; SendInput would let us pass arbitrary global hotkeys through to a hidden Teams for actions UIA can't reach. Lower priority now that UIA covers the core actions.
5. **Forward Teams keyboard shortcuts via SendInput.** Phase E.2 hides the Teams window but doesn't forward Ctrl+Shift+M / Ctrl+Shift+O / Ctrl+Shift+H to it. UIA covers mute/camera/share/leave/raise-hand/chat/background already; SendInput would let us pass arbitrary global hotkeys through to a hidden Teams for actions UIA can't reach. Lower priority now that UIA covers the core actions.