# Commit + push the May 2026 polish batch to forge.wilddragon.net. # # Run from the repo root: # pwsh -ExecutionPolicy Bypass -File .\commit-and-push.ps1 # # Splits into 8 atomic commits (#59, #61, #64-#69), then pushes origin/main. # Stops on first error so you can resolve and re-run. $ErrorActionPreference = 'Stop' # Ensure we're at repo root. if (-not (Test-Path '.git') -or -not (Test-Path 'TeamsISO.sln')) { throw "Run from the TeamsISO repo root." } # Tidy up the diagnostic artifact I left while probing the sandbox. if (Test-Path '.claude-bash-test.txt') { Remove-Item '.claude-bash-test.txt' -Force Write-Host "Removed sandbox diagnostic file." -ForegroundColor DarkGray } # ─── helper ───────────────────────────────────────────────────────────── function Stage-AndCommit($message, [string[]]$paths) { Write-Host "" Write-Host "──── $message ────" -ForegroundColor Cyan foreach ($p in $paths) { if (Test-Path $p) { git add -- $p if ($LASTEXITCODE -ne 0) { throw "git add failed for $p" } } else { Write-Warning "Path not found, skipping: $p" } } # Anything actually staged? git diff --cached --quiet if ($LASTEXITCODE -eq 0) { Write-Host " (no changes to commit; skipping)" -ForegroundColor DarkGray return } git commit -m $message if ($LASTEXITCODE -ne 0) { throw "git commit failed: $message" } } # ─── #59 Auto-disable on participant departure ───────────────────────── # View-model gained AutoDisableOnDeparture; MainViewModel hooks departure; # DISPLAY settings shows the toggle. # (These three files also carry later changes — staging them here means the # first commit captures only the auto-disable additions IF you've checked # the diff is clean. If `git diff --cached` after the add looks bigger than # the auto-disable feature alone, abort, edit the message, and let the # combined commit cover #59 as part of the broader UI batch.) Stage-AndCommit ` "feat(ui): auto-disable ISOs when participants leave the meeting" ` @( "src/TeamsISO.App/ViewModels/GlobalSettingsViewModel.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/MainWindow.xaml" ) # ─── #61 Operator presets ────────────────────────────────────────────── # Only the new files; the wiring into MainWindow header / MainViewModel # was already staged above as part of #59 (because all three commits touch # MainWindow.xaml / MainViewModel.cs, the cleanest atomic split would # require git add -p; for batch-push we accept that the boundary is # approximate and the headline message reflects the dominant change). Stage-AndCommit ` "feat(ui): operator presets — save/load named ISO assignment snapshots" ` @( "src/TeamsISO.App/Services/OperatorPresetStore.cs", "src/TeamsISO.App/PresetsDialog.xaml", "src/TeamsISO.App/PresetsDialog.xaml.cs" ) # ─── #64 Optional MSI / exe code-signing in release.yml ──────────────── Stage-AndCommit ` "ci: optional MSI + exe code-signing in release.yml" ` @( ".forgejo/workflows/release.yml", "docs/RELEASING.md" ) # ─── #65 Refresh discovery affordance ────────────────────────────────── # Includes engine-side RefreshDiscovery + idempotent re-Add + regression test. Stage-AndCommit ` "feat(engine): refresh discovery affordance + idempotent re-Add handling" ` @( "src/TeamsISO.Engine/Discovery/NdiDiscoveryService.cs", "src/TeamsISO.Engine/Discovery/ParticipantTracker.cs", "src/TeamsISO.Engine/Controller/IIsoController.cs", "src/TeamsISO.Engine/Controller/IsoController.cs", "src/tests/TeamsISO.Engine.Tests/Discovery/ParticipantTrackerTests.cs" ) # ─── #66 / #67 / #68 / #69 UI batch ──────────────────────────────────── # These four features all touch MainViewModel.cs / MainWindow.xaml / theme # files together, so a per-feature split is impractical without git add -p. # We commit as one batch with a descriptive message. Stage-AndCommit ` "feat(ui): May 2026 batch — auto-apply preset, settings tabs, Phase E.2/E.3" ` @( "src/TeamsISO.App/Services/TeamsLauncher.cs", "src/TeamsISO.App/Services/TeamsControlBridge.cs", "src/TeamsISO.App/MainWindow.xaml.cs", "src/TeamsISO.App/Themes/WildDragonTheme.xaml" ) # ─── #70 / #71 / #73 Hardening + onboarding ──────────────────────────── # Crash diagnostics, first-launch welcome dialog, Reset-to-defaults button. # Touches App.xaml.cs, AboutWindow (re-open onboarding link), and adds the # new OnboardingWindow files. Stage-AndCommit ` "feat(ui): crash diagnostics, first-launch welcome, reset-to-defaults" ` @( "src/TeamsISO.App/App.xaml.cs", "src/TeamsISO.App/OnboardingWindow.xaml", "src/TeamsISO.App/OnboardingWindow.xaml.cs", "src/TeamsISO.App/AboutWindow.xaml", "src/TeamsISO.App/AboutWindow.xaml.cs" ) # ─── #77 Per-output recording ────────────────────────────────────────── # IRecorderSink + RawBgraRecorderSink + IsoPipelineConfig.Recorder wiring + # IsoController.SetRecording + UI checkbox in DISPLAY tab. Stage-AndCommit ` "feat: per-output recording — raw BGRA stream + ffmpeg convert.cmd" ` @( "src/TeamsISO.Engine/Pipeline/IRecorderSink.cs", "src/TeamsISO.Engine/Pipeline/RawBgraRecorderSink.cs", "src/TeamsISO.Engine/Pipeline/IsoPipelineConfig.cs", "src/TeamsISO.Engine/Pipeline/IsoPipeline.cs", "src/TeamsISO.Engine/Controller/IIsoController.cs", "src/TeamsISO.Engine/Controller/IsoController.cs" ) # ─── #78 / #79 REST control surface + preset apply lift ─────────────── # ControlSurfaceServer + PresetApplier (lifted from PresetsDialog) + # REST endpoints + DISPLAY tab toggle + CONTROL-SURFACE.md docs. # PresetsDialog and MainViewModel.TryAutoApplyPendingPreset both delegate # to PresetApplier so apply has a single implementation across the dialog, # auto-apply-on-launch, and the REST surface. Stage-AndCommit ` "feat: REST control surface + lift preset-apply into PresetApplier" ` @( "src/TeamsISO.App/Services/ControlSurfaceServer.cs", "src/TeamsISO.App/Services/PresetApplier.cs", "src/TeamsISO.App/PresetsDialog.xaml.cs", "docs/CONTROL-SURFACE.md" ) # ─── #80 In-app preview thumbnails ───────────────────────────────────── # Engine: IsoPipeline.LatestProcessedFrame + IsoController.GetLatestProcessedFrame. # UI: ParticipantViewModel.Thumbnail (WriteableBitmap, BGRA, 160x90 nearest-neighbor), # DataGrid Preview column, .csproj AllowUnsafeBlocks. Stage-AndCommit ` "feat: in-app preview thumbnails per participant" ` @( "src/TeamsISO.Engine/Pipeline/IsoPipeline.cs", "src/TeamsISO.Engine/Controller/IIsoController.cs", "src/TeamsISO.Engine/Controller/IsoController.cs", "src/TeamsISO.App/ViewModels/ParticipantViewModel.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "src/TeamsISO.App/TeamsISO.App.csproj" ) # ─── #81 / #82 WebSocket push + OSC bridge ───────────────────────────── # /ws on the existing HTTP listener for live state push; OscBridge as a # parallel UDP listener using the same command vocabulary. Stage-AndCommit ` "feat: WebSocket live-state push + OSC bridge" ` @( "src/TeamsISO.App/Services/ControlSurfaceServer.cs", "src/TeamsISO.App/Services/OscBridge.cs", "src/TeamsISO.App/App.xaml.cs", "src/TeamsISO.App/ViewModels/GlobalSettingsViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "docs/CONTROL-SURFACE.md" ) # ─── #83 / #85 Update check (manual + auto-on-launch) ───────────────── # Manual "Check for updates" in About + silent throttled launch-time check # with banner above the participants area. Stage-AndCommit ` "feat: update check — manual in About + auto-on-launch with banner" ` @( "src/TeamsISO.App/Services/UpdateChecker.cs", "src/TeamsISO.App/AboutWindow.xaml", "src/TeamsISO.App/AboutWindow.xaml.cs", "src/TeamsISO.App/ViewModels/UpdateBannerViewModel.cs", "src/TeamsISO.App/App.xaml.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/ViewModels/GlobalSettingsViewModel.cs", "src/TeamsISO.App/MainWindow.xaml" ) # ─── #86 Preset import / export ──────────────────────────────────────── # OperatorPresetStore.ExportAllAsJson + ImportBundle + Export/Import buttons # in the Presets dialog footer. Stage-AndCommit ` "feat: preset import / export bundles" ` @( "src/TeamsISO.App/Services/OperatorPresetStore.cs", "src/TeamsISO.App/PresetsDialog.xaml", "src/TeamsISO.App/PresetsDialog.xaml.cs" ) # ─── #87 Recording markers ───────────────────────────────────────────── # IRecorderSink.AddMarker fan-out via IIsoController.AddRecordingMarker; # UI button in IN-CALL bar; REST + OSC endpoints; manifest.json gets # markers[] array. Stage-AndCommit ` "feat: recording markers (UI button + REST + OSC + manifest array)" ` @( "src/TeamsISO.Engine/Pipeline/IRecorderSink.cs", "src/TeamsISO.Engine/Pipeline/RawBgraRecorderSink.cs", "src/TeamsISO.Engine/Controller/IIsoController.cs", "src/TeamsISO.Engine/Controller/IsoController.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "src/TeamsISO.App/Services/ControlSurfaceServer.cs", "src/TeamsISO.App/Services/OscBridge.cs", "docs/CONTROL-SURFACE.md" ) # ─── #88 / #89 NDI name template + enriched footer ───────────────────── # OutputNameTemplate static helper + ParticipantViewModel uses it on Toggle; # footer gains REC badge + Control-Surface badge. Stage-AndCommit ` "feat: custom NDI output name template + enriched status bar" ` @( "src/TeamsISO.App/Services/OutputNameTemplate.cs", "src/TeamsISO.App/ViewModels/ParticipantViewModel.cs", "src/TeamsISO.App/ViewModels/GlobalSettingsViewModel.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/MainWindow.xaml" ) # ─── #90 / #91 Disk space watcher + diagnostics bundle ───────────────── Stage-AndCommit ` "feat: disk space watcher + diagnostic bundle export" ` @( "src/TeamsISO.App/Services/DiskSpaceWatcher.cs", "src/TeamsISO.App/Services/DiagnosticsBundle.cs", "src/TeamsISO.App/App.xaml.cs", "src/TeamsISO.App/AboutWindow.xaml", "src/TeamsISO.App/AboutWindow.xaml.cs" ) # ─── #92 Per-participant recording opt-out ───────────────────────────── # IsoController.EnableIsoAsync overload taking record-override; UI checkbox # in DataGrid bound to ParticipantViewModel.RecordToDisk. Stage-AndCommit ` "feat: per-participant recording opt-out (Rec column in DataGrid)" ` @( "src/TeamsISO.Engine/Controller/IIsoController.cs", "src/TeamsISO.Engine/Controller/IsoController.cs", "src/TeamsISO.App/ViewModels/ParticipantViewModel.cs", "src/TeamsISO.App/MainWindow.xaml" ) # ─── #93 / #94 Keyboard shortcuts + help cheat sheet ─────────────────── # F1 / Ctrl+M / Ctrl+Shift+S / Ctrl+R InputBindings + HelpWindow dialog. Stage-AndCommit ` "feat: window-scoped keyboard shortcuts + help cheat sheet (F1)" ` @( "src/TeamsISO.App/HelpWindow.xaml", "src/TeamsISO.App/HelpWindow.xaml.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/MainWindow.xaml" ) # ─── #95 / #96 / #97 Bulk enable + filter + context menu ─────────────── # EnableAllOnlineCommand, ParticipantsView with live filter, right-click # context menu on DataGrid rows. Stage-AndCommit ` "feat: bulk enable + participant filter + right-click context menu" ` @( "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/ViewModels/ParticipantViewModel.cs", "src/TeamsISO.App/MainWindow.xaml" ) # ─── #98 / #99 / #100 / #101 / #102 Operator polish batch ───────────── # --apply-preset CLI, dynamic status with live counts, embedded HTML panel # at /ui, session timer in footer, NotesService + REST/OSC notes endpoint. Stage-AndCommit ` "feat: CLI flags, dynamic status, HTML panel, session timer, notes" ` @( "src/TeamsISO.App/App.xaml.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "src/TeamsISO.App/Services/ControlSurfaceServer.cs", "src/TeamsISO.App/Services/ControlPanelHtml.cs", "src/TeamsISO.App/Services/OscBridge.cs", "src/TeamsISO.App/Services/NotesService.cs", "docs/CONTROL-SURFACE.md" ) # ─── #103 Duplicate preset action ────────────────────────────────────── Stage-AndCommit ` "feat(ui): duplicate-preset action in Presets dialog" ` @( "src/TeamsISO.App/PresetsDialog.xaml", "src/TeamsISO.App/PresetsDialog.xaml.cs" ) # ─── #104 CHANGELOG.md ───────────────────────────────────────────────── Stage-AndCommit ` "docs: add CHANGELOG.md tracking the May 2026 batch" ` @( "CHANGELOG.md" ) # ─── #105 / #106 / #107 Final UI polish ─────────────────────────────── # NotesWindow viewer + ShowNotesCommand + IN-CALL bar Notes button + README # rewrite. Confirm-before-Stop-All (catches mid-show misclicks). # About dialog gained "Logs / Recordings / Notes" folder shortcut buttons. Stage-AndCommit ` "feat(ui): notes viewer + Stop-All confirm + folder shortcuts + README" ` @( "src/TeamsISO.App/NotesWindow.xaml", "src/TeamsISO.App/NotesWindow.xaml.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "src/TeamsISO.App/AboutWindow.xaml", "src/TeamsISO.App/AboutWindow.xaml.cs", "README.md" ) # ─── #116 / #117 / #118 Operator polish (toast, restart, roll) ─────── # Always-toast on participant disconnect (not just auto-disable path). # Per-pipeline "Restart this ISO" right-click action. # "Roll recording" via UI command + REST /recording/roll + OSC. Stage-AndCommit ` "feat(ui+control): disconnect toast, per-pipeline restart, roll recording" ` @( "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/ViewModels/ParticipantViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "src/TeamsISO.App/Services/ControlSurfaceServer.cs", "src/TeamsISO.App/Services/OscBridge.cs", "docs/CONTROL-SURFACE.md" ) # ─── #115 Test-pattern generator + console flag ────────────────────── # TestPatternGenerator: SMPTE color bars + sweep band BGRA frames. # TeamsISO.Console --test-pattern broadcasts TEAMSISO_TEST at 720p30. # Useful for verifying NDI runtime without Teams running. Stage-AndCommit ` "feat(engine+console): SMPTE test-pattern generator + --test-pattern flag" ` @( "src/TeamsISO.Engine/Pipeline/TestPatternGenerator.cs", "src/TeamsISO.Console/Program.cs", "src/tests/TeamsISO.Engine.Tests/Pipeline/TestPatternGeneratorTests.cs" ) # ─── #114 / #119 Tray icon + WinForms/WPF disambiguation ───────────── # Adds System.Windows.Forms via UseWindowsForms=true for NotifyIcon. # GlobalUsings.cs aliases Application + MessageBox to WPF (resolves # CS0104 ambiguity caused by WinForms exposing same-named types). # ControlSurfaceServer.cs gained explicit `using System.IO;` (implicit # usings shifted with UseWindowsForms). Stage-AndCommit ` "feat(ui): system tray icon + WinForms/WPF namespace disambiguation" ` @( "src/TeamsISO.App/Services/TrayIconHost.cs", "src/TeamsISO.App/Services/UIPreferences.cs", "src/TeamsISO.App/App.xaml.cs", "src/TeamsISO.App/TeamsISO.App.csproj", "src/TeamsISO.App/GlobalUsings.cs", "src/TeamsISO.App/Services/ControlSurfaceServer.cs", "src/TeamsISO.App/ViewModels/GlobalSettingsViewModel.cs", "src/TeamsISO.App/MainWindow.xaml" ) # ─── #76 / #74 / #112 Tests + audio meter scaffold + MF recorder ───── # OperatorPresetStore + OutputNameTemplate + OscMessage tests in a new # net8.0-windows test project. Audio level VU bar in DataGrid (engine # field added; capture path is a follow-up). MediaFoundationRecorderSink # scaffold gated behind MF_AVAILABLE build symbol. Stage-AndCommit ` "test+feat: App.Tests project + audio VU scaffold + MF recorder stub" ` @( "src/tests/TeamsISO.App.Tests/TeamsISO.App.Tests.csproj", "src/tests/TeamsISO.App.Tests/Services/OperatorPresetStoreTests.cs", "src/tests/TeamsISO.App.Tests/Services/OutputNameTemplateTests.cs", "src/tests/TeamsISO.App.Tests/Services/OscMessageTests.cs", "src/TeamsISO.App/Services/OperatorPresetStore.cs", "src/TeamsISO.App/TeamsISO.App.csproj", "src/TeamsISO.Engine/Domain/IsoHealthStats.cs", "src/TeamsISO.Engine/Pipeline/MediaFoundationRecorderSink.cs", "src/TeamsISO.App/ViewModels/ParticipantViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "TeamsISO.sln", "TeamsISO.Windows.slnf", "docs/REAL-TIME-RECORDING.md" ) # ─── #108 / #109 / #110 / #111 Final session-2 polish ───────────────── # UIPreferences persists DISPLAY toggles + ParticipantSort across launches. # PreviewWindow non-modal floating preview at 20Hz for multi-monitor. # Configurable participant sort order via ICollectionView.SortDescriptions. # NotesWindow gains inline input (operator can type notes directly, not # only via REST/OSC). HTML control panel gains a "Note…" button. Richer # GET / response. Updated CHANGELOG + README to reflect all of session 2. Stage-AndCommit ` "feat: persist UI prefs + preview window + sort + inline note input" ` @( "src/TeamsISO.App/Services/UIPreferences.cs", "src/TeamsISO.App/Services/ControlSurfaceServer.cs", "src/TeamsISO.App/Services/ControlPanelHtml.cs", "src/TeamsISO.App/ViewModels/GlobalSettingsViewModel.cs", "src/TeamsISO.App/ViewModels/MainViewModel.cs", "src/TeamsISO.App/PreviewWindow.xaml", "src/TeamsISO.App/PreviewWindow.xaml.cs", "src/TeamsISO.App/NotesWindow.xaml", "src/TeamsISO.App/NotesWindow.xaml.cs", "src/TeamsISO.App/ViewModels/ParticipantViewModel.cs", "src/TeamsISO.App/MainWindow.xaml", "README.md", "CHANGELOG.md" ) # ─── #72 / #75 UIA polish ────────────────────────────────────────────── # (Already committed above as part of the #66-#69 batch since they touched # the same TeamsControlBridge / TeamsLauncher files.) # ─── docs ─────────────────────────────────────────────────────────────── Stage-AndCommit ` "docs: refresh _NEXT.md after recording + control surface" ` @( "docs/superpowers/plans/_NEXT.md" ) # ─── Push ─────────────────────────────────────────────────────────────── Write-Host "" Write-Host "──── Pushing to origin/main ────" -ForegroundColor Cyan git push origin main if ($LASTEXITCODE -ne 0) { throw "git push failed" } Write-Host "" Write-Host "Done. Commits pushed to forge.wilddragon.net/zgaetano/teamsiso." -ForegroundColor Green Write-Host "Forgejo CI will now build the Linux engine on Ubuntu and the Windows release runner is dormant until you push a v*.*.* tag." -ForegroundColor DarkGray