Skip to content

Merge CSV, Excel, PDF, Word and PowerPoint files in V2 chat and workflows - #1641

Merged
Paul Lizer (paullizer) merged 19 commits into
paullizer-react-v2-uifrom
paullizer-multi-file-merge
Oct 5, 2026
Merged

Paul Lizer (paullizer) merged 19 commits into
paullizer-react-v2-uifrom
paullizer-multi-file-merge

Conversation

@paullizer

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

Copy link
Copy Markdown
Contributor

Summary

People often need many files of one kind turned into one: regional CSVs into one spreadsheet, signed forms into one PDF, chapters into one Word document, team decks into one presentation. V2 couldn't do this, and asking a model to rewrite the files risks changing the data. This PR adds deterministic merging to V2 chat orchestration and V2 workflows. Code does the merge; no model reads or rewrites the files. It was built in seven phases under #1619.

  • Spreadsheets in chat (tabular_merge, tabular_inspect): CSV and Excel files become one CSV or Excel file. Columns match by name or exact order, or are reconciled by union or by an AI-prepared column mapping that code checks before any row is copied. Header rows, every-sheet mode, duplicate removal, sorting and a Source File column are supported. When a request doesn't say, chat asks whether the result should be one sheet or a sheet per file.
  • Documents in chat (document_merge): PDFs into one PDF with a bookmark per file, Word documents into one document, decks into one deck with a section per deck, and spreadsheets into one workbook with a sheet per file. The merge step keeps only a description: the files, options, size and SHA-256. Render (assembled_document_v1) reads the same files again with the user's current access and delivers the file only if it is byte-identical.
  • Workflows: a Merge files task in the V2 workflow editor handles scheduled, synced or large merges. It takes selected files, every matching file, recent files, or the files File Sync changed, up to 100 files and 1,000,000 rows by default. Chat can propose these workflows.
  • Admins: merging is governed by Enable Merge on the Document Action Capabilities card, which has chat and workflow file and row limits, and by the orchestration Capabilities list. Deployments that narrowed that list must add Merge spreadsheets and Merge documents.

Worth a careful look:

  • Hostile files. Word fields that start programs (DDE) are refused. The first document's template link is removed. PowerPoint program and macro actions are removed, as are PDF scripts and actions that open files or programs. functions_ooxml_package_guard.py refuses Office XML parts that declare a DOCTYPE or use an encoding other than UTF-8/16, before any parser reads them. Packages that declare or hide too much uncompressed data are refused. Formula-like cells are neutralized in CSV and written as text in Excel.

  • Access for merged documents. paullizer-react-v2-ui authorizes retained results from their conversation and run. A merged document is the deliberate exception: Render reads the originals again through read_available_document_bytes, which enforces current access and screening. See ORCHESTRATION_OUTPUT_LIFECYCLE.md.

  • Determinism. The same files and options always give the same bytes: ZIP dates are fixed and Word list IDs are derived. A retried workflow therefore reuses the file it already attached.

  • Engine layout. CodeQL found import cycles between functions_document_merge.py and the assemblers it loads lazily. The code the assemblers share now lives in functions_document_merge_core.py. functions_document_merge.py keeps merge_documents and still exports the public names, so its callers didn't change.

  • New dependency. Word merges need docxcompose==2.2.0 (MIT), which brings in Babel (BSD-3-Clause). Office and PDF libraries load only when a merge of that kind runs.

  • Phase 3 differences from V2: Merge multiple files (CSV/Excel, PDF, Word, PowerPoint) through chat orchestration and workflows #1619. These were not built:

    • Per-file checkpoints. A resumed run repeats the deterministic merge instead.
    • "Create & run once".
    • Merge support in the AI workflow assistant.
    • Automatic publishing to a workspace.

    They are listed on V2: Merge multiple files (CSV/Excel, PDF, Word, PowerPoint) through chat orchestration and workflows #1619 as possible follow-ups.

Linked issue

Refs #1619

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

Release notes cover v0.261.237 through v0.261.246 in docs/explanation/release_notes.md. This PR doesn't include a Latest Feature card or screenshot yet.

Version bump

  • application/single_app/config.py VERSION third segment bumped, or not needed because this is docs-only
  • deployers/version.txt bumped, or not needed because deployers/ was not changed

Each change bumped the version:

Version Change
0.261.237 to 0.261.243 Phases 1 to 7
0.261.244 The one-sheet or sheet-per-file question
0.261.245 Merge spools spill into the container's scratch directory
0.261.246 CodeQL fixes: the assemblers' shared code moves to functions_document_merge_core.py, plus small cleanups

deployers/ is unchanged.

This branch is synced with paullizer-react-v2-ui at 25470e7, which published 0.261.236 (#1643), and renumbered above it. If more PRs land there first, it gets synced and renumbered again.

Testing / validation

Unless noted, these ran on 29677f0, the merge with paullizer-react-v2-ui at 25470e7, with Python 3.12 on Windows. application/single_app and functional_tests were on PYTHONPATH, plus the repo root and ui_tests for UI tests.

  • CI: every check passed on a3a98d0, including CodeQL. CodeQL's run on 60130be reported 21 new alerts in this PR's code: import cycles, plus small code-quality findings in the merge modules and tests. a3a98d0 fixed them in code. A later unused-import alert (4001) was fixed in 784b63c. No alert was dismissed or suppressed.
  • Merge, render and lifecycle suites, plus V2: Scroll the chat rail as one panel and pop workflow alerts from the bell #1643's test_v2_sidebar_conversation_scroll.py and the orchestration import allowlist: 979 passed.
    python -m pytest -q -p no:langsmith_plugin -p no:cacheprovider functional_tests/test_file_merge_scratch_dir.py functional_tests/test_file_merge_hardening.py functional_tests/test_document_merge_assembly.py functional_tests/test_document_merge_pdf_workbook.py functional_tests/test_document_merge_docx.py functional_tests/test_document_merge_pptx.py functional_tests/test_tabular_merge_engine.py functional_tests/test_tabular_merge_reconciliation.py functional_tests/test_workflow_merge_task.py functional_tests/test_workflow_merge_pdf_workbook.py functional_tests/test_workflow_merge_word.py functional_tests/test_workflow_merge_powerpoint.py functional_tests/test_orchestration_document_merge_capability.py functional_tests/test_orchestration_tabular_merge_capability.py functional_tests/test_orchestration_tabular_reconciliation.py functional_tests/test_orchestration_output_lifecycle.py functional_tests/test_orchestration_file_render_scratch_dir.py functional_tests/test_orchestration_merge_layout_question.py functional_tests/test_generated_file_structured_renderers.py functional_tests/test_workflow_saved_output_artifacts.py functional_tests/test_v2_sidebar_conversation_scroll.py functional_tests/test_orchestration_dependency_allowlist.py
    
  • On a3a98d0, python -m pytest -q functional_tests/test_m365_runtime_imports.py functional_tests/test_orchestration_dependency_allowlist.py functional_tests/test_document_merge_assembly.py functional_tests/test_workflow_merge_task.py: 141 passed. These cover real runner imports, the orchestration import allowlist, and cold imports of the merge engine without Office or PDF libraries.
  • python functional_tests/test_file_merge_scratch_dir.py: 11 passed. With the two dir=scratch_file_dir() arguments reverted, its 5 scratch-directory cases fail.
  • node --test functional_tests/test_v2_orchestration_merge_arguments.mjs functional_tests/test_v2_workflow_merge_task.mjs functional_tests/test_v2_workflow_proposal_merge.mjs: 25 passed.
  • npm --prefix application/v2_ui run typecheck: passed. Both V2 bundles were rebuilt from this commit:
    • npm --prefix application/v2_ui run build
    • npm --prefix application/v2_ui run build -- --outDir ../../ui_tests/artifacts/orchestration-plan-editor, the bundle the UI tests load.
  • UI tests, each file run with python -m pytest <file> -q: 133 passed.
  • On f8a02a0, V2 workflow alerts: require acknowledgment, repeating sound, size options and team delivery (0.261.235) #1636's functional and route tests, plus the workflow, orchestration, admin and route-policy tests this branch touches: 26 files, each run in its own process. 21 pass, including the three workflow goldens and the route policy inventory. The other 5 fail the same way, test for test, on paullizer-react-v2-ui without this branch:
    • route_tests/test_workflow_alert_acknowledge_policy.py, route_tests/test_workflow_alert_since_hours_policy.py and test_group_workflow_file_sync_client_parity.py: setup errors, because this environment's werkzeug has no __version__.
    • test_workflow_file_sync_prompt_context.py and test_workflow_task_document_actions.py: string assertions against runner source that the target no longer contains.
  • python scripts/build_docs_inventory.py: no inventory changes. python -m pytest -q functional_tests/test_docs_app_surface_coverage.py functional_tests/test_docs_site_quality.py: 13 passed.
  • Regression sweep after syncing with paullizer-react-v2-ui at e1e6949: 465 orchestration, workflow, merge, export, docs and admin test files, run file by file on both branches. There were no new failures:
    • 79 files fail the same way on the target without this branch, mostly for Azure configuration or harness setup.
    • One test races on a shared node_modules cache when shards run in parallel, and passes on its own.
  • Two docs tests still fail, the same way on the target:
    • functional_tests/test_docs_link_integrity.py: 11 broken relative links, none in the merge docs.
    • functional_tests/test_docs_release_notes_integrity.py: the generated release-notes pages are stale.
  • Known issue from V2 workflow alerts: require acknowledgment, repeating sound, size options and team delivery (0.261.235) #1636, not from this PR: ui_tests/test_workflow_alert_classic_acknowledgment.py fails when it runs in the same pytest process after any test that uses pytest-playwright's page fixture. Its harness starts a second sync Playwright, which Playwright refuses ("using Playwright Sync API inside the asyncio loop"). This reproduces on paullizer-react-v2-ui with only its own tests, and the file passes on its own.
  • Not done yet: a live run with a real planner model and Azure storage. The automated tests use scripted models, so these should be tried on a deployment:
    • Chat PDF, Word and PowerPoint merges.
    • The one-sheet question.
    • A 100-file workflow merge.

Documentation

  • Release notes updated, or not needed
  • Feature documentation updated, or not needed
  • Fix documentation updated, or not needed

New docs:

  • docs/explanation/features/V2_FILE_MERGE.md: the umbrella feature doc.
  • V2_FILE_MERGE_PHASE_1_SPREADSHEETS.md through V2_FILE_MERGE_PHASE_7_CHAT_DOCUMENTS.md: one doc per phase. The Phase 4 doc explains the shared core module.
  • docs/guides/merge-files.md: the user guide.

Updated docs:

  • docs/admin/agents-actions.md and docs/admin/orchestration.md.
  • ORCHESTRATION_OUTPUT_LIFECYCLE.md, CHAT_ORCHESTRATION.md and GENERATED_FILE_EXPORT_FRAMEWORK.md.
  • docs/guides/create-a-workflow.md and docs/guides/create-files-with-orchestration.md.

There's no separate fix doc: the bug fixes harden this new feature and are documented in the Phase 7 doc.

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security()). There are no new routes.
  • Settings sent to non-admin frontends use sanitize_settings_for_user(). No settings object is sent: the workflow editor receives only Merge's enabled flag and workflow file limit, and Merge settings are edited on the admin Actions pane.
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS
  • No secrets, keys, connection strings, or local-only artifacts are included

Paul Lizer (paullizer) and others added 13 commits October 2, 2026 19:22
Adds a deterministic tabular_merge Reason capability to V2 chat
orchestration so several same-structure CSV or Excel files can be combined
into one retained table and rendered to CSV or XLSX through render_file.

- functions_tabular_merge.py: pure merge engine (by_name/exact_order
  policies, Source File provenance column, row limits, exact counts)
- functions_orchestration_merge.py: limits, authorized byte loading,
  records-v1/report persistence and failure-code mapping
- Registry, schema, adapter and executor wiring with catalog failure text
- Exact tabular export profiles so CSV/XLSX render keeps every column
- Admin Merge settings (enabled, chat/workflow document and row limits)
- Docs, guides, release notes and functional/UI tests; goldens refreshed

Version 0.261.218

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…refs #1619)

Lets a V2 chat merge CSV and Excel files whose columns differ, and adds a
Gather capability that inspects files before merging.

- Engine: union and mapped policies, column aliases, header row, every-sheet
  mode with a Source Sheet column, exclusion of files or sheets that do not
  fit, duplicate removal (exact rows or key columns, first or last), bounded
  multi-column sort, nullable columns, and tabular inspection
- tabular_inspect (Gather) retains sheets, headers, row counts, samples and a
  compatibility summary without a model
- tabular_column_mapping_v1 compose profile; tabular_merge binds it as a
  "mapping" input and validates it again before code applies it
- Plan validation shares the engine's option rules; a bound mapping must come
  from a compose step using the profile
- Planner recipe and guidance, new catalog failure messages, plan review
  wording for merge and inspection settings
- Fixes the registry capability list test that Phase 1 left stale
- Docs, guide, release notes, functional, .mjs and browser UI tests; goldens
  regenerated and audited

Version 0.261.219

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A workflow task can now merge many CSV and Excel files into one CSV or Excel
file with code: Merge files is a new document action. Its files are chosen
in order, or found at run time (every matching file, recent files, or the
files File Sync changed) and merged in file-name order. Every file is
authorized again, read through the access boundary, merged by the Phase 1-2
engine, rendered by the generated-file export framework and attached to the
run once. No model runs.

- functions_workflow_merge.py executes merges; the runner dispatches merge
  tasks, discovers run-time files, maps merge failures to WorkflowInputError,
  marks merge tasks replay-safe, and keys the artifact by run, task and bytes.
- The merge contract raises reviewed MergeActionErrors that workflow saves
  show by task position; editor options say whether Merge is on and its limit.
- Chat workflow proposals can carry merge tasks, with new repairable draft
  codes; the proposal card describes them as code that runs no model.
- The V2 editor authors merge tasks; the classic editor routes them to V2.
- Version 0.261.220, docs, release notes, and functional and UI tests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A workflow Merge files task now has a merge type. Besides combining rows
(Phase 3), it can join PDFs into one PDF with a bookmark per file, or put
each CSV or Excel file on its own sheet of one Excel workbook. Both use the
same source choices as row merges (selected files in order, every matching
file, recent files, File Sync changed files), authorize every file again,
run with code and no model, and attach one file to the run.

- functions_document_merge.py (+ _pdf, _workbook): pure, bounded document
  merge engine. Only the PDF and workbook assemblers ship in this phase.
- PDF: encrypted files are refused; scripts, form actions, XFA and links
  that open files or programs are removed wherever they appear, keeping
  only navigation (page links, standard page commands, http/https/mailto).
  pypdf keeps every source until the file is written, so workflow PDF
  merges keep the fixed 300 MB input budget.
- Workbook: Excel cell types and number formats are kept, CSV is copied as
  text, formula-like text is never evaluated, and control characters Excel
  can't store are removed and counted.
- The same files always give the same bytes (fixed package dates and ZIP
  metadata), so a replayed task reuses its idempotent artifact.
- Library errors are reported by file name only; a failing cancellation
  check or storage error passes through unchanged so the run can retry.
- functions_workflow_merge.py: shared discovery and authorization, then
  rows (tabular) or files (documents) with per-kind limits; merge_summary
  carries the kind.
- functions_workflow_drafts.py: blueprint merge kind (tabular, workbook,
  pdf), format validation (merge_format_invalid) and option validation
  through the document-action contract; errors never echo input.
- Chat proposals and the V2 editor describe each kind; planner guidance
  covers merge kinds (goldens regenerated, only that bullet changed).
- Docs: Phase 4 feature doc, umbrella phase table (chat document merges
  move to Phase 7), guides, release notes v0.261.221.

Version: 0.261.221

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comparing the workflow, orchestration and merge suites with the pre-merge
baseline (8a802f1) found three regressions from the merge phases, all in
test harnesses that load production code into hand-built namespaces or
stub request-boundary modules:

- test_support/orchestration_research.py: the offline registry runtime now
  seeds TABULAR_COLUMN_MAPPING_PROFILE, which the registry imports since
  Phase 2 (planner failure diagnostics, research selection).
- test_workflow_task_result_handoff.py: the inventory runner namespace
  defines DOCUMENT_ACTION_TYPE_MERGE, which _execute_workflow_dispatch
  checks for every task since Phase 3 (repeat dispatcher and M365 repeat
  checkpoint tests).
- test_workflow_repeat_editor_options.py: stubs functions_document_actions,
  which get_workflow_editor_options imports since Phase 3 for the Merge
  files task options, and checks the merge projection.

All 107 compared files now match the baseline.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A workflow Merge files task can now use "Combine Word documents" as its
merge type: Word documents are appended, in order, into one .docx with
code and no model, choosing files the same four ways as every merge.

- functions_document_merge_docx.py: docxcompose-based assembler. The
  first document is the base (page setup, headers, footers); later bodies
  keep their styles, numbering, images, tables and footnotes. Formatting
  keeps each document's look (clashing styles copied under new names) or
  uses the first document's; page breaks and file-name headings are
  optional; orphaned comment anchors are removed and reported.
- Deterministic output (fixed modified date + normalized package), the
  result is re-opened before delivery, library errors name only the file,
  and cancellation-check or storage failures pass through for retry.
- docx enabled in MERGE_KINDS_AVAILABLE, DOCUMENT_MERGE_KINDS and the V2
  editor; Word merges read at most 300 MB (fixed in-memory budget).
- Chat proposals: blueprint kind docx with formatting, page_breaks and
  source_headings; the merge_options_invalid hint lists each kind's
  options; planner guidance and goldens updated (merge bullet only);
  proposal card wording for Word.
- requirements.txt: docxcompose==2.2.0 (MIT; pulls in Babel, BSD-3).
- Tests: Word assembler (determinism, failures), Word workflow tasks,
  editor authoring in a browser, proposal parsing and wording; PowerPoint
  is now the kind that isn't available yet.
- Docs: Phase 5 feature doc, umbrella, guides, release notes v0.261.222.

Version: 0.261.222

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A workflow Merge files task can now use "Combine PowerPoint decks" as its
merge type: the slides of PowerPoint decks are appended, in order, into one
.pptx with code and no model. Every merge type is now available.

- functions_document_merge_pptx.py: package-level assembler. Slides keep
  their pictures, media, charts with embedded workbooks, diagrams, tables
  and notes; keep_source brings layouts, masters and themes (identical ones
  reused), use_first places slides on the first deck's matching layouts;
  one section per deck; IDs stay unique and unselected slides leave no
  orphaned parts; python-pptx re-opens the result. The first deck decides
  the slide size; differing sizes, embedded fonts, comments and linked
  content are reported. Encrypted, damaged, oversized and macro-enabled
  decks are refused.
- Deterministic output: fixed ZIP entries (fixed_zip_entry, now shared
  with normalized_package) and derived section IDs instead of uuid4.
- Per-deck and final-write wrappers report library errors by file name
  only; cancellation-check and storage failures pass through for retry.
- pptx enabled in MERGE_KINDS_AVAILABLE (now every kind),
  DOCUMENT_MERGE_KINDS and the V2 editor; up to 2,000 slides, 300 MB of
  decks.
- Chat proposals: blueprint kind pptx with formatting and sections;
  planner guidance and goldens updated (merge bullet only); proposal card
  wording for PowerPoint.
- Tests: PowerPoint assembler (determinism, failures), PowerPoint workflow
  tasks, editor authoring in a browser, proposal parsing and wording, and a
  withheld kind still refused by the contract, the merge and the editor.
- Docs: Phase 6 feature doc, umbrella, guides, release notes v0.261.223.

Version: 0.261.223

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
V2 chat orchestration can now join whole documents in a chat turn, without
a workflow. A new Reason capability, document_merge ("Merge documents"),
merges PDFs, Word documents or PowerPoint decks into one file, or puts CSV
and Excel files on separate sheets of one workbook, with the same
deterministic engine workflow merges use. No model reads the files.

The merge step assembles the authorized files once to check them and
retains a document_assembly_v1 description (kind, options, files in order,
the checked file's size and SHA-256), never the bytes. render_file with the
new assembled_document_v1 profile reads only the merge result's own lineage
documents, with access checked again after every read, assembles them
again, and delivers the file only when it is byte-identical; otherwise it
fails as output_source_changed and nothing is uploaded. Plans must name the
kind, use only that kind's settings and render in the merge's own format.

Hardening for every merge:
- Word documents with DDE/DDEAUTO fields are refused, however the field
  code is split, nested, cased or encoded; the first document's template
  link is removed and linked content is reported.
- PowerPoint ppaction://program and ppaction://macro actions are removed
  from every deck, including the first, in every part declared as Office
  XML whatever its name or encoding.
- Office packages with an XML part that declares a document type or is
  written or declared in another encoding than UTF-8/UTF-16 are refused
  before any library parses them (new functions_ooxml_package_guard.py),
  in document and spreadsheet merges. Parts are chosen by name and
  declared content type; only prologs are read (4 KiB per part, 32 MiB
  per package), with cancellation checks.
- Word lists copied from later documents get derived IDs instead of
  docxcompose's random ones, so Word merges with lists are byte-identical
  (also fixes repeated workflow Word merges attaching a second copy).
- A storage fault while Render re-reads a merged file's originals stays
  retryable; _authorize's source-failure translation is shared with the
  new reader.
- Tests cover cross-process byte-identical re-assembly, 100 files of 1,000
  rows in one workflow run, formula-free CSV/XLSX output, ZIP size lies,
  cold imports, and delivery through the real rendering service.

Also: Merge documents in the admin capability list, plan card wording,
planner guidance (workflows only for scheduled, synced or very large
merges), regenerated planner goldens, Phase 7 feature doc, guide, admin
docs and release notes. Version 0.261.224.

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

Several CSV or Excel files merged into one Excel file can mean every row
on one sheet (tabular_merge) or each file on its own sheet (document_merge
kind workbook). The planner used to assume one sheet. It now asks, with
exactly two choices, "All rows on one sheet" and "Each file on its own
sheet", when the request doesn't decide the layout.

- build_deliverable_availability adds MERGE_LAYOUT_FACT only while
  tabular_merge, document_merge and render_file are all offered, so the
  planner never asks a question whose answer it can't deliver.
- It doesn't ask when CSV output, wording (stack, one table, a sheet per
  file, separate sheets), a saved preference or an earlier answer decides
  it; when the user declines, rows go on one sheet and the plan says so.
- The general clarification rule now names its exceptions (capability
  guidance, deliverables facts, workflow instructions) while still
  preferring stated assumptions otherwise.
- Workflow merge proposals ask the same question with the same choices.
- New functional test drives the real planner with a scripted model;
  planner goldens regenerated (only the two intended text changes).
- Guide, Phase 7 and umbrella feature docs, admin orchestration page and
  release notes updated. Version 0.261.225.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
paullizer-react-v2-ui published v0.261.218 through v0.261.232 for nine
merged PRs while this branch used v0.261.218 through v0.261.225 for the
V2 file merge phases, so config.py and the release notes collided.

The integration branch's sections are kept exactly as published. This
branch's eight sections shift up fifteen, to v0.261.233 through
v0.261.240, and config.py becomes 0.261.240. Version references in this
branch's code headers, tests and documentation move with them; only
lines this branch added were renumbered, and every other change in the
renumbering is checked to be a version number.

The integration branch now authorizes a retained result from its
conversation and run without rereading its source documents. A merged
document is assembled from its original files when it renders, so those
files are still read with the user's current access, and only identical
bytes are delivered. Two lifecycle tests now pin that: a file the user
can no longer open fails the render, and a new version with the same
bytes is still delivered. The Phase 7 feature doc and the output
lifecycle doc describe the exception.

Conflicts: config.py and the release notes (renumbered), the output
lifecycle test header, and the workflow proposal card UI test (each side
added one test; both are kept).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
While this branch was being synced, paullizer-react-v2-ui merged #1626
and #1633 and published v0.261.233, which this branch had just taken for
its first merge phase.

The integration branch's sections are kept exactly as published. This
branch's eight sections shift up one, to v0.261.234 through v0.261.241,
and config.py becomes 0.261.241. Every file only this branch changed is
checked to equal its previous content with those versions shifted, and
the release notes are the integration branch's file plus this branch's
eight sections.

functions_structured_file_renderers.py conflicted on imports only: the
exact-tabular profiles import from this branch and the scratch directory
import from the integration branch are both kept.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
paullizer-react-v2-ui 0.261.233 (#1623) gave short-lived server files a
dedicated location: scratch_file_dir() returns /sc-temp-files, which the
image creates for its non-root user, when the process can write to it,
and None, the platform temp directory, otherwise. File renders and
generated-file downloads use it.

The merge engines' spools didn't. A merged document over 16 MiB, or a
spreadsheet merge's rows over 8 MiB, spilled into the platform temp
directory (/tmp in the image). That works, but sits outside the
directory the image provides. new_output_spool(), which every document
assembler uses, and the tabular _RowSpool now pass
dir=scratch_file_dir(). Nothing else changes; openpyxl still keeps its
own write-only sheet files in the platform temp directory and removes
them once written.

test_file_merge_scratch_dir.py makes every spool spill on its first
write and records where tempfile creates each file: the scratch
directory when it exists, the platform default when it doesn't, for
spreadsheet merges and PDF, Word, PowerPoint and workbook merges, with
the same result as an in-memory merge. Without this change the five
scratch-directory cases fail.

Refs #1619

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
paullizer-react-v2-ui merged #1635 and published v0.261.234, which this
branch used for Phase 1.

The integration branch's sections are kept exactly as published. This
branch's nine sections shift up one, to v0.261.235 through v0.261.243,
and config.py becomes 0.261.243. 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 unchanged, and the release
notes are the integration branch's file plus this branch's nine
sections.

test_workflow_task_result_handoff.py conflicted on its header only. It
keeps #1635's "Harness dependencies restored in: 0.261.234" line with
this branch's Version, now 0.261.238, and both harness changes: #1635's
publication policy and schedule rules, and this branch's merge document
action constant. It now passes. functions_workflow_runner.py merged
cleanly: #1635 rewords saved-result failures in
_execute_workflow_task_sequence, apart from this branch's merge task.

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

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

Refs #1619

Split shared document merge primitives into a cycle-free core module and clean up CodeQL findings in merge tests and workbook handling.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread application/single_app/functions_document_merge_core.py Fixed
Paul Lizer (paullizer) and others added 4 commits October 5, 2026 14:24
0.261.244 moved the code the PDF, Word, PowerPoint and workbook
assemblers share into functions_document_merge_core.py to clear
CodeQL's import-cycle alerts. The umbrella, Phase 4 and Phase 7 docs
still described functions_document_merge.py as holding all of it.
They now say what moved and why, and that callers are unchanged.

The v0.261.244 release note now describes the change in the repo's
usual terms rather than as a list of alert fixes, and says merges
behave exactly as before.

Docs only, so the version stays 0.261.244.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CodeQL (alert 4001) found that functions_document_merge_core.py imports
typing.Sequence without using it. It came along when the shared code
moved out of functions_document_merge.py, but merge_documents, the only
function that uses it, stayed in functions_document_merge.py. No other
merge module has an unused import.

This completes the 0.261.244 CodeQL cleanup, so the version is
unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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>
paullizer-react-v2-ui merged #1643 (V2 sidebar conversation scroll) and
published v0.261.236, 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.237 through v0.261.246,
and config.py becomes 0.261.246. 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. None of the integration branch's own text in this branch's
files used the shifted versions.

Only config.py and the release notes changed on both sides, and both
conflicted on versions only.

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
V2 reached 0.261.238 when #1644 merged, so this branch moves one above it.
Sets config.py VERSION to 0.261.239 and moves this branch's own 0.261.238
lines to 0.261.239: the hand-off modules' and tests' Version, Implemented in,
MINIMUM_VERSION and assert_app_version_at_least literals, the two route-test
coverage notes, the run adapter test's hand-off refusal note, the two
hand-off rows in docs/admin/orchestration.md, the feature doc and this
branch's release-notes header. #1644's own 0.261.238 lines (its schema
docstring, its Microsoft 365 section and troubleshooting row in
orchestration.md, its fix docs and its release-notes section) are unchanged.
The open V2 PRs claim 0.261.234 (#1639), 0.261.235 (#1637), 0.261.236
(#1638) and 0.261.246 (#1641), none of them 0.261.239.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
paullizer-react-v2-ui merged #1644 (orchestration retained-result and
Microsoft 365 action fixes) and published v0.261.237 and v0.261.238,
which this branch used for Phases 1 and 2.

The integration branch's sections are kept exactly as published. This
branch's ten sections shift up two, to v0.261.239 through v0.261.248,
and config.py becomes 0.261.248. 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.

Five files changed on both sides. config.py and the release notes
conflicted on versions only. functions_orchestration_adapters.py,
functions_orchestration_schema.py and docs/admin/orchestration.md
merged cleanly; in the admin page only this branch's five lines about
its own versions were shifted, and #1644's lines about 0.261.237 and
0.261.238 are kept. #1644's new failure codes and build_failure
argument are additive and don't touch the merge capabilities.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit a5a5b1c into paullizer-react-v2-ui Oct 5, 2026
11 checks passed
Paul Lizer (paullizer) added a commit that referenced this pull request Oct 6, 2026
Merge only landed V2 with rerere disabled. Preserve both capability-import sets, both draft error families, all incoming release-note sections and the three V2 off-golden fixtures. Keep V2 VERSION 0.261.248 pending the separate hand-off renumber to 0.261.250. Auto-merged shared files preserve both sides; executor registry imports are their exact union. The regenerated docs inventory is unchanged. Full verification remains pending.

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
V2 reached 0.261.248 with #1641; coordinator reserves 0.261.249 for 6b-2 and 0.261.250 for Phase 7a. Change only config.py VERSION and the 44 PR-owned version lines. Preserve every incoming V2 version reference and golden fixture. No behavior changes.

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
Preserve both proposal-test histories and every V2 release-note section. The version bump follows separately.

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
Keep all base version history; update only 6b-2's version, tests and documentation after the V2 microsoft#1641 merge.

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
test_the_phase_4_blueprint_and_payloads_are_unchanged failed at V2
15feec6 on the schema digest alone. Its pin (ab12fb1d) predated microsoft#1641,
which added the merge task schema and was merged into Phase 7a at
b8e4730 without a refresh.

The pin now holds 520139cb, the value V2 computes at a5a5b1c, after microsoft#1641
and before hand-off merged, so the test still proves hand-off left the
Phase 4 schema unchanged. The payload, validation and dry-run pins are
unchanged.

The fix doc adds the builder test to Files modified, records the pin under
Validation, and gives the 200-document read time as about 1.7 seconds, to
match the c07b911 timings.

Refs microsoft#1549, microsoft#1543. Follow-up to microsoft#1640.

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.

2 participants