This is an automated email from the ASF dual-hosted git repository.
wenjin272 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-agents.git
The following commit(s) were added to refs/heads/main by this push:
new bc55d97e [infra] Add a Python-Java bridge review guide (#957)
bc55d97e is described below
commit bc55d97e6a1f4a4302d18b1070e4f1dcad5d2f40
Author: Weiqing Yang <[email protected]>
AuthorDate: Tue Aug 4 04:11:36 2026 -0700
[infra] Add a Python-Java bridge review guide (#957)
---
code_review.md | 2 +-
review-guides/python-java-bridge.md | 54 +++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/code_review.md b/code_review.md
index f78e7bd6..3d4e6bdf 100644
--- a/code_review.md
+++ b/code_review.md
@@ -40,7 +40,7 @@ Guides load on demand, so the general passes here stay short.
| Change type | Focus | Guide |
|---|---|---|
| `runtime/` state and recovery | serde and replay type fidelity, real
failure-path tests |
[review-guides/runtime-state-recovery.md](review-guides/runtime-state-recovery.md)
|
-| Python-Java bridge | cross-language parity, type mapping across Pemja |
planned |
+| Python-Java bridge | cross-language parity, type mapping across Pemja |
[review-guides/python-java-bridge.md](review-guides/python-java-bridge.md) |
| `api/` contract | API shape, compatibility policy, deprecation | planned |
| `dist` and dependency | shading, LICENSE and NOTICE, dist registration |
planned |
| docs-only | facts match their source of truth | planned |
diff --git a/review-guides/python-java-bridge.md
b/review-guides/python-java-bridge.md
new file mode 100644
index 00000000..685a1988
--- /dev/null
+++ b/review-guides/python-java-bridge.md
@@ -0,0 +1,54 @@
+# Review Guide: Python-Java Bridge
+
+Load this guide when a PR changes code that crosses the Python-Java boundary:
+Pemja entry points, resource or tool wrappers, event and agent-plan
+serialization, or type conversion in either direction. It narrows the full
+passes in `code_review.md` to the ones that matter most for this area; the
+general passes still apply.
+
+## Focused checklist
+
+- When a method lands on a type that exists in both languages, check every
+ wrapper carrying it across, not only the two implementations. A wrapper
+ inheriting the other side's implementation can fail the call instead of
+ crossing it, and one left on the legacy path degrades silently.
+- Settle what an explicitly null declarative argument means. A Java descriptor
+ lookup cannot distinguish an absent argument from one declared null, while
+ Python can, so the same YAML can reach a different conclusion on each side.
+- Keep constants shared by both languages in sync: event type strings, resource
+ types, YAML aliases, flattened-map keys. A new event type or attribute also
+ needs the cross-language snapshots regenerated and committed on both sides.
+- Confirm both legs of a conversion carry the same fields. An argument present
+ on one leg and missing on the other drops data with no error, and the legs
+ usually live in different files.
+- Treat bridge entry-point names as a contract. Python function names called
+ from Java and Java fully-qualified names resolved from Python are string
+ literals, so renaming or moving either breaks only at runtime.
+- Keep values that cross the boundary flattened to primitives, strings, lists,
+ and maps. Returning an arbitrary object in either direction to a call that
+ originated on a non-main interpreter thread can crash the JVM, which is why
+ the existing conversions return flat maps.
+
+## Validation
+
+Run both language lanes. A bridge change verified on one side only is untested.
+
+- Java: `mvn --batch-mode test -pl runtime -am`. The `-am` matters here because
+ the Java halves of the cross-language snapshot tests live in `api` and
+ `plan`, upstream of the module that owns the bridge implementations.
+- Python: from `python/`, run `uv sync --extra test`, install the
+ `apache-flink` release for the Flink version under test (`tools/ut.sh` names
+ the supported versions), then `uv run --no-sync pytest flink_agents/runtime
+ flink_agents/api flink_agents/plan`. PyFlink is not a declared test
+ dependency and the event types import it, so collection fails without it.
+
+Together these run the committed cross-language snapshot tests from both sides.
+Dispatch through a real interpreter is only covered by the cross-language
+end-to-end modules.
+
+## Examples from past reviews
+
+| Case | Pass it exercises | Review |
+|---|---|---|
+| A usage-tracking method reached both setup types but not the wrappers, so
each inherited an implementation its connection cannot serve: the Python-backed
setup never initializes the Java connection, the Java-backed one holds only a
resource name. Calls failed instead of crossing, and the connection wrappers
fell back to the legacy call, returning no usage. | Whether every wrapper
carrying a call across the boundary was updated, including result conversion
and cross-language tests. | [# [...]
+| An explicitly configured null `structured_output_strategy` was normalized to
`AUTO` on the Java side, while Python rejected `None` with a validation error.
| Comparing the behavior each language derives from the same declarative value.
|
[#843](https://github.com/apache/flink-agents/pull/843#discussion_r3637512045) |