Repository navigation
Phase 4: orchestration proposes workflows - #1580
Merged
Paul Lizer (paullizer) merged 21 commits intoSep 30, 2026
Merged
Paul Lizer (paullizer) merged 21 commits into
Paul Lizer (paullizer) merged 21 commits into
Conversation
Captures the planner system prompt, payload, repair message, capability resolution and strict deliverable-kind error on the unmodified Phase 2 base so later commits prove the new setting (off by default) leaves orchestration planning byte-identical. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Phase 4 (microsoft#1547) prerequisite: a workflow proposed from chat that reviews new File Sync files must open in an editor that can show and change File Sync. - New Flask-free functions_workflow_file_sync_sources.py: the collector the personal sources route always applied (own sources behind the personal gate, the active group and public workspace a user manages), read-only, with a settings reader seam and a planner projection. - GET /api/user/workflows/file-sync-sources uses it and returns file_sync_enabled (the personal gate), so V2 can say File Sync is off. - V2: the personal editor offers Monitor File Sync changes and Run File Sync before each run, labels sources by workspace, marks deleted personal sources, reloads after file_sync_source_unavailable, and keeps untouched settings verbatim. Only the File Sync lines of the dialog changed (microsoft#1548). - Tests: the real collector and role checks, client parity in both scopes, a new personal File Sync Playwright suite, and updated editor suites. - Docs: V2_PERSONAL_WORKFLOW_FILE_SYNC.md; the guide and three docs no longer call personal File Sync a limitation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Build a bounded, handle-only planning context for workflow proposals from chat: the requester's personal workflow catalog (MCP summary shape), the agents they may select with matched action kinds, the File Sync sources and selected documents they may use in a personal workflow. The handle-to-record map stays on the server with the turn; the planner never sees record ids, task instructions or credentials. V2 sends the browser's IANA time zone with each plan request. The server validates it with the workflow schedule zone list (exact names only) and falls back to UTC. The zone and the workflow context are stored with the turn and carried through replans, question answers, plan editor revisions, retries and execution. None of this is read, stored or passed unless enable_chat_orchestration and enable_chat_orchestration_workflows are on (the new setting defaults off), so every context builder is called with exactly its previous arguments when workflow proposals are off. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The coordinator reserved 0.261.204 for Phase 4, so move VERSION and the headers, docs and version floors this branch added from 0.261.200. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A plan can now declare a proposed workflow as a deliverable, but only while enable_chat_orchestration_workflows is on: with it off, the planner sees the same kinds, reasons, facts and error messages as before. - Only a workflow_propose step delivers a workflow, exactly one, and only when the user asked for it (requested explicit). A proposal no deliverable declares is refused, and a lone proposal step is linked to the only planned workflow. - Closed, application-owned unavailable reasons for workflows, including workflow_one_per_request for a second workflow in the same request. - The answer step is told that a card after the answer proposes the workflow and that nothing is created until the user approves it; delivery notes cover a proposal that was unavailable, turned off or not prepared. - V2 normalizes the kind, labels it "Workflow proposal", and shows a prepared proposal as "Proposed" rather than "Delivered". Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Brings in microsoft#1566 (Phase 2 workflow draft service), microsoft#1564 (A1/A2), microsoft#1567 (N2), microsoft#1565 and microsoft#1569 (3a change tracking). The only textual conflict was config.py, resolved to this change's reserved VERSION 0.261.204. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Phase 4, commit 4: a chat plan can now propose one personal workflow. - Registry: a workflow_propose descriptor with a closed blueprint argument schema (task_actions capped at 5), max one per plan, and a request gate that is dormant unless enable_chat_orchestration_workflows is on and the request has a workflow planning context. A failed gate check logs the error type only and leaves the capability unavailable. - New functions_orchestration_workflows.py: plan-time blueprint checks (static rules, check_workflow_blueprint with the request's time zone and handles, agent capability coverage), the adapter that runs the Phase 2 dry run and retains a server-only sidecar plus a public card, deterministic proposal ids, similar-workflow hints, rebuild on restore, and drop_workflow_proposals, which degrades a plan by removing the proposal step and every binding, delivery and final response naming it. - Planner: instructions, one shared repair, then degrade (never for plan edits), with the workflow deliverable made unavailable when degraded. - Executor restores the sidecar on resume; plan editing threads the workflow planning context; the services alias skips the new adapter. - functions_workflow_drafts.check_workflow_blueprint: a storage-free structural check used at plan time. - Setting enable_chat_orchestration_workflows (default off, only a real boolean true saves as on), the Propose workflows capability option, admin docs and the regenerated docs inventory. - Tests: new test_orchestration_workflow_propose_capability.py; the handle-prefix cases; two more V2 round-trip builder cases; constant drift equalities; the dependency allowlist entry. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Adds the requester-only status, accept, deny and draft routes for workflow proposals, with the decision compare-and-swap on the producing run, the re-accept guard (Create again), idempotent accept, the claim window, and activity logging on create. A retry child drops recorded decisions, and apply_workflow_origin honors an edited proposal. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The V2 chat shows each workflow an orchestration plan proposed under the answer that proposed it, in the requester's own conversations only. The card discloses the schedule, each task's runner and full instructions, Microsoft 365 reach and alerts as plain text, and offers Create & start, Create paused, Deny and Edit. Edit opens the V2 workflow editor seeded with the proposal's draft; Save accepts the proposal with the edited workflow. The state is read back from the server on every load, and a card that is still creating polls within the claim window, pausing while hidden. The workflow editor dialog gains two additive props, initialDraft and onSaveOverride. The new Phase 4 tests gain standalone pytest runners. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A recurring request often implies a result for the current period too, such as "every Monday, tell me what to focus on this week". When workflow proposals are offered, the planner is now told to answer the current period once as a preview and to propose the workflow for the runs to come, resolving the preview's relative dates from request_local_time. In a turn whose planning context can support a proposal, the answer-writing step is told the user's local time just before the request, in the wording a calendar workflow's run gives each task, so the preview and the scheduled runs read "this week" the same way. The line is computed when the answer is written, from the turn's validated zone or the planning context's zone. Every other answer is written from exactly the messages it was written from before. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
microsoft#1575 took 0.261.204 on V2 and 3b holds 0.261.205, so the coordinator moved Phase 4 to 0.261.206. Move VERSION and the headers, docs, version floors and stubbed bootstrap version this branch added from 0.261.204. Only files this branch changed since V2 7900ab1 are touched, before merging V2, so microsoft#1575's own 0.261.204 references stay as they are. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Brings in microsoft#1575 (remove the redundant orchestration progress card, which took 0.261.204) and microsoft#1570 (roadmap status). The only textual conflict was config.py, resolved to this change's reserved VERSION 0.261.206. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Versions now follow the order PRs go ready: microsoft#1578 takes 0.261.205 and 3b (microsoft#1577) takes 0.261.206, so the coordinator moved Phase 4 to 0.261.207. Move VERSION and the headers, docs, version floors and the stubbed bootstrap version this branch set to 0.261.206. Only files this branch changed since V2 2f8dab4 are touched. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The document catalog took every document the candidate probe authorized, so a document the probe found by searching could become a standing input of a proposed workflow. Offer only the documents the user selected or referenced with # in this request (the turn's document_ids seed), still filtered by the enrichment's current authority check. A task that needs another document can add it in the editor. Tests: a probe-only document is left out of the catalog and the handle map, and a #-named group document is kept, through the real merge_elicitation_context and enrich_planner_candidates. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Admin: the classic Chat Orchestration pane and the V2 admin field list gain Propose Workflows From Chat (enable_chat_orchestration_workflows), off by default, depending on Chat Orchestration and personal workflows. The classic form normalizer saves it. Docs: a feature page for chat orchestration workflow proposals, a "Create a workflow from chat" guide section, a chat-controls section for the proposal card, the admin settings row and the v0.261.207 release notes. Tests: - the Monday-email "done when" chain: plan, adapter, status and Create & start, the stored weekly Monday 08:00 workflow in the request's zone with notify-only digest rules, a second accept returning the same id and Deny refused afterwards - the proposal and its server-only values never reach the stream, the public step list or the assistant messages - an unexpected create failure releases the claim, so a retry creates - the step refuses another user, a legacy plan and a cancelled run before describing, authorizing or persisting anything - a proposal step left behind by a failed drop is still refused - the admin switch's field, form normalizer, template and Playwright behavior Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Brings microsoft#1578 (flow canvas stable re-renders, 0.261.205), microsoft#1579 and microsoft#1576 (pytest return-False guard, XSS guardrail updates). Conflicts: config.py keeps Phase 4's 0.261.207; release_notes.md puts the v0.261.207 section above v0.261.205 and restores the unindented v0.261.204 heading. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The proposal card's Open workflow and similar-workflow links use workflowProposalLink, which returns the fixed /workspace/workflows path with only a URLSearchParams-encoded workflow_id query, so it can't return a script URL. The XSS sink check (diff mode against 18dac67) passes. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Two Playwright tests for the overlap with microsoft#1569 (3a, change tracking), which made file_sync an authored field of structured (version 3) drafts: * A structured personal workflow switched to the Monitor File Sync changes trigger saves file_sync in the payload, with no "cannot change saved identity" rollback, and the real personal rules authorize the source. * Editing a personal Monitor workflow's File Sync sources is exactly one Changes-tab row ("On, 1 source" to "On, 2 sources"), and its Jump focuses the first source inside the File Sync section. Mutation checks on a rebuilt bundle: dropping 'file_sync' from WORKFLOW_AUTHORED_FIELDS fails the first test (the switch is rolled back and the source stays disabled); breaking the Jump section lookup fails the second at the focus check while the first still passes. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The proposal feature page said plan validation reports no_suitable_agent when no agent covers a task's actions. Plan validation only reports agent_capability_mismatch, and only when another offered agent has every action kind the task needs. When no offered agent has them, the plan passes and the proposal step stores the card reason no_suitable_agent, so the card shows the proposal as unavailable. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…utes Commit 5 added a module-level import of log_workflow_creation to route_backend_orchestration.py, for the activity log entry an accepted workflow proposal records. The shared activity-logging stub in test_support/app_stubs.py didn't provide it, so every suite that imports the orchestration routes through stubbed_config or import_app_module failed in setUp with an ImportError: plan_revision_routes, plan_revision_references and the V2 plan editor backend suite. The stub now provides it as a no-op, like the other activity loggers. plan_revision_references passes 24/24 and the plan editor backend suite 7/7, normally and under -O. plan_revision_routes passes 28/29; the one failure, test_document_removal_is_not_lost_when_editor_opens, fails the same way on the base. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Use get_user_settings directly as the default settings reader, and dict as the stubbed File Sync config reader, instead of wrapping each in a lambda. - Explain why the personal File Sync source list skips an active group or public workspace the user can't use. - Call the stubbed fetch responder without the unused request argument. - Import the plan editor's constants and fixtures in one from-import. No behavior change. Refs microsoft#1547 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
marked this pull request as ready for review
September 30, 2026 04:30
Paul Lizer (paullizer)
merged commit Sep 30, 2026
6cc22fc
into
microsoft:paullizer-react-v2-ui
11 checks passed
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Sep 30, 2026
Phase 4 (microsoft#1580) landed first and took 0.261.207, and microsoft#1578 took 0.261.205, so 0.261.206 is skipped. This is a byte-level replace of 0.261.206 with 0.261.208 in every file of this PR, with CRLF preserved; nothing else changes. Refs microsoft#1548 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
Sep 30, 2026
Merges paullizer-react-v2-ui at 6cc22fc (microsoft#1580) with rerere off. - config.py: VERSION 0.261.208. - release_notes.md: the v0.261.208 section sits above Phase 4's v0.261.207 section, which is unchanged. - test_route_blueprint_policy_inventory.py: keeps Phase 4's proposal coverage line and test, adds the assistant coverage line, and moves Version to 0.261.208. - docs/_data/app_surface.yml: regenerated with scripts/build_docs_inventory.py (capabilities 122). Refs microsoft#1548 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
Sep 30, 2026
Phase 4 (microsoft#1547, microsoft#1580) made personal File Sync editable: workflowForSave now spreads workflowFileSyncForSave for every scope, so an edited file_sync is sent as workflowFileSyncConfig normalizes it, with sources reduced to scope_type, scope_id and source_id and dropped while File Sync is off (unless the trigger is file_sync). The Python port gains workflow_file_sync_config and workflow_file_sync_for_save and applies them before the alert fields, so the server's projection saves exactly what the editor would. The candidate parity suite gains eleven File Sync save cases checked against the real TypeScript under Node and against pinned answers, and the field parity suite now pins the two File Sync mode lists. The assistant still has no File Sync operations; that remains a follow-up. 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
Sep 30, 2026
Record 3b (microsoft#1577, v0.261.208) and Phase 4 (microsoft#1580, v0.261.207) as shipped and mark 3c (the Ask AI tab) in progress. Add what later phases build on, their follow-ups, the side fixes from microsoft#1576, microsoft#1578 and microsoft#1579, and gotcha 61 (Microsoft 365 pending-action run links). Docs only; no version bump. Refs microsoft#1543 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.
Refs #1547
Part of #1543
Draft until the coordinator's review passes. Version 0.261.207 (
config.py.205 → .207 only).Summary
With the new admin setting Propose Workflows From Chat (
enable_chat_orchestration_workflows, off by default), a chat orchestration plan can answer a recurring request once, as a preview, and propose a personal workflow for the runs to come. "Every Monday at 8, read my email and tell me what I should focus on this week" gets this week's answer and a proposed Monday 08:00 workflow in the user's time zone.workflow_proposecapability (Reason role) andworkflowdeliverable. The planner writes a closed Phase 2 blueprint that names the requester's agents, File Sync sources, the documents they named in this request and their existing workflows only by request-local handles. Plan validation runs the draft service's write-free checks. A blueprint that still fails after one repair is dropped with everything bound to it, and the rest of the plan runs.adapter_workflow_proposedry-runs the blueprint, then stores a smallstructured-v1proposalresult and a server-only sidecar (blueprint digest, handles, time zone, summary without instructions, similar workflows, expiry, reason). The card is the only surface.GET /api/v2/orchestration/runs/<run_id>/workflow-proposals, thenPOST …/<proposal_id>/accept,POST …/<proposal_id>/denyandGET …/<proposal_id>/draft. Accept is idempotent (uuid5 proposal and workflow ids). Decisions use the run doc's 8-attempt etag CAS with a 120-second claim window. A denied proposal can't be accepted, proposals expire after 14 days, and a workflow the requester deleted comes back only through Create again. Accept logs the creation in the activity log, never approves Run as, and refuses URL Access.Docs:
docs/explanation/features/CHAT_ORCHESTRATION_WORKFLOW_PROPOSALS.md,V2_PERSONAL_WORKFLOW_FILE_SYNC.md,docs/admin/orchestration.md,docs/reference/chat-controls.md,docs/guides/create-a-workflow.md, the v0.261.207 release notes, and the regenerateddocs/_data/app_surface.yml.Decisions made autonomously
From the approved plan
workflow_proposeis unavailable there (workflow_shared_conversation). A chat later converted to collaboration makes its proposals unavailable. The routes still check the requester.json_object. The strict json_schema variant (a Phase 2 follow-up) is declined, and the Phase 2 schema is enforced at plan time instead.task_actions(closed kinds). When another offered agent has every kind a task needs, a mismatched runner is repairableagent_capability_mismatch. When no offered agent has them, the plan passes, and the card shows the proposal as unavailable withno_suitable_agent.run_as: noneis repairablerun_as_required, and the repair setsself.workflowdeliverable becomes unavailable withworkflow_draft_invalid, and the preview still runs. Plan edits are refused rather than degraded.proposal_id:uuid5(run_id:step_id)of the producing run. Retries resolve inherited stubs to it.created_at, and it also blocks Create again. The user can ask again for a fresh, revalidated proposal.origin.edited:apply_workflow_originhonors a caller-suppliededitedfor a new workflow, computed from material fields against the stored-blueprint build.workflowdeliverable kind exists for the planner only while the setting is on, so messages and prompts are unchanged when it's off.workflow_quota_reached), and accept rechecks.timezoneis filled with the validated request zone during normalization.file_sync_enabled, so V2 mirrors the save gate.Made while implementing
checkpoints_deletedhides its proposals (404proposal_not_found), and a deletion that lands during a decision returns 409proposal_unavailable.run_not_found/proposal_not_found), not a 403.service_unavailable. The draft service'sworkflows_unavailablestays a 403./approvals, and Connect links to/profile?tab=settings#m365-connection-status. Open workflow and the similar-workflow links useworkflowProposalLink, built as agreed from Track P'sWORKFLOW_LINK_PARAM. It's added to the XSS checker's approved same-origin URL builders.capabilities_usedincludesworkflow_propose, in a personal conversation, on an unmasked message.chat-orchestration-capabilities-section, right after Enable Action Access.#-referenced in this request (the turn'sdocument_idsseed), still filtered by the enrichment's authority check. A document the candidate probe found by searching is never offered.log_workflow_creationimport inroute_backend_orchestration.pybroke every suite that imports the route throughfunctional_tests/test_support/app_stubs.py. The shared activity-logging stub now provides it.Coordinator review notes, as folded in
time_zonein the body that still uses America/New_York.workflow_context_unavailable, logged with codes only. The queries are bounded, the build is timed, and the catalog block has a character cap that drops the lowest-priority entries first. There's one test per catalog raising.captured_fromstays historical.proposal(workflow_proposal_not_consumable), and a dropped step takes every binding with it. There's a test for an answer step that consumes the proposal.-<hash6>. Tests cover "2024 Report", "日本語", "!!!" and a 200-character name.m365.connectedcomes from the stored record only. Polling stops at the 120-second claim window and pauses while hidden.IfNotModifiedloop, with exhaustion mapped to 409proposal_busy. It has the all-412 test and the confirm-fails-after-create test.test_orchestration_workflow_proposal_done_when.py.initialDraftandonSaveOverridetouch only the dialog's props and its single save call site. The plan-editing hunk is small and separate.workflowRunLink.ts,notificationLinks.tsandworkflowAlertNotices.tsare unchanged.Runs when File Sync finds changes in <source>. Manual says Create and "It runs only when you start it from Workflows".test_orchestration_research_pre_effect.pyandtest_workflow_document_picker_recent_targets.py.return Falsetests. New tests fail withassert,self.assert*orraise.Validation
Everything below ran at 177e0bc, except the broad sweep, which ran at 8cd926f. The two commits after the sweep change only a feature doc and the shared test stub, and the suites that import the stub were rerun at 177e0bc. The head, 5933c07, only addresses CodeQL notes, with no behavior change; the suites it touches were rerun there (see CodeQL). "Base" means V2 18dac67 (VERSION .205), run from a
git archivesnapshot of that commit. Each block names its runner.pytest, one process per file, normally and with
python -O(38 files)Everything passes in both modes except the three base failures listed at the end.
app_stubsimporters: conversation-context routes 23.ui_tests/test_v2_orchestration_plan_editor_backend.pypasses 7/7.test_orchestration_research_pre_effect.py41, andtest_workflow_document_picker_recent_targets.py3/4 (a base failure).Scripts (
python functional_tests\<file>,__main__result)These files report results from
__main__(their tests return values), so they ran as scripts.test_orchestration_agent_selection.py6/6,test_orchestration_run_hydration_routes.py6/6 andtest_orchestration_turn_recovery_identifiers.py5/6. All three are identical on base.test_docs_app_surface_coverage.py7/7 andtest_docs_site_quality.py6/6.test_docs_link_integrity.py2/5, with the same 11 broken links as base. Head checks 1087 relative links and base 1064, so every added link resolves.test_docs_release_notes_integrity.py0/1, as on base. The generated release pages are stale: base is missing 143 releases and head 144, the extra one being v0.261.207.Broad sweep: pytest, one process per file, normal mode (367 more files)
The sweep covered 367 more files whose names cover orchestration, workflows, V2, admin, group and public workspaces, Microsoft 365 and tabular. 287 passed. The other 80:
test_app_settings_auxiliary_writers.pyhas 18 failures, identical on base;test_tabular_row_orchestration_scale.pyis identical on base, test by test. Tests 1–31, run alone: 28 pass, and Process Tabular Data #11, Add AI Search and Doc Intelligence to Admin Settings #27 and Archive Conversations Instead of Permanent Deletion #30 fail (NameErrors in the test's exec namespace). Tests 32–77, one process each at 5933c07: 38 pass, and 7 fail with the same kind of stub drift (NameErrors, a missing stub attribute, an unexpected keyword).test_phase_six_rolling_pool_pauses_dispatch_at_checkpoint_high_waternever finishes on either side: it spins on one core, which is what held the whole file past the timeout. The suite readsfunctions_settings.pyonly as text, for its tabular keys, and imports none of this branch's changed modules directly.test_orchestration_dependency_imports.py11, andtest_orchestration_harness_execution.py649 (+2 xfailed).test_orchestration_turn_recovery_identifiers.py(see Scripts).Playwright (pytest, one process per file): 226 tests, all pass
workflow_id=<created id>, and thatproposalgets no output chip.file_sync, and editing sources makes one Changes-tab row whose Jump lands in File Sync.-O.Node (
node --test): 13 files, 188 tests, all passGuardrails, build and diffs
run_v2_guardrails.py(18dac67..HEAD, 78 changed files) passes all six checks:npm run build(tsc -bandvite build) is clean, built after the last V2 source change (the 3718cca merge). The Playwright runs used that bundle.config.pychanges only .205 → .207, andrelease_notes.mdhas 35 added lines and none removed.Base failures (identical on V2 18dac67, not changed here)
test_orchestration_plan_revision_routes.py::PlanRevisionRouteTests::test_document_removal_is_not_lost_when_editor_openstest_workflow_document_picker_recent_targets.py::test_recent_target_runner_hookstest_broken_access_control_guardrails_checker.py::test_checker_assets_and_version_are_wired_into_repo, which expectsupload-artifact@v4while the workflow pins v7.0.1.test_v2_prompt_attachment_persistence.py(72 failed) andtest_v2_prompt_composer_card.py(2 failed). The failing ids are identical on base; the stubbed namespace lacks names such asprepared_chat_image_references.test_orchestration_turn_recovery_identifiers.py5/6 as a script (image_reference_provenance_from_seedsisn't defined).test_app_settings_auxiliary_writers.py(18), and the 71 sweep files above.test_tabular_row_orchestration_scale.py: 10 failures and one test that never finishes (see the broad sweep).ui_tests/test_v2_workflow_loops.pypasses 72/73 (Playwright, pytest);test_revoked_record_refresh_clears_the_previous_pagefails.test_block_revision_assist.pypasses 7/8 as a script.test_workflow_priority_alerts.pyneeds a Cosmos key. It's one of the 71 sweep files.test_save_failures_retain_flow_fields…[400/409/503]passed in this run.CodeQL
CodeQL reported 9 new alerts at 177e0bc. At 5933c07 it reports 3: the Log Injection alerts below.
Six were in code this branch adds; 5933c07 fixes them, with no behavior change:
functions_workflow_file_sync_sources.py: a lambda that only wrappedget_user_settings(L67), and twoexcept … passblocks with no comment (L93, L106). Skipping there is intended: an active group or public workspace that's unset, gone or not managed by the user contributes no sources, as in the route before the helper moved out of it. The blocks now say so.test_personal_workflow_file_sync_sources.pyL122: a lambda that only wrappeddict.test_v2_orchestration_workflow_proposal_card.pyL32: the plan editor module was imported with bothimportandfrom … import. Onefromimport now brings in the constants and the fixtures.test_workflow_settings_client.jsL54: the stubbedfetchpassed the request to responders that take no arguments. The tests read the recordedrequestsinstead, so the call no longer passes it.Rerun at 5933c07:
-O: personal File Sync sources 22, group File Sync client parity 179, planning context 112, proposal routes 60, imports 6, "Done when" 2;node --test: settings client 11;run_v2_guardrails.py: all six checks pass.Three are Log Injection (medium) at the existing
log_eventsinks infunctions_appinsights.py, which this branch doesn't change:logger.exception(L515),logger.log(L531) and the fallback logger (L553). Each alert lists at least 74 user-provided sources. This branch adds 4 routes and 3 request reads, so it adds sources to existing sinks rather than new sinks. I made no change for these, because the flows are already neutralized in ways CodeQL doesn't model:[SIMPLE_CHAT_LOG_EVENT]. Everything else goes in as structured properties built by_build_logger_extra. That keeps text only for allowlisted diagnostic keys, keeps a*_hashkey only when it's 64 hex characters and a workflow code key only when it's a snake_case code, and reduces every other string to its length.sanitize_log_messagereplaces CR, LF and tab in the message and every property string before anything is emitted, including the console fallback.workflow_log_context, which logs only its SHA-256 hash. Other ids reach the logger properties as lengths only.The new logging sites, and what each logs:
route_backend_orchestration.pyL2789 (the proposal routes' 503 path)functions_orchestration_workflow_proposals.pyL215_log, called at L395, L522, L701, L722, L759, L868, L877 and L928functions_orchestration_workflows.pyL127_log, called at L296, L609, L697, L720, L744 and L759functions_orchestration_workflow_context.pyL715_log_context, called at L753, L778, L800 and L844functions_orchestration_executor.pyL608functions_orchestration_planner.pyL1275functions_orchestration_registry.pyL290This token can't read or dismiss code-scanning alerts (403), so these three need a maintainer's triage.
#1577's CodeQL check lists Log Injection at these same three sink lines, plus L419. 3b matched them to the existing alerts #2551–#2554, which are open on V2 and Development. This branch doesn't change the sink lines, so these are the same alerts, and dismissing #2551–#2554 for #1577 clears them here too. This check passes either way, because they're medium.
Follow-ups
trigger_typegaps the kickoff listed as pre-existing.functions_document_actions↔functions_settingsimport cycle, the stale generated release-notes pages, and the stubbed-namespaceNameErrors behind several base failures listed under Validation.