Repository navigation
Phase 3c: Ask AI tab in the V2 workflow editor (0.261.211) - #1593
Merged
Paul Lizer (paullizer) merged 17 commits intoOct 1, 2026
Conversation
Adds the workflow editor's Ask AI side-panel tab on the shared assist thread, calling POST /api/user/workflows/assist. Answers are checked against the draft they were sent with, diffed client-side, and applied through applyAssist so they are highlighted, undoable and reviewed before saving. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cancel the running turn before the thread is released, and remember a key an editor held until its thread leaves the store, so a late answer never sweeps the chat's idle image transcripts. Mark the locked editor fieldset aria-busy. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- test_v2_workflow_ask_ai_logic.ts: 169 node checks for the request builder, response guard, code-point counting, client-side diff, candidate rebase, turn replay, errors and Draft with AI. - test_v2_workflow_ask_ai.py: driver plus source-level checks (plain-text rendering, gating, default-off thread options). - test_v2_workflow_ask_ai_parity(.py/_logic.ts): the editor's real requests go through 3b's parser and service, and the scripted answers come back through the editor's guard, rebase, diff and applyAssist. - The fallback change wording now matches the server's summary rule. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
microsoft#1585 took 0.261.210, so 3c moves up one. Mechanical: only version strings change. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Playwright suite for the Ask AI tab (25 items) over 3b's real assist pipeline with a scripted model: Done when, # placement, context documents, lock/Cancel/Retry/stale guard, the request contract, code-point limit, undo with skipped keys, every status, hostile text, Jump to (task field and flow block), hidden-tab cases, keyboard, narrow screens, Draft with AI and quick actions. - Proposal-draft tests: Edit from the proposal card sends base null and a draft without an id, and Save reviews AI changes before accepting. - Footer: on narrow screens Cancel and Save wrap together to a second row instead of wrapping the Save label. - A one-word error such as the role check's "Forbidden" shows the sentence in its message. Refs microsoft#1548 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
List the new dependencies in the order A2's guards expect, and update A1's guards for the opt-in code point count and the quick actions that leave the input alone. UTF-16 counting stays the default. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Through the proposal card's Edit: an Ask AI turn and closing the editor keep the chat's idle image thread, and once the editor lets its thread go the chat prunes as before. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…lizer-phase-3c-workflow-ask-ai-tab # Conflicts: # application/single_app/config.py
Every tab-built request is now POSTed as its exact text to POST /api/user/workflows/assist through 3b's route harness (the real route body, helpers and gates on a closed Flask app over a scripted model), and the tab replays the route's real 200 bodies. A new test checks that the route read exactly the bytes the tab sent, ran the pipeline once for the signed-in user, and answered uncached JSON. Refs microsoft#1548 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Feature docs: the Ask AI tab, its thread, requests, rebase and change check, turn cards, failures, Draft with AI and accessibility (WORKFLOW_AI_ASSISTANT.md); the shared thread's opt-in options and the workflow limit (V2_SHARED_ASSIST_THREAD.md); AI-authored changes now coming from Ask AI and Draft with AI (WORKFLOW_EDITOR_CHANGE_TRACKING.md). - Admin and guide: the setting now shows the tab and Draft with AI; a new "Ask AI to change a workflow" section and two troubleshooting rows. - Release notes: v0.261.211 above microsoft#1585's v0.261.210, which is unchanged. - test_v2_workflow_ask_ai.py: the four chat editors pass none of the shared thread's new options, and the client's instruction limit matches ASSIST_INSTRUCTION_MAX_LENGTH and is counted in code points. - workflowAssist.ts: correct a comment about per-field Revert. Refs microsoft#1548 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Explain the ignored PlaywrightError in AssistStub.release(), and import card_ui's fixtures by package path from the modules that define them, so CodeQL can see they are pytest fixtures rather than unused imports. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Review part 1 for microsoft#1593. R1: WorkflowsSection's reloadEditing reopened the editor and cleared the dirty flag after its reads finished, even if the editor had been closed, saved or replaced by another workflow's editor in the meantime. A request token now supersedes the reload when an editor opens, closes or saves, so a late reload is ignored. While a reload loads, the draft it is about to discard is locked (fields, Save, undo and redo, flow authoring, the Changes tab, Send, the quick actions and each card's Undo). Cancel and Escape still close the editor. A failed reload unlocks the draft. T1: the logic checks now pin the held-thread guarantees of pruneThreads: another conversation's sweep keeps an idle held workflow thread, the 50-thread cap keeps a held least-recently-touched thread, and a held keepKey sweeps nothing even when it isn't marked quiet. Browser tests cover a reload whose editor is closed, replaced by another workflow's editor or saved while it loads, and a reload that fails. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Review part 2 for microsoft#1593. T2: no test pressed Ctrl+Z or Ctrl+Y while the draft was locked, so the editor's key capture could be removed without a failure. Two browser cases now press Ctrl+Z, Ctrl+Y and Ctrl+Shift+Z on a focused flow block, which is not a text field, with an undo and a redo both available: once while an Ask AI request runs and once while a reload loads. Nothing changes. After Cancel request, or after the reload fails, the same keys on the same block undo and redo. The feature doc now says the reload lock includes the keys. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Draft with AI jumps to the instructions it drafted in the same pass that applies the change, but the highlight that carries the change key renders one deferred pass later. On a slow device the jump ran first, found no change key and fell back to the task item, whose first control is Task name. Every tracked field now carries its field key from its first render, and the jump looks for the change key, then the field key, then the item. On the Flow surface the disabled Draft with AI button dropped focus to the page, so history recovery asked the canvas to focus the block, batched with the change. jumpToChange now clears that block focus request, because the jump places focus itself. The List and Flow Draft with AI cases run under 6x CPU throttling and check focus on the drafted instructions, again after a settle, and in a focus log. The undo case also jumps to a field the turn no longer changes, which has no highlight. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CodeQL (py/uninitialized-local-variable) does not model pytest.skip as raising, so it flagged session in cpu_throttled as possibly unbound. Move the throttle, yield and reset into the try statement's else clause so they only run once the session exists. Behavior is unchanged: a browser without the DevTools protocol still skips. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
marked this pull request as ready for review
October 1, 2026 10:12
microsoft#1594 (Phase 5) merged into paullizer-react-v2-ui first and took 0.261.212, so 3c moves to 0.261.213. This is a mechanical renumber of this PR's own files: config.py, the release-notes heading, the docs' version lines and mentions, and the functional and UI test headers and version assertions. Every changed line differs only by the version. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Brings in Phase 5 (microsoft#1594, 0.261.212). Conflicts resolved: - application/single_app/config.py: keep VERSION 0.261.213 (3c). - docs/explanation/release_notes.md: the v0.261.213 section goes on top, then Phase 5's v0.261.212 section byte-identical, then v0.261.210 and earlier unchanged. docs/admin/workflow.md and docs/_data/features.yml merged cleanly; both sides are kept. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
merged commit Oct 1, 2026
677c8f3
into
microsoft:paullizer-react-v2-ui
11 checks passed
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Oct 1, 2026
Status update 4 for the chat orchestration workflows roadmap (docs only). - Status table: 3c done (microsoft#1593, v0.261.213), so Phase 3 is complete; Phase 5 done (microsoft#1594, v0.261.212); 6a in review (microsoft#1592). - 3c shipped block and its follow-ups; Phase 5 shipped block and its follow-ups; 6a in-review note; 6b run deep-link guidance now covers Phase 5's workflowRunHref. - Base failures on paullizer-react-v2-ui that the phase PRs report, with verified causes. - Gotchas 62 (result answers outside the message list) and 63 (Retry and Edit of a result-backed turn). Refs microsoft#1543 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
14 of 24 tasks
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Oct 1, 2026
Mechanical: the 0.261.213 stamps become 0.261.214 in 6a's own files: VERSION, the release-notes heading, the docs' version and front-matter lines, the test headers' Version and Implemented in lines, the assert_app_version_at_least floors and the Playwright bootstrap seed. 0.261.213 now belongs to Phase 3c (microsoft#1593). Part of 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 1, 2026
Brings in the V2 workflow editor's Ask AI tab (0.261.213). Conflicts: - config.py keeps VERSION 0.261.214. - docs/admin/workflow.md takes 3c's "Enable AI Workflow Assistant" row, with the Ask AI tab and Draft with AI wording, and keeps the "Use Workflow Results In Chat" row directly after it. - release_notes.md keeps the 0.261.214 section above 3c's 0.261.213 section. Every older section is unchanged. features.yml and the rest of workflow.md merged cleanly. app_surface.yml is unchanged: 3c added no settings, and the regenerated inventory matches the merged file. Part of microsoft#1546 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This was referenced Oct 1, 2026
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
POST /api/user/workflows/assistand applies each answer through 3a'sapplyAssistas one AI change. Highlights, Previously:, per-field Revert, the Changes list and the AI-change review on the first save all work as they do for 3a. The tab never saves.Retry-Afteris honored. Draft with AI fills a task's empty instructions.features.enable_workflow_ai_assistantis on and the editor can change a personal workflow. Group workflows, readers, unsupported drafts and workflows with an active run don't get it. It also works on a Phase 4 workflow proposal opened from chat with Edit. Admins get no new setting: the existing Enable AI Workflow Assistant now shows the tab.Linked issue
Closes #1548
Part of #1543
Release Notes & Latest Features
Is this visible to end users?
Is this admin-facing (Admin Settings, governance, deployment, config)?
No new setting: the existing Enable AI Workflow Assistant (
enable_workflow_ai_assistant, added in 3b) now also shows the tab and Draft with AI.docs/admin/workflow.mdsays so.Should this become a Latest Feature card?
Not yet, because a card needs a screenshot. It's listed as a follow-up for when the guide's screenshot exists.
Screenshot needed for the card?
Version bump
application/single_app/config.pyVERSIONthird segment bumped, or not needed because this is docs-only:0.261.212→0.261.213. Fix orchestrated web search and deep research in V2 chat #1582 took .209, Show what was extracted from V2 image uploads, index text-free images, and default image generation to 2025-04-01-preview #1585 .210 and Phase 5 (Phase 5: orchestration runs existing workflows (workflow_run, start-and-link) #1594) .212, so702f1c5cbmoved this PR from .211 to .213 before the V2 merge.deployers/version.txtbumped, or not needed becausedeployers/was not changed: not needed.Testing / validation
Everything ran on head
9ee340bba, one file per run, in sequence, with the V2 bundle built from that head. "Normal and-O" means both runs gave the same result. The CodeQL fix that followed,dc9d22ad1, changes only two browser-test files, and both Ask AI browser files passed again on it (see CodeQL). The three coordinator review rounds after that,439d1115b,c17339aa8and360207d97, reran the tests they affect; see Coordinator review. After Phase 5 merged,a9dd15b28merged the V2 tip5fc50a593. What reran on that head is listed at the end of this section, under After the Phase 5 merge.npm run build: passed. Its chunk-size warning is pre-existing.npm run typecheckandnpm run buildpassed again on360207d97.New tests
functional_tests/test_v2_workflow_ask_ai.py-O);python functional_tests/test_v2_workflow_ask_ai.py7/7. 7 passed (normal and-O) again on439d1115b,c17339aa8,360207d97anda9dd15b28, with 175 logic checksfunctional_tests/test_v2_workflow_ask_ai_parity.py-O), again ona9dd15b28ui_tests/test_v2_workflow_ask_ai.pydc9d22ad1; 29 passed on439d1115b; 31 passed onc17339aa8; 32 passed on360207d97,9a9590ce0anda9dd15b28ui_tests/test_v2_workflow_ask_ai_proposal.pydc9d22ad1,360207d97anda9dd15b28Shared components (N7)
functional_tests/test_v2_assist_thread.py-O), again ona9dd15b28functional_tests/test_v2_plan_editor_references.py-O)functional_tests/test_v2_chat_context_picker.py-O): base, see Known base failuresfunctional_tests/test_v2_image_editor.py-O)ui_tests/test_v2_assist_thread.pyui_tests/test_v2_plan_editor_references.pyui_tests/test_v2_orchestration_plan_editor.pyui_tests/test_v2_image_editor.pyui_tests/test_v2_workflow_editor.py360207d97ui_tests/test_v2_workflow_change_tracking.py360207d97ui_tests/test_v2_orchestration_workflow_proposal_card.py360207d97anda9dd15b283b's server tests and other regressions
functional_tests/test_workflow_assist_field_parity.pyfunctional_tests/test_workflow_assist_candidate_parity.pyfunctional_tests/test_workflow_assist_request.pyfunctional_tests/test_workflow_assist_scenarios.pyfunctional_tests/route_tests/test_workflow_assist_policy.pyfunctional_tests/test_v2_workflow_change_tracking.pyfunctional_tests/test_orchestration_workflow_proposal_editor_round_trip.pyfunctional_tests/test_group_workflow_file_sync_client_parity.pyfunctional_tests/test_v2_workflow_unsupported_schedule_readonly.pyfunctional_tests/test_workflow_alert_client_parity.pyfunctional_tests/test_workflow_calendar_schedule_client_parity.pyfunctional_tests/test_workflow_draft_v2_round_trip.pyfunctional_tests/test_workflow_file_sync_analyze_targets.pyfunctional_tests/test_workflow_flow_layout.pyfunctional_tests/test_v2_prompts_workbench.pyfunctional_tests/test_v2_prompt_composer_card.pyfunctional_tests/test_v2_chart_editor.pyfunctional_tests/test_v2_diagram_editor.pyfunctional_tests/test_block_revision_assist.pyfunctional_tests/test_assist_thread_submission_id.pyfunctional_tests/test_message_block_revisions.pyfunctional_tests/test_orchestration_plan_revision_routes.pyfunctional_tests/test_v2_elicitation_answers.pyfunctional_tests/test_orchestration_context_picker.pynode functional_tests/test_workflow_field_drafts.jsnode functional_tests/test_workflow_settings_client.jsui_tests/test_v2_chat_context_selection.pyui_tests/test_v2_elicitation_composer.pyui_tests/test_v2_prompt_composer_experience.pyui_tests/test_v2_image_reference_generation.pyui_tests/test_v2_workflow_loops.pyui_tests/test_v2_workflow_flow_authoring.py360207d97ui_tests/test_v2_personal_workflow_file_sync.py::test_editing_personal_sources_is_one_change_and_jump_lands_in_file_sync360207d97python ui_tests/test_v2_orchestration_composer.pypython ui_tests/test_v2_orchestration_elicitation.pyGuardrails, docs and the base check
python run_v2_guardrails.py <worktree> 4f778386b 9ee340bba 3c, mirrors the Development-only PR checks: broken access control, XSS sinks, Swagger routes, Python syntax and the malicious-PR review, plus a TS/TSX sink scan. All passed. The malicious-PR review's warnings are informational, with no blockers.python scripts/build_docs_inventory.py: no inventory change.python functional_tests/test_docs_app_surface_coverage.py: 7/7.python functional_tests/test_docs_site_quality.py: 6/6.python functional_tests/test_docs_latest_release_catalog_parity.py: 6/6. All three passed again on360207d97.python functional_tests/test_docs_link_integrity.py: 2/5.python functional_tests/test_docs_release_notes_integrity.py: 0/1. Both are base failures, with the same results on360207d97.python functional_tests/test_v2_ui_local_assets.py: 4/4 on360207d97.paullizer-react-v2-uiat5fc50a593, ona9dd15b28:4f778386bat9a9590ce0. It was 31 files, +6588/−116 atc17339aa8;360207d97addsuseWorkflowAuthoring.ts, and9a9590ce0adds one test line.config.pychanges only0.261.212→0.261.213release_notes.mdonly adds lines (+20/−0). The v0.261.213 section sits above Phase 5's v0.261.212 section, and the .212, .210 and .209 sections are byte-identical to the V2 tip.0.261.211, andgit grep 0.261.211finds nothing.After the Phase 5 merge
Phase 5 (#1594) merged first and took 0.261.212.
702f1c5cbrenumbers this PR from 0.261.211 to 0.261.213 on its own: 40 lines in 14 files, each changing only the version.a9dd15b28then merges the V2 tip5fc50a593with rerere off. Onlyconfig.py, kept at .213, andrelease_notes.mdconflicted; the .213 section goes on top, with Phase 5's .212 section byte-identical below it.docs/admin/workflow.mdanddocs/_data/features.ymlmerged cleanly, with both sides kept. Rerun ona9dd15b28, in sequence, with a fresh V2 build:npm run typecheckandnpm run build: passed.functional_tests/test_v2_workflow_ask_ai.py,test_v2_workflow_ask_ai_parity.pyandtest_v2_assist_thread.py: 33 passed (7, 12 and 14), normal and-O.python functional_tests/test_v2_workflow_ask_ai.py: 7/7, with 175 logic checks.ui_tests/test_v2_workflow_ask_ai.pyandui_tests/test_v2_workflow_ask_ai_proposal.py: 35 passed (32 and 3).ui_tests/test_v2_orchestration_workflow_proposal_card.py: 22 passed. I reran it because Phase 5 changedMessageList.tsx, which renders the proposal cards.test_docs_app_surface_coverage.py7/7,test_docs_site_quality.py6/6 andtest_docs_latest_release_catalog_parity.py6/6.python scripts/build_docs_inventory.pymakes no inventory change.test_docs_link_integrity.py(2/5) andtest_docs_release_notes_integrity.py(0/1) are base failures; see Known base failures.5fc50a593:check_xss_sinks.pypassed for 17 files andcheck_broken_access_control.pyfor 1.check_swagger_routes.pyskipped, because no changed Python file defines a route.py_compilepassed for all 7 changed Python files, and the route policy suites passed 10/10, 4/4 and 2/2.Documentation
### **(v0.261.213)**, above Phase 5's v0.261.212 section, has "Ask AI Tab In The V2 Workflow Editor" and "Draft With AI For Workflow Task Instructions".WORKFLOW_AI_ASSISTANT.mdcovers the Ask AI tab: when it's offered, the thread, sending, applying, the turn card, failures (including what's locked while a reload loads), Draft with AI and accessibility. It also has usage, the tab's tests and the known limitations.V2_SHARED_ASSIST_THREAD.mdhas "Options for the workflow editor" (countCodePoints,retainand held threads,textandsendText,cancelledMessage,contextDocumentsOnly, therenderReplywrapper) (N10).WORKFLOW_EDITOR_CHANGE_TRACKING.mdexplains how Ask AI and Draft with AI useapplyAssistandrevertTurn. Since review part 3 it also says that Jump clears a block focus request, and that every tracked field carries a field key that Jump finds before the highlight renders.docs/admin/workflow.md,docs/guides/create-a-workflow.md("Ask AI to change a workflow") anddocs/_data/features.yml.The guide declares the media slot
docs/images/guides/create-a-workflow-ask-ai.png. It shows a placeholder until a screenshot is added.Security checklist
@swagger_route(security=get_auth_security()): this PR adds no routes, and its only backend change isVERSION.sanitize_settings_for_user(): no settings are sent. The tab reads the existing per-user bootstrap flagfeatures.enable_workflow_ai_assistant.test_v2_workflow_ask_ai.pychecks that it imports only local modules.Decisions made autonomously
undefinedvalues andNaN(gotcha 25).workflowAssistViolationcomparesownFieldvalues, so without the rebase a liveid: undefinedagainst a missingidwould refuse every new-draft turn. The coordinator confirmed this is required.rebaseAssistCandidatekeeps the live value and its identity. On v3,rebased.flow === live.flowwhen the flow is unchanged.undefined, so a key the model deleted stays deleted.applyAssiststill refuses it.workflow:personal:<id>, and a new or proposal draft usesworkflow:new:<id>, one per editor mount.retain), so the thread isn't swept, and using it never sweeps a chat's idle image or plan thread.onReloadprop fromWorkflowsSectionreopens the saved version under a fresh editor key.time_zoneis sent only when the editor's time-zone list has the browser's zone. Otherwise it's left out and the server's default applies./api/workflows/draft-instructions, appears only where Ask AI does, and only on a task whose instructions are empty.WORKFLOW_TASK_INSTRUCTIONS_LIMITisn't added, and the message says so.enable_workflow_ai_assistant, so hiding the button whenever Ask AI is hidden is the conservative choice.{role, text}.#picker offers documents only (contextDocumentsOnly).planDraftReferencesandcanonicalPlanReferences(value, 20).fetch(N8).ApiErrordoesn't exposeRetry-After, and 503 provider throttling carries only the header.apiUrl,CREDENTIALS_MODEand the JSONAcceptandContent-Typeheaders.reloadingprop rather than reusingassist.busy, because busy also covers a 429 wait.jumpToChangeclears the block focus request that the step before it made, through a newclearFocusRequestinuseWorkflowAuthoring.ts. Without it, after Draft with AI on Flow, the canvas could take focus back from the drafted field.jumpToChangegets this. For a jump from a card, the Changes tab or a warning, any earlier request has already been carried out, so clearing it changes nothing.onRestorewhere a restore came from would change 3a's history.Real-server parity (N1)
functional_tests/test_v2_workflow_ask_ai_parity.pyconnects the tab's TypeScript to 3b's real code. It reuses the scenario builders intest_workflow_assist_candidate_parity.pyand their esbuild/node runner.Requests. The test builds requests with
buildWorkflowAssistRequestfrom editor-normalized drafts:time_zone, references, a 20-item conversation with emoji, tabs and new lines, and a 2,000-code-point instructionparse_assist_requestaccepts each one, and each is posted as its exact text through the real Flask route with a scripted model.Responses. Every candidate-parity scenario's real 200 body, including "new draft" and "new draft with a shared reference", passes
parseWorkflowAssistResponse.rebaseAssistCandidate,workflowAssistViolation(live, rebased)is''.verifyAssistChangesgives exactly the server'schanges[]. The key, kind, label, owner label, focus key and node id all match, with the same wording. There are no exceptions.N12: no disagreement between 3b's server and 3a's editor turned up.
Coordinator review
Part 1 (
439d1115b)reloadEditinginWorkflowsSection.tsxreopened the editor and cleared the dirty flag as soon as its two reads finished, even if the editor had been closed, saved or replaced by another workflow's editor while they loaded. In the worst case, another workflow's unsaved edits vanished without a prompt.editorRequesttoken (useRef) is bumped when an editor opens, closes or saves.reloadEditingtakes a fresh one and returns after its reads if the token changed.pruneThreads's held-thread guarantees are pinned. Three logic checks: another conversation's sweep keeps an idle held workflow thread; the 50-thread cap keeps a held least-recently-touched thread, evicts the next oldest and leaves 50; and a held keepKey that isn't marked quiet sweeps nothing.ui_tests/test_v2_workflow_ask_ai.py29 passed.functional_tests/test_v2_workflow_ask_ai.py7 passed (normal and-O), with 175 logic checks.functional_tests/test_v2_assist_thread.py14 passed (normal and-O).Part 2 (
c17339aa8)ui_tests/test_v2_workflow_ask_ai.py31 passed.functional_tests/test_v2_workflow_ask_ai.py7 passed (normal and-O).Part 3 (
360207d97)data-workflow-field-key, and the jump looks for the change key, then the field key, then the item.data-workflow-change-key, which the highlight sets one deferred render later (useDeferredValue). On a slow CPU the jump ran first, fell back to the task item and focused its first control, Task name.recoverAuthoring) asked the canvas to focus the block in the same batch as the change. The canvas could then take focus from the field after the jump.jumpToChangenow clears that request (decision 14).nodeIdbefore it looks for the field.finally. Each checks focus on the drafted instructions, again after a 1 s settle, and in afocusinlog that may hold only the button and the field. The undo case now also jumps to a task field the turn no longer changes, so there's no highlight to find.360207d97all three passed in each of 5 runs.360207d97:ui_tests/test_v2_workflow_ask_ai.py32 passed, the proposal file 3, change tracking 24, flow authoring 30, the workflow editor 9, the proposal card 22 and the File Sync jump case 1.functional_tests/test_v2_workflow_ask_ai.py7 passed (normal and-O). Typecheck, build and the docs suites passed.9a9590ce0. CodeQL flagged the throttle helper's CDP session as possibly unbound (see CodeQL below). The fix changes only that helper's control flow.ui_tests/test_v2_workflow_ask_ai.pypassed 32/32 again, and both throttled cases passed on their own.Mutation checks
For each mutant I changed the source, rebuilt as needed, confirmed that the named tests failed, then restored the source.
dangerouslySetInnerHTMLretain: falseDiagramEditorpassesretain: truereloadEditingignores the tokendraftLockedignores the reloadif (false && draftLocked && …)if (assistPending && …)data-workflow-field-keyon the fieldjumpToChangedoesn't clear the focus requestOne nuance on M4: the blank-Create Playwright case alone still passes, because
newWorkflowDefinition()has noidkey. The proposal and parity cases catch it.Removing the token bump in
openEditoris equivalent today. Every path to it, the list's Edit and Create behind the modal editor and a deep link that waits until no editor is open, runs only after the open editor closed, and closing already bumped the token. The bump stays as a guard. The coordinator's L2a, which drops the replay's turn slice but keeps the 20-item cap, is equivalent too, because a completed exchange always yields two items.CodeQL
All 11 checks passed on the merge head
a9dd15b28, includingAnalyze (python), and CodeQL reported "No new alerts in code changed by this pull request", with no annotations (check run 110328185558). All 11 had also passed on9a9590ce0, with no new alerts.On
360207d97every other check passed, but CodeQL raised one new error, again in this PR's own browser tests:py/uninitialized-local-variableatui_tests/test_v2_workflow_ask_ai.py:1450, in thecpu_throttledhelper that part 3 added.pytest.skip()as raising, so it saw a path wheresessionis read after theexceptwithout being bound. At runtime the skip raises, so no test was affected.9a9590ce0moves the throttle, theyieldand the reset into thetrystatement'selseclause, so they only run once the CDP session exists. This follows the repo's other CDP helper intest_v2_workflow_alert_notices.py, which does its work inside thetry. A browser without the DevTools protocol still skips.All 11 checks passed on
dc9d22ad1as well, with no new alerts.On
9ee340bbaevery check passed as well, but CodeQL raised two new notes, both in this PR's own browser tests:py/empty-exceptatui_tests/fixtures/workflow_ask_ai.py:181.AssistStub.release()ignored aPlaywrightErrorwith no comment. That error means the browser already cancelled the request, so there's no route left to answer.dc9d22ad1adds a comment saying so.py/unused-importatui_tests/test_v2_workflow_ask_ai_proposal.py:42–54, forcard_ui,connect_options,editor_assetsandeditor_browser.@pytest.fixturedefinition.test_v2_orchestration_workflow_proposal_card, which resolves only throughsys.path, and three of them were re-exports from other modules.dc9d22ad1imports each one from the module that defines it, with aui_tests.-qualified path.After the fix,
ui_tests/test_v2_workflow_ask_ai_proposal.pypassed 3/3 again andui_tests/test_v2_workflow_ask_ai.pypassed 25/25.Known base failures
None of these are in files this PR changes.
test_v2_chat_context_picker.py::test_the_composer_no_longer_carries_a_write_only_selectionassertsonPickerOpenChange={setPickerOpen}inComposer.tsx. The V2 tip hasonPickerOpenChange={(open) => {, and this PR doesn't touchComposer.tsx.test_v2_prompt_composer_card.py:test_the_server_records_what_the_bubble_needsandtest_the_typescript_logic_checks_pass.NameError: name 'prepared_chat_image_references' is not definedin the extracted<shipping-persistence-boundary>block ofroute_backend_chats.py. Show what was extracted from V2 image uploads, index text-free images, and default image generation to 2025-04-01-preview #1585 added that variable.4f778386b, and a clean worktree of4f778386bfails the same way.test_block_revision_assist.py::test_the_prompt_is_honest_about_positioning:functions_block_revision_assisthas noASSIST_SYSTEM_PROMPTanymore; it's nowCHART_ASSIST_SYSTEM_PROMPT.test_orchestration_plan_revision_routes.py::PlanRevisionRouteTests::test_document_removal_is_not_lost_when_editor_opensfails with "A selected document could not be opened…". It's backend only.ui_tests/test_v2_workflow_loops.py::test_revoked_record_refresh_clears_the_previous_page: the "no longer have access" alert never appears in the Complete record inspection region ofWorkflowExecutionHistory.tsx, which this PR doesn't touch. This PR'sWorkflowsSection.tsxchange only adds the reload wiring. The coordinator's brief listed this test as a known base failure.ui_tests/test_v2_orchestration_composer.pyandui_tests/test_v2_orchestration_elicitation.pyset their module-level_PAGEonly in theirmain()runner. They needpython <file>, where each passes 6/6, not pytest.test_docs_link_integrity.py(2/5) finds broken links, none in this PR's lines. Two of them arefeatures.ymllinks in thecontent-screeningentry, which is the same on the base.test_docs_release_notes_integrity.py(0/1) finds generated release pages stale for 149 releases ona9dd15b28, 148 of them already stale on the base5fc50a593. Against4f778386bit was 148 and 147.Honest notes
0228a36f7.9ee340bba.dc9d22ad1fixes them.9a9590ce0fixes it.pruneThreads's held-thread guarantees (T1) and the Ctrl+Z/Ctrl+Y capture (T2); and Draft with AI's focus on a slow device (F1), which my unthrottled browser tests missed.439d1115b,c17339aa8and360207d97fix them.Follow-ups
docs/images/guides/create-a-workflow-ask-ai.pngexists.test_docs_release_notes_integrity.py).prepared_chat_image_referencesbreak from Show what was extracted from V2 image uploads, index text-free images, and default image generation to 2025-04-01-preview #1585 intest_v2_prompt_composer_card.pyis the most recent.flowUnsupportedReasoninto the PythonworkflowForSave./api/workflows/draft-instructionsshould checkenable_workflow_ai_assistanton the server as well. That's a product decision, so this PR flags it and doesn't change it. The classic Draft Workflow Instructions button doesn't follow the setting today.Closes #1548
Part of #1543