Skip to content

Python: Preserve MessageText values during formula preprocessing - #8366

Merged
Jose Alvarez (jpalvarezl) merged 7 commits into
microsoft:mainfrom
jpalvarezl:fix/python-message-text-preprocessing
Sep 15, 2026
Merged

Jose Alvarez (jpalvarezl) merged 7 commits into
microsoft:mainfrom
jpalvarezl:fix/python-message-text-preprocessing

Conversation

@jpalvarezl

@jpalvarezl Jose Alvarez (jpalvarezl) commented Sep 14, 2026 •

Copy link
Copy Markdown
Member

Motivation & Context

Nested MessageText(...) results should remain text when a declarative workflow evaluates the surrounding PowerFx expression. Repeatedly scanning rewritten formula text can process message contents and quoted literals as function calls. Temporary bindings must also preserve the meaning of existing and undefined state references.

Description & Review Guide

  • What are the major changes?
    • Use shared module-level lexical helpers to traverse original expression sections, including PowerFx interpolated strings, while leaving literal text, quoted identifiers, and line/block comments untouched.
    • Pass both short and long MessageText results through temporary state instead of inserting them into formula source.
    • Choose temporary names that avoid existing Local keys and names in the original formula, while retaining cleanup on success and failure.
    • Add preprocessing regressions and real-PowerFx coverage for interpolation boundaries, collisions, missing references, multiple/nested calls, and cleanup, reusing existing coverage rather than duplicating it.
  • What is the impact of these changes?
    • No public API changes. Message values remain data, existing symbols retain their values during evaluation, and undefined references stay undefined.
    • All 55 selected preprocessing, PowerFx, and local YAML workflow tests passed without skips on Python 3.11 with PowerFx 0.0.34 and .NET 10. Python compilation, Ruff lint/format checks, the changed implementation's Pyright check, the declarative test mypy check (20 files), and pre-commit hooks passed. The full unit suite has not been run locally for this update.
  • What do you want reviewers to focus on?
    • Formula scanning and quoting behavior, collision-free temporary bindings, and preservation of evaluation/cleanup semantics.

Related Issue

None.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

Process only original formula text and bind extracted messages through temporary state instead of embedding message content in formula source. Avoid temporary-name collisions and cover literal handling, nested calls, and cleanup regressions.

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

Copilot 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.

🟡 Changes recommended

The scanner can execute calls inside comments and mishandle valid single-quoted identifiers.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Preserves MessageText results as data during Power Fx preprocessing.

Changes:

  • Adds temporary bindings with collision avoidance and cleanup.
  • Prevents rescanning text and double-quoted literals.
  • Expands regression and Power Fx tests.
File summaries
File Description
_declarative_base.py Reworks MessageText preprocessing.
test_declarative_state_path_safety.py Adds preprocessing and cleanup tests.
test_graph_coverage.py Updates short-message expectations.
Review details

Suppressed comments (1)

python/packages/declarative/agent_framework_declarative/_workflows/_declarative_base.py:710

  • This raw substring match also scans Power Fx line comments. For example, 1 // MessageText(1 / 0) is a valid formula whose comment should be ignored, but preprocessing evaluates the commented expression and can fail before Power Fx evaluates 1. Please make comment ranges opaque during scanning so commented-out calls are never executed.
            call_prefix = f"{function_name}("
            if not formula.startswith(call_prefix, cursor):
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@github-actions github-actions Bot 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.

MAF Automated Review — Iteration 1

Result: No findings
Scope: full PR (1 commit(s)): d3bb137c426f
Model: gpt-5.6-sol-fast

Overview

No publishable findings were identified in the reviewed scope.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

Share quoted-token and comment handling between formula scanning and call-boundary matching. Cover identifier escapes and comment boundaries with preprocessing and real-PowerFx regressions, and replace the test append-return lambda with a typed helper for mypy.

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

Jose Alvarez (jpalvarezl) commented Sep 14, 2026 •

Copy link
Copy Markdown
Member Author

Pushed 748365c addressing the quoted-identifier feedback and the comment-handling finding from the review summary, plus the CI mypy error. Local validation: 48 focused tests passed without skips, declarative test mypy passed (20 files), and source type-check, lint/format, compilation, and pre-commit hooks passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assert the rejected sandbox entry is evicted, then drain asynchronous disposal before checking that its output directory is gone. Avoid racing a directory listing against background deletion without changing runtime behavior.

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

@github-actions github-actions Bot 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.

MAF Automated Review — Iteration 2

Result: No findings
Scope: 53 net-new commit(s): b7deabb8bcf0, dcd1e62715ca, 501bd5274cf1, 1b4513dfa2f4, 8a546111de85, 4b2f3a33d53e, 5be4c7896784, c457acaccf19, d7823b2f3343, b9dbe4f801a8, c37de519ba5c, a6eb2991ddcc, 5a8cef940916, 4d173b24007d, eddccc474c07, 3abfddffc556, e4309e5456c4, e1c849c4ad1a, c744b16af97b, 4e020838d701, c1f33dfca3b4, 595aa8a5f262, 249759787350, 119c795cceef, e0162ab4bea0, c47da07e2294, 14b9f1d7e9a4, a096549746f2, e844e8f5a007, 393fbf261844, f30187e974cb, ebaa4033cee9, ff15faf50578, 3ccb3aff1e86, 3c670707766a, df03d32151dc, 1cd06c5a2058, 926b4ecacdaa, b0bfd61c1383, db418ad75a1e, 567f1695711f, 21f6fe72c6e4, 3347c43ea886, 003ae93fd476, ae2876262194, 7abe2ff92b2f, 4d5c63a46a9e, 216e7616c884, 31bf0112506b, 4b4d849602d3, 748365cd5b6f, 7442753aa3f9, 6d8ca2dd1d54
Model: gpt-5.6-sol-fast

Overview

This incremental range replaces the earlier double-quote-specific scan with a shared opaque-token helper that protects quoted identifiers and comments in both scanning passes. Collision checks, finally-based temporary-state restoration, focused PowerFx regressions, and the Hyperlight registry-drain test provide concrete guards around the changed behavior. No Critical, High, or Medium defect introduced by the reviewed range was established.

Reviewed the supplied incremental change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

@moonbox3 Evan Mattson (moonbox3) 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.

Also looks like there's a file conflict we should resolve.

@eavanvalkenburg

Copy link
Copy Markdown
Member

Thanks for the contribution. Before this is ready, could you please follow up on and resolve the remaining discussions at _declarative_base.py:687 and _declarative_base.py:690, and resolve the merge conflicts with main? Once those are addressed, please re-request review.

Revert 6d8ca2d. The cleanup test is now fixed upstream; remove our independent correction before merging main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Traverse only original expression positions so interpolation expressions are preprocessed without reinterpreting literal text or message values. Move quoted-token handling to module scope and add focused regression coverage for the new interpolation contexts.

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

Copy link
Copy Markdown
Member Author

The two remaining discussions are addressed in 15b3427 and resolved, with focused interpolation regressions added. The main-branch conflicts were resolved by 882ea4d; the Hyperlight test now matches upstream and is no longer part of this PR diff. Re-requested review from eavanvalkenburg and moonbox3.

@jpalvarezl
Jose Alvarez (jpalvarezl) added this pull request to the merge queue Sep 15, 2026
Merged via the queue into microsoft:main with commit fe8497a Sep 15, 2026
41 checks passed

This branch was previously deployed

1 inactive deployment
github-app-auth — 15b3427c Deployed Sep 15, 2026 by jpalvarezl via add_label #22871
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants