Skip to content

Show one progress indicator per V2 orchestration phase - #1654

Merged
Paul Lizer (paullizer) merged 5 commits into
microsoft:paullizer-react-v2-uifrom
paullizer:paullizer-orchestration-single-progress-indicator
Oct 6, 2026
Merged

Paul Lizer (paullizer) merged 5 commits into
microsoft:paullizer-react-v2-uifrom
paullizer:paullizer-orchestration-single-progress-indicator

Conversation

@paullizer

@paullizer Paul Lizer (paullizer) commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • A running plan shows one progress indicator. Once a plan is approved (manually, on its timer or automatically), the V2 chat no longer draws a "Thinking" bubble above the plan card, which was already showing the run. The card is the only indicator until the answer arrives. Run notices, such as a saved-memory warning, stay under the finished answer's reasoning steps.
  • The card says what the run is doing. Its status line used to show a bare role such as "Reasoning". It now shows "Starting", then the running step's kind of work and title (for example "Gathering: Read quarterly reports"), then "Preparing the answer" once every step has settled. "Waiting for results" is unchanged.
  • Planning says Planning. While the planner works, the bubble reads "Planning" instead of "Thinking", so the plan card that replaces it reads as its result.
  • Impact: V2 chat orchestration users only. Ordinary chat still shows "Thinking", including a chat reply sent while a plan waits in the same conversation. Stop and the composer lock are unchanged. There are no server, API or payload changes.

Before: after Approve, a "Thinking" bubble sat above the plan card, which showed the plan's intent, 0/1, Review and a status of "Reasoning". After: only the card shows, with a status such as "Reasoning: Draft candidate names", until the answer arrives.

Root cause

A run borrows the chat store's shared streaming flag, which routes Stop to it, locks the composer and collects the run's thoughts for the answer. executeSavedPlan took it through beginOrchestrationTurn, and MessageList drew StreamingBubble whenever streaming was true. The store recorded only that something was streaming, not that it was the run, so the bubble couldn't step aside for the card.

The bubble had nothing to add anyway. The server never streams a run's answer: it sends orchestration_step frames and the occasional notice thought, then the whole answer in one content frame just before done (_finalize in functions_orchestration_execution.py). For the whole run, the bubble could only say "Thinking". The v0.261.204 fix removed the orchestration lane's progress card for the same reason, but left this placeholder.

Approach

  • chatStore.ts records who owns the streaming flag. New state orchestrationSurface is 'planning', 'running', or null for a chat stream. orchestrationSurfaces goes from a Set to a Map of conversation to phase, so leaving and reopening a conversation, and a server re-key, keep the phase. beginOrchestrationTurn takes an optional trailing phase that defaults to planning, so existing callers are unchanged. sendMessage, resumeChatStream, retryMessage and editMessage set it to null.
  • Why not infer it from the orchestration store. The composer only blocks on streaming, so a chat reply can be sent while a run waits for a durable result or is being reconciled. That run is still in flight on its card, so hiding the bubble whenever a run was in flight would also hide the reply's "Thinking". A new test drives exactly that case through the real controller.
  • The bubble hides only while the card is drawing the run. executeSavedPlan claims the surface as running, and the new selectActiveTurnRunInFlight is true exactly when ActiveOrchestrationCard draws its running row. StreamingBubble steps aside only when both hold, and shows as usual otherwise, so a run never ends up with no indicator.
  • describeRunProgress in orchestrationPlan.ts writes the status line. That module imports only types, so the new Node test runs the shipped function directly.

Notes for review

Commits

  1. 011b17640 Show one progress indicator per orchestration phase: the fix, its tests and its docs.
  2. e6c21aaf6 Renumber the progress indicator fix to 0.261.254.
  3. 639a5cb2a Merge V2 ea0d359 (Show a workflow's reply once in the conversation it created (0.261.253) #1637) into the orchestration progress indicator.
  4. fcde4b070 Renumber the progress indicator fix to 0.261.256.
  5. 054909864 Merge V2 6154f95 (V2 shared conversations: mention pills, agent activity lines, generated documents and media (0.261.255) #1652) into the orchestration progress indicator.

Linked issue

N/A: this came from direct feedback on the V2 orchestration UI, and no issue was filed.

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

Version bump

Testing / validation

At the head, 054909864, after merging #1652. These ran on the merged tree just before it was committed, and the commit contains exactly that tree.

  • npm --prefix .\application\v2_ui run typecheck: passed.
  • npm --prefix .\application\v2_ui run build -- --outDir ..\..\ui_tests\artifacts\orchestration-plan-editor and npm --prefix .\application\v2_ui run build: both passed.
  • node .\functional_tests\test_v2_orchestration_run_progress_status.mjs (new): passed, 8/8.
  • node .\functional_tests\test_v2_orchestration_streaming_surface.mjs (new): passed, 6/6, including the check that every write taking streaming names its owner.
  • node .\functional_tests\test_v2_orchestration_progress_lane.mjs: passed, 6/6.
  • node .\functional_tests\test_v2_collaboration_ai_activity_logic.mjs, node .\functional_tests\test_v2_collaboration_mention_pills_logic.mjs and node .\functional_tests\test_v2_drawer_media_logic.mjs (V2 shared conversations: mention pills, agent activity lines, generated documents and media (0.261.255) #1652's): all passed.
  • python .\functional_tests\test_v2_stream_reconnect.py: passed, 10/10.
  • python .\functional_tests\test_v2_new_chat_reset.py: passed, 6/6.
  • python .\functional_tests\test_v2_stream_leave_without_cancel.py: passed, 15/15.
  • python .\functional_tests\test_v2_prompt_composer_card.py: passed, 11/11, including its TypeScript checks, which call beginOrchestrationTurn with positional arguments.
  • python .\functional_tests\test_v2_prompts_workbench.py: passed, 22/22.
  • python .\functional_tests\test_collaboration_ai_activity_events.py and python .\functional_tests\test_collaboration_generated_documents.py (V2 shared conversations: mention pills, agent activity lines, generated documents and media (0.261.255) #1652's): passed, 6 and 5 checks.
  • python .\functional_tests\test_v2_prompt_attachment_persistence.py: 84 passed.
  • python .\functional_tests\test_workflow_reply_replaces_agent_posted_message.py (Show a workflow's reply once in the conversation it created (0.261.253) #1637's): passed, 10/10.
  • python .\functional_tests\test_docs_site_quality.py: passed, 6/6.
  • python .\functional_tests\test_docs_app_surface_coverage.py: passed, 7/7.
  • python -m pytest .\ui_tests\test_v2_orchestration_streaming_bubble.py .\ui_tests\test_v2_new_chat_reset.py .\ui_tests\test_v2_orchestration_planning_retry.py -q: 27 passed.
  • python -m pytest .\ui_tests\test_v2_reasoning_controls.py -q: 33 passed.
  • python .\ui_tests\test_v2_orchestration_plan_card.py: passed, 7/7.
  • python -m pytest .\ui_tests\test_v2_collaboration_ux.py -q (V2 shared conversations: mention pills, agent activity lines, generated documents and media (0.261.255) #1652's, which covers the shared-conversation side of StreamingBubble): 4 passed.
  • python .\scripts\check_xss_sinks.py --base-sha 6154f9599 --head-sha 054909864 (git diff --name-only 6154f9599 054909864 -- application): passed for all 7 files.

The new browser tests catch the old behaviour: with only application/v2_ui/src reverted, test_v2_orchestration_streaming_bubble.py fails 4 of 5, and only the unchanged tabular test passes.

At 011b17640, before the V2 merges:

  • Run one file at a time with python -m pytest <file> -q, all passed: test_v2_orchestration_approval_persistence.py 23, test_v2_orchestration_auto_open.py 5, test_v2_orchestration_conversation_context.py 5, test_v2_orchestration_model_picker.py 11, test_v2_orchestration_workflow_run_links.py 29, test_v2_workflow_run_card.py 41, test_admin_orchestration_actions.py 8, test_admin_orchestration_workflow_runs.py 9, test_admin_orchestration_workflow_proposals.py 7, test_v2_elicitation_composer.py 18, test_v2_prompt_composer_experience.py 56, test_chat_streaming_thinking_placeholder.py 1.
  • Run with python <file>, the way these runner-style files are written, all passed: orchestration composer 6/6, drawer views 3/3, elicitation 6/6, pending approval resume 5/5, plan editing 5/5, run hydration 7/7.
  • Of the 20 functional_tests/test_v2_* files matching orchestration, stream or tabular parity, 19 passed; test_v2_tabular_parity.py is below.

Not passing or not run, all unrelated to this change:

  • python .\functional_tests\test_v2_tabular_parity.py: 13/14, still at 054909864. The failing check ("Could not locate the composer submit handler") reads only Composer.tsx, which this PR doesn't change, so it fails the same way on V2.
  • These couldn't be collected in this environment: test_chat_saved_analysis.py, test_chat_three_document_smoke.py and test_chat_workflow_results.py (module 'lib' has no attribute 'GEN_EMAIL'), and test_v2_orchestration_plan_editor_backend.py and test_v2_orchestration_recovery_backend.py (No module named 'content_screening'). test_chat_saved_analysis.py calls beginOrchestrationTurn positionally; the new parameter is optional and last, and the TypeScript checks above cover the same call shapes.
  • test_docs_release_notes_integrity.py and test_docs_link_integrity.py already fail on V2: the generated release-notes pages lag the source by more than 180 releases, and 11 relative links and 10 site links are broken in pages this PR doesn't touch.
  • Running many orchestration UI files in one pytest process fails with "Playwright Sync API inside the asyncio loop", where the shared page fixture meets the files' own browsers. Each file passes on its own, as above.

Documentation

  • Release notes updated, or not needed. A new ### **(v0.261.256)** section has one Bug Fixes entry and one User Interface Enhancements entry. It sits directly above V2's v0.261.253 section (V2 shared conversations: mention pills, agent activity lines, generated documents and media (0.261.255) #1652 added no release-notes section) and is a pure 16-line insertion against V2 6154f9599.
  • Feature documentation updated, or not needed. In CHAT_ORCHESTRATION.md, "Stream events" now describes the Planning label, the run phase and the card's status line. The version header and the test table are updated too: the streaming bubble row, plus rows for the two new Node tests.
  • Fix documentation updated, or not needed. New docs/explanation/fixes/ORCHESTRATION_RUN_DUPLICATE_THINKING_INDICATOR_FIX.md covers the issue, root cause, files, tests, and before and after. ORCHESTRATION_DUPLICATE_PROGRESS_CARD_FIX.md (v0.261.204) links to it.

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security()). N/A: no routes are added or changed.
  • Settings sent to non-admin frontends use sanitize_settings_for_user(). N/A: no settings are sent.
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS. The change is in the bundled V2 React source, and no dependencies or script sources are added.
  • No secrets, keys, connection strings, or local-only artifacts are included. Build outputs (static/v2, ui_tests/artifacts) are gitignored and not committed.

Paul Lizer (paullizer) and others added 5 commits October 6, 2026 10:47
While an approved plan ran, the V2 chat drew the generic "Thinking"
streaming bubble beside the plan card's running row, so two indicators
described the same work and neither said what was happening. The run
borrows the chat store's shared streaming flag (Stop, composer lock,
thought collection), and MessageList drew the bubble whenever it was set.

- chatStore records which orchestration phase holds the streaming
  surface (planning or running); chat streams record none, so a chat
  reply sent while a run waits still shows Thinking.
- executeSavedPlan takes the surface as running. The streaming bubble
  draws nothing while the plan card is drawing that run, until the answer
  arrives, and falls back to the normal bubble if the card is not.
- While a turn plans, the bubble says Planning instead of Thinking.
- The running card's status line comes from describeRunProgress:
  Starting, then "<Gathering|Reasoning|Rendering>: <step title>", then
  Preparing the answer; Waiting for results is unchanged.
- New Node tests for the status helper and the real controller/store
  surface lifecycle; UI tests updated and extended; fix doc, feature doc,
  release notes; version 0.261.253.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
microsoft#1637 merged into paullizer-react-v2-ui as 0.261.253, the version this
branch also claimed, so this fix moves one above it. Only version
references change: config.py, the release notes heading, the fix and
feature docs, and the version headers of the tests this branch added or
updated. No behaviour changes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…icator

Bring in origin/paullizer-react-v2-ui at ea0d359, the merge of microsoft#1637
(0.261.253), which this branch had also numbered 0.261.253 before it was
renumbered.

Only two files conflicted:
- config.py keeps VERSION = "0.261.254", one above V2.
- release_notes.md keeps the v0.261.254 section directly above V2's
  v0.261.253 section, with every section byte-exact.

MessageList.tsx merged cleanly: V2's superseded-workflow-reply filter
changes the thread list, and this branch changes StreamingBubble.

Every other file matches the side that changed it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
microsoft#1652 merged into paullizer-react-v2-ui as 0.261.255, above the
0.261.254 this branch had taken, so this fix moves one above it again.
Only version references change: config.py, the release notes heading,
the fix and feature docs, and the version headers of the tests this
branch added or updated. No behaviour changes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…icator

Bring in origin/paullizer-react-v2-ui at 6154f95, the merge of microsoft#1652
(0.261.255), which went above the 0.261.254 this branch had taken; the
previous commit renumbers this fix to 0.261.256.

Only two files conflicted:
- config.py keeps VERSION = "0.261.256", one above V2.
- MessageList.tsx: both sides changed the top of StreamingBubble. The
  resolution keeps this branch's store read (orchestrationSurface,
  activeConversationId) and adds V2's collaborative selector, so every
  hook still runs before either early return. Both early returns stay:
  a run shown on its plan card, and a shared conversation whose
  activity line stands in for the bubble. Orchestration routes only
  accept personal conversations, so the two cannot apply at once.

chatStore.ts merged cleanly; V2's change adds no new streaming writes.
For MessageList.tsx and chatStore.ts the merge adds exactly V2's change
to this branch and exactly this branch's change to V2. The release notes
did not conflict: microsoft#1652 left them alone, so this PR's v0.261.256 section
still sits directly above V2's v0.261.253 section. Every other file
matches the side that changed it. No earlier recorded resolution was
applied.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit 4ae1df8 into microsoft:paullizer-react-v2-ui Oct 6, 2026
11 checks passed
Paul Lizer (paullizer) added a commit that referenced this pull request Oct 6, 2026
…0.261.257

#1654 merged as 0.261.256, the number this branch had taken. Both release
note sections are kept, with this branch's on top.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit that referenced this pull request Oct 6, 2026
…masked

Brings in #1654, which renumbered its progress indicator fix to 0.261.256.

- config.py: both sides had set 0.261.256, so git merged it silently; this fix
  now takes 0.261.257 so the two fixes keep separate versions.
- release_notes.md: the base's v0.261.256 section stays as it is, and this
  fix's entries move to a new v0.261.257 section at the top.
- chatStore.ts merged cleanly: the base's orchestrationSurface phase and this
  branch's deleted-message filter touch different code.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit that referenced this pull request Oct 6, 2026
#1654 took 0.261.256 on the base branch, so this fix's test headers,
minimum-version check, and fix documentation now name 0.261.257, matching
config.py and its release notes section.

Refs #1649.

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
…esign to 0.261.256

The base moved to 0.261.255, and open PRs microsoft#1654 and microsoft#1638 both hold
0.261.254, so this branch takes the next free number.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant