Repository navigation
V2 workflow alerts: require acknowledgment, repeating sound, size options and team delivery (0.261.235) - #1636
Merged
Paul Lizer (paullizer) merged 6 commits intoOct 5, 2026
Conversation
… (0.261.234) Each workflow alert rule can now require acknowledgment, play a sound once or repeat it until acknowledged, choose a small, medium or large size, and in a group workflow alert everyone in the group with one shared acknowledgment. - Rules store the new options only when not the default; the server validates them with reviewed messages, and both editors mirror them. - Matched rules merge options strongest-wins; a model-evaluated rule that asks for a stronger option is still evaluated. - Team alerts are one group-scoped notification; current members acknowledge it for everyone through POST /api/notifications/<id>/acknowledge, and members other than the owner read a simpler alert. - Read, dismiss and acknowledge writes are ETag-conditional with retry. - The pop-up read returns pending must-acknowledge alerts regardless of age or read state, plus team alerts, with complete and sounds_enabled. - V2 and classic re-show must-acknowledge alerts until acknowledged, play locally bundled tones in one tab per browser, and share a BroadcastChannel. - New admin setting enable_workflow_alert_sounds (on), per-device Play alert sounds switch, and a V2 Alert monitor switch for operations screens. Refs microsoft#1634 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
V2 - The sound follows the alerts the store holds (syncWorkflowAlertSound), so an alert acknowledged while it waited, in another tab or by the bell stops sounding, and a refused sound is never retried for an acknowledged alert. - Acknowledged ids are never re-presented by a read that left earlier. - Open acknowledges only the alert opened; other pending alerts stay in the notice and keep sounding. Acknowledging one keeps the loop going for the rest. - Play once chimes once per browser through a shared soundedOnce record, checked and written under the Web Lock. - Alerts that need acknowledgment lead the notice and card. - A pending notice takes its own room in the full rail instead of covering the items below, and a flyout steps aside from focus it covers (WCAG 2.4.11). - The full-size dialog is no longer capped at 85vh. - Enable sound stays until a retried sound plays. Classic - One repeating loop in the loudest tone; a refused tab gives up the lock; refused one-off chimes are retried; the shared soundedOnce record. - Mark as read is offered again for ordinary alerts without links. Tests: V2 and classic regressions for each finding (mutation-checked against the previous commit), and a classic/V2 sound contract parity test. Refs microsoft#1634 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Found in review of the previous commit: - Each "play once" alert took the Web Lock on its own, so when several arrived together the first in server order (newest) won and the rest were dropped: a newer low alert's chime could play instead of an older critical alert's alarm. V2 and classic now gather the chimes asked for in one task into a batch, take the lock once, play the loudest that hasn't chimed in the browser and record all of them. Enable sound retries refused chimes the same way. - A V2 flyout that had stepped aside could keep that flag while an ordinary alert led and focus moved elsewhere, so the next alert needing acknowledgment arrived invisible. Every focus move is now measured whatever leads, and the record belongs to one lead in one placement, so a new lead is shown. Tests: V2 and classic regressions for both, mutation-checked against the previous commit. Refs microsoft#1634 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This was referenced Oct 4, 2026
microsoft#1635 took 0.261.234, so this PR's release notes section moves to v0.261.235, above microsoft#1635's section. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
microsoft#1635 merged into paullizer-react-v2-ui as 0.261.234 first. Moves VERSION, the feature and guide docs, and this PR's test headers and version floors to 0.261.235. Refs microsoft#1634 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Remove the unused find_group_by_id import from functions_notifications and the unused stopAllWorkflowAlertSounds helper from notifications.js. - Drop an unused variable in the V2 editor UI test. - py/cyclic-import reports functions_notifications -> functions_group -> functions_settings -> content_screening.service -> functions_notifications. The chain predates this PR and closes only through imports made inside functions (the rule counts those too), so nothing can fail while modules load. New test_workflow_alert_notifications_import_cycle.py keeps any module-level cycle out of functions_notifications and loads the real modules cold and offline in each order the app reaches them, with and without -O. Refs microsoft#1634 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
marked this pull request as ready for review
October 5, 2026 17:52
Paul Lizer (paullizer)
merged commit Oct 5, 2026
5be1d84
into
microsoft:paullizer-react-v2-ui
11 checks passed
Paul Lizer (paullizer)
added a commit
that referenced
this pull request
Oct 5, 2026
V2 moved to 5be1d84 (VERSION 0.261.235) when #1636 merged: must-acknowledge workflow alerts, alert sounds, sizes and team delivery. Conflicts: - config.py: keep this branch's 0.261.238, still above V2's 0.261.235. - release_notes.md: keep both sections, 0.261.238 above 0.261.235. This also restores V2's 0.261.234 entry exactly: the previous merge (ab87e79) left extra spaces in its Ref line and dropped the blank line before 0.261.233. admin_settings_fields.py, functions_personal_workflows.py, functions_settings.py, route_frontend_admin_settings.py and docs/_data/features.yml auto-merged. docs/_data/app_surface.yml auto-merged with capabilities: 125, because both sides raised the same count by one. Regenerated with scripts/build_docs_inventory.py: 126, for enable_chat_orchestration_workflow_handoff and enable_workflow_alert_sounds. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
added a commit
that referenced
this pull request
Oct 5, 2026
paullizer-react-v2-ui merged #1636 (workflow alert acknowledgment) and published v0.261.235, which this branch used for Phase 1. The integration branch's sections are kept exactly as published. This branch's ten sections shift up one, to v0.261.236 through v0.261.245, and config.py becomes 0.261.245. Every file only this branch changed is checked to equal its previous content with those versions shifted, every file only the integration branch changed is byte-identical to it, and the release notes are the integration branch's file plus this branch's ten sections. Ten files changed on both sides. config.py and the release notes conflicted on versions only. The other eight merged cleanly; in docs/guides/create-a-workflow.md only this branch's six lines about its own versions were shifted, and #1636's line about 0.261.235 is kept. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This was referenced Oct 5, 2026
Paul Lizer (paullizer)
added a commit
that referenced
this pull request
Oct 5, 2026
Brings in #1636 (must-acknowledge workflow alerts, sounds, sizes and team delivery), which also used 0.261.235 and changed the alert notice this branch moves from My Workspace to the bell. - WorkflowAlertNotice.tsx: kept the bell anchor. #1636 gave an alert that needs acknowledgment room of its own below My Workspace in the full rail; that room is now WorkflowAlertRowSlot, a row under the rail's header whose notch is measured to point at the bell. It pushes New chat and the navigation down and sits outside the chat scroll region. The bell's overlay slot stands aside while it is in use; the flyout keeps #1636's step-aside behaviour. - Feature docs and the notifications guide describe the row instead of My Workspace; both sides' text is kept. - Renumbered this PR to 0.261.236: config.py, this PR's tests and docs, and its release-notes section, now above #1636's 0.261.235 entry. - Tests: the in-flow test also checks the row hangs from the bell, comes after the header controls and survives collapse/expand; the scrolled chat rail test covers a must-acknowledge alert; the functional test guards the row. Refs #1642. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
15 of 24 tasks
Paul Lizer (paullizer)
added a commit
that referenced
this pull request
Oct 5, 2026
PR #1636 took 0.261.235, so the settings fix moves to 0.261.236 and the Microsoft 365 orchestration fix to 0.261.237. This merge resolves the version and release notes conflicts; the next commit renumbers the rest. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
added a commit
that referenced
this pull request
Oct 5, 2026
PR #1636 took 0.261.235 on paullizer-react-v2-ui. The settings document type fix is now 0.261.236, and the Microsoft 365 orchestration fix is 0.261.237, in code headers, tests and documentation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Oct 6, 2026
V2 is still at 0.261.233. microsoft#1635, microsoft#1636, microsoft#1637 and microsoft#1638 claim .234 to .236, so this branch takes .237. Every 0.261.234 reference moves to 0.261.237: config.py, the release notes header, the feature docs, the chat-controls reference and the test headers. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Oct 6, 2026
Brings in microsoft#1636 (V2 workflow alerts: require acknowledgment, repeating sound, size options and team delivery, released as 0.261.235). Three conflicts: - config.py: VERSION kept at 0.261.237, which is still above V2's 0.261.235. - release_notes.md: both sides added a section at the top. Both are kept intact under their own headings, v0.261.237 above v0.261.235, so against V2 the file only gains 6b-2's section. - ui_tests/test_v2_workflow_alert_notices.py: the last line of test_open_run_goes_to_the_run_in_its_workspace keeps 6b-2's read_calls == ["o1", "o2", "o4"], and every must-acknowledge test microsoft#1636 appended after it is kept unchanged. Refs microsoft#1546 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Oct 6, 2026
microsoft#1636 changed BootstrapPayload.features to BootstrapFeatures, which allows undefined values, so App.tsx and MessageList.tsx no longer typechecked against workflowRunTrackerShouldRun's Record<string, boolean> parameter after the merge. The gate already compares each flag with === true, so only the parameter type widens; the tracker test now also covers an explicit undefined flag. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Oct 6, 2026
Sets config.py VERSION to 0.261.238, one above the versions claimed by the open V2 PRs (microsoft#1636 0.261.234, microsoft#1637 0.261.235, microsoft#1638 0.261.236, 6b-2 next), and moves the hand-off modules' and tests' Version, Implemented in, MINIMUM_VERSION and assert_app_version_at_least literals to it. The off-golden fixture keeps its factual capture note (f1aeef1, 0.261.233). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New route
POST /api/notifications/<notification_id>/acknowledge(recipients only, 404 otherwise).GET /api/notifications/workflow-alertsalso returns pending must-acknowledge alerts (no recency window) and team alerts from the caller's groups, withcompleteandsounds_enabled. Read, dismiss and acknowledge writes are now ETag-conditional with retry, so concurrent writes to a shared alert can't drop each other.Commits after the feature
paullizer-react-v2-uiand renumbered to 0.261.235. Clearer saved-result error messages and repaired workflow test harnesses #1635 merged first as 0.261.234; this PR's release notes section, VERSION, docs and test headers now say 0.261.235.find_group_by_idimport, the unusedstopAllWorkflowAlertSoundshelper and an unused test variable.About the remaining CodeQL
py/cyclic-importnoteIt reports
functions_notifications→functions_group→functions_settings→content_screening.service→functions_notifications. That chain predates this PR (the base already importsfunctions_groupat the top offunctions_notifications); CodeQL reports it here because this PR edited that import line.py/cyclic-importis a recommendation-level maintainability rule that also counts imports made inside functions, and both links that close this chain are function-local (functions_settings.pylines 2254 and 2370,content_screening/service.pyline 1234), so nothing can fail while modules load (py/unsafe-cyclic-importdid not fire). Moving this PR's imports into functions wouldn't clear the note and would break the stub-loaded tests. Newfunctional_tests/test_workflow_alert_notifications_import_cycle.pykeeps any module-level cycle out offunctions_notificationsand loads the real modules cold and offline in each order the app reaches them. It can be dismissed as "won't fix", or left for a separate cleanup of the settings and screening imports.Linked issue
Refs #1634
Release Notes & Latest Features
Is this visible to end users?
Is this admin-facing (Admin Settings, governance, deployment, config)?
Should this become a Latest Feature card?
Screenshot needed for the card?
Version bump
application/single_app/config.pyVERSIONthird segment bumped, or not needed because this is docs-only (0.261.234 → 0.261.235; Clearer saved-result error messages and repaired workflow test harnesses #1635 took 0.261.234 first)deployers/version.txtbumped, or not needed becausedeployers/was not changedTesting / validation
After merging the base and the CodeQL changes (head
8f39dafad):python -m pytest functional_tests/test_workflow_alert_notifications_import_cycle.py— 16 passed. Mutation-checked: hoisting the two function-local imports to module level fails the static guard and the group-first cold import.python -m pyteston the workflow alert, notification, editor, docs-bell and route-policy functional files (the 24 files listed in the earlier run plus the new import test) — 444 passed, 1 failed:test_chat_completion_notifications.py::test_version_updated_for_feature, which requires exactlyVERSION = "0.250.047"(stale, unrelated).python -m pytest ui_tests/test_workflow_alert_classic_acknowledgment.py ui_tests/test_v2_workflow_alerts.py— 48 passednode --check application/single_app/static/js/notifications.js— passedpython scripts/check_xss_sinks.py --base-sha efee70775 --head-sha HEAD <63 changed files>— passed;python scripts/check_broken_access_control.py --base-sha efee70775 --head-sha HEAD <33 changed .py files>— passed;python scripts/check_swagger_routes.py <3 changed route files>— passedpython functional_tests/test_docs_app_surface_coverage.py— 7/7 passed;python functional_tests/test_docs_site_quality.py— 6/6 passedEarlier, at
c78092a28(no V2 source has changed since):npm --prefix application/v2_ui run typecheckandnpm --prefix application/v2_ui run build— passedpython -m pytest ui_tests/test_v2_workflow_alert_notices.py ui_tests/test_v2_notifications_bell.py ui_tests/test_v2_workflow_alerts.py— 132 passedpython -m pytest ui_tests/test_workflow_alert_classic_acknowledgment.py— 18 passed (three consecutive runs)Not run, or failing for reasons unrelated to this change:
SIMPLECHAT_UI_BASE_URL(a running, signed-in app) were skipped.test_notification_polling_redirect_guard.pyis stale on the base branch too: it expects the notifications comment directly after{% if session.get('user') %}and anotifications.jstag without?v=, and the base already hascompletion-audio-cues.jsbetween them and the cache-buster.test_workflow_priority_alerts.py(CosmosClient credentials whenconfig.pyis imported) andtest_group_notification_context.py(needs live Cosmos DB) need Azure configuration.module 'lib' has no attribute 'GEN_EMAIL') came from a cryptography 50 / pyOpenSSL 25.3 mismatch in my local Python, not from the app; with a compatible cryptography those tests pass.Known risks and limitations:
AutoplayAllowlistin Edge and Chrome, documented). The alert itself always shows.completekeeps them from being retired, and they appear as the others are acknowledged.Documentation
New
docs/explanation/features/WORKFLOW_ALERT_ACKNOWLEDGMENT.md; updatedWORKFLOW_ALERT_RULES.md,V2_WORKFLOW_ALERT_NOTICES.md,V2_WORKFLOW_ALERT_EDITING.md,WORKFLOW_PRIORITY_ALERTS.md, the create-a-workflow, manage-notifications and update-profile-preferences guides,docs/admin/workflow.md,docs/_data/features.ymlanddocs/_data/app_surface.yml, and a v0.261.235 release notes section.Security checklist
@swagger_route(security=get_auth_security())sanitize_settings_for_user()