This is an automated email from the ASF dual-hosted git repository.

jason810496 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 906aab3c2e4 Add  TypeScript SDK capability manifest and compatibility 
matrix (#71754)
906aab3c2e4 is described below

commit 906aab3c2e4a564fdbff7dc3897a6c2a8a507475
Author: Jason(Zhe-You) Liu <[email protected]>
AuthorDate: Wed Aug 26 15:49:31 2026 +0800

    Add  TypeScript SDK capability manifest and compatibility matrix (#71754)
    
    * Add TypeScript SDK capability manifest and compatibility matrix
    
    Co-authored-by: Phani Kumar <[email protected]>
    
    * Report a missing TypeScript supervisor schema constant separately
    
    read_ts_schema_version returned None both when capabilities.yaml disagreed
    with the generated runtime constant and when the constant could not be read
    at all, so a missing or renamed SUPERVISOR_API_VERSION sent the contributor
    to capabilities.yaml, which cannot fix either case. The unreadable case now
    names src/generated/supervisor.ts and the generator instead. Reading the 
file
    also no longer raises when it is absent, so that path reaches the new 
message.
    
    ---------
    
    Co-authored-by: Phani Kumar <[email protected]>
---
 .pre-commit-config.yaml                            |  14 +++
 scripts/ci/prek/update_ts_sdk_readme_matrix.py     | 113 +++++++++++++++++++
 .../ci/prek/test_update_ts_sdk_readme_matrix.py    |  73 +++++++++++++
 ts-sdk/README.md                                   |  52 +++++++++
 ts-sdk/capabilities.yaml                           | 119 +++++++++++++++++++++
 5 files changed, 371 insertions(+)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5278a66716e..5f575d25296 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -295,6 +295,20 @@ repos:
         additional_dependencies: ['PyYAML>=6.0', 'rich>=13.6.0']
         pass_filenames: false
         require_serial: true
+      - id: update-ts-sdk-readme-matrix
+        name: Update the TypeScript SDK compatibility matrix in 
ts-sdk/README.md
+        entry: ./scripts/ci/prek/update_ts_sdk_readme_matrix.py
+        language: python
+        files: >
+          (?x)
+          ^ts-sdk/capabilities\.yaml$|
+          ^ts-sdk/src/generated/supervisor\.ts$|
+          ^ts-sdk/README\.md$|
+          ^scripts/ci/prek/lang_sdk_compat_matrix\.py$|
+          ^scripts/ci/prek/update_ts_sdk_readme_matrix\.py$
+        additional_dependencies: ['PyYAML>=6.0', 'rich>=13.6.0']
+        pass_filenames: false
+        require_serial: true
       - id: check-go-version-in-sync
         name: Check Go toolchain version is consistent across build files
         entry: ./scripts/ci/prek/check_go_version_in_sync.py
diff --git a/scripts/ci/prek/update_ts_sdk_readme_matrix.py 
b/scripts/ci/prek/update_ts_sdk_readme_matrix.py
new file mode 100644
index 00000000000..837ffa59dbe
--- /dev/null
+++ b/scripts/ci/prek/update_ts_sdk_readme_matrix.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# /// script
+# requires-python = ">=3.10,<3.11"
+# dependencies = ["PyYAML>=6.0", "rich>=13.6.0"]
+# ///
+"""Regenerate the TypeScript SDK compatibility table in ``ts-sdk/README.md``.
+
+Renders the Markdown matrix from ``ts-sdk/capabilities.yaml`` between the 
AUTO-GENERATED markers.
+Exits non-zero when the file changed so the contributor re-stages it. The hook 
also verifies that
+the manifest's supervisor schema version matches the generated TypeScript 
runtime constant.
+"""
+
+from __future__ import annotations
+
+import re
+import sys
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent))
+
+from common_prek_utils import console, insert_documentation
+from lang_sdk_compat_matrix import (
+    AIRFLOW_ROOT_PATH,
+    LANG_SDKS,
+    README_MATRIX_FOOTER,
+    README_MATRIX_HEADER,
+    CapabilitiesDoc,
+    load_capabilities,
+    render_markdown_table,
+)
+
+SDK_ID = "ts"
+TS_SUPERVISOR = AIRFLOW_ROOT_PATH / "ts-sdk" / "src" / "generated" / 
"supervisor.ts"
+SCHEMA_VERSION_PATTERN = re.compile(r'^export const SUPERVISOR_API_VERSION = 
"(?P<version>[^"]+)" as const;$')
+
+
+def read_ts_schema_version() -> str | None:
+    """Read ``SUPERVISOR_API_VERSION`` from the generated TypeScript runtime 
source."""
+    if not TS_SUPERVISOR.exists():
+        return None
+    for line in TS_SUPERVISOR.read_text().splitlines():
+        if match := SCHEMA_VERSION_PATTERN.fullmatch(line):
+            return match["version"]
+    return None
+
+
+def check_schema_version(doc: CapabilitiesDoc) -> bool:
+    """Whether the manifest agrees with the generated TypeScript supervisor 
schema version.
+
+    Unlike the Java sibling hook (which treats an unreadable gradle property 
as an implicit pass),
+    an unreadable constant here is deliberately treated as a failure: silently 
skipping the check
+    would let capabilities.yaml drift from the runtime undetected. It is 
reported separately from a
+    genuine mismatch because editing capabilities.yaml cannot fix a missing 
constant.
+    """
+    ts_version = read_ts_schema_version()
+    declared = doc["supervisor_schema_version"]
+    if ts_version is None:
+        console.print(
+            "[red]Could not read SUPERVISOR_API_VERSION from 
ts-sdk/src/generated/supervisor.ts: "
+            "the file is missing, or the generated declaration no longer 
matches this hook's "
+            "pattern. Regenerate it with 'pnpm run generate:supervisor' in 
ts-sdk/ (or update "
+            "SCHEMA_VERSION_PATTERN if scripts/generate-supervisor.mjs changed 
its output). "
+            "Editing ts-sdk/capabilities.yaml cannot fix this.[/]"
+        )
+        return False
+    if ts_version == declared:
+        return True
+    console.print(
+        f"[red]ts-sdk/capabilities.yaml declares supervisor_schema_version 
{declared!r} but "
+        f"src/generated/supervisor.ts SUPERVISOR_API_VERSION is 
{ts_version!r}. "
+        "Update capabilities.yaml to match.[/]"
+    )
+    return False
+
+
+def main() -> int:
+    sdk = next(entry for entry in LANG_SDKS if entry["id"] == SDK_ID)
+    doc = load_capabilities(sdk["capabilities_yaml"], expected_sdk=SDK_ID)
+    if not check_schema_version(doc):
+        return 1
+    changed = insert_documentation(
+        sdk["readme"],
+        render_markdown_table(doc),
+        README_MATRIX_HEADER,
+        README_MATRIX_FOOTER,
+        extra_information="the TypeScript SDK compatibility matrix",
+    )
+    if changed:
+        console.print(
+            "[yellow]Regenerated the TypeScript SDK compatibility matrix in 
ts-sdk/README.md; re-stage it.[/]"
+        )
+        return 1
+    return 0
+
+
+if __name__ in ("__main__", "__mp_main__"):
+    raise SystemExit(main())
diff --git a/scripts/tests/ci/prek/test_update_ts_sdk_readme_matrix.py 
b/scripts/tests/ci/prek/test_update_ts_sdk_readme_matrix.py
new file mode 100644
index 00000000000..57f84edb94f
--- /dev/null
+++ b/scripts/tests/ci/prek/test_update_ts_sdk_readme_matrix.py
@@ -0,0 +1,73 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import pytest
+import yaml
+from ci.prek import lang_sdk_compat_matrix as matrix, 
update_ts_sdk_readme_matrix as hook
+
+SCHEMA_VERSION = "2026-06-16"
+
+
+def _doc() -> dict:
+    def entry(supported: bool) -> dict:
+        return {"supported": supported, "since": "3.3" if supported else None, 
"note": ""}
+
+    return {
+        "sdk": "ts",
+        "supervisor_schema_version": SCHEMA_VERSION,
+        "min_airflow_version": "3.3",
+        "states": {state: entry(True) for state, _ in matrix.STATE_DIMENSIONS},
+        "capabilities": {cap.name: entry(True) for cap in 
matrix.CAPABILITY_DIMENSIONS},
+    }
+
+
+class TestMain:
+    @pytest.fixture
+    def wired(self, tmp_path, monkeypatch):
+        capabilities_yaml = tmp_path / "capabilities.yaml"
+        capabilities_yaml.write_text(yaml.safe_dump(_doc()))
+        readme = tmp_path / "README.md"
+        
readme.write_text(f"intro\n\n{matrix.README_MATRIX_HEADER}\n{matrix.README_MATRIX_FOOTER}\n\noutro\n")
+        ts_supervisor = tmp_path / "supervisor.ts"
+        ts_supervisor.write_text(f'export const SUPERVISOR_API_VERSION = 
"{SCHEMA_VERSION}" as const;\n')
+        monkeypatch.setattr(
+            hook,
+            "LANG_SDKS",
+            [{"id": "ts", "capabilities_yaml": capabilities_yaml, "readme": 
readme}],
+        )
+        monkeypatch.setattr(hook, "TS_SUPERVISOR", ts_supervisor)
+        return readme
+
+    def test_generates_target_then_is_idempotent(self, wired):
+        assert hook.main() == 1
+        content = wired.read_text()
+        assert "| Dimension | Tier | Supported | Since | Notes |" in content
+        assert matrix.SUPPORTED_MARK in content
+        assert content.startswith("intro\n") and content.endswith("outro\n")
+
+        assert hook.main() == 0
+
+    def 
test_schema_version_disagreeing_with_ts_source_fails_without_writing(self, 
wired):
+        hook.TS_SUPERVISOR.write_text('export const SUPERVISOR_API_VERSION = 
"2020-01-01" as const;\n')
+        assert hook.main() == 1
+        assert matrix.README_MATRIX_HEADER + "\n" + 
matrix.README_MATRIX_FOOTER in wired.read_text()
+
+    def test_schema_version_matches_ts_source(self):
+        sdk = next(entry for entry in matrix.LANG_SDKS if entry["id"] == 
hook.SDK_ID)
+        doc = matrix.load_capabilities(sdk["capabilities_yaml"], 
expected_sdk=hook.SDK_ID)
+        assert doc["supervisor_schema_version"] == 
hook.read_ts_schema_version()
diff --git a/ts-sdk/README.md b/ts-sdk/README.md
index 5d90568fc38..65568a5e877 100644
--- a/ts-sdk/README.md
+++ b/ts-sdk/README.md
@@ -214,6 +214,58 @@ current task context when omitted.
 accepts an abort signal so tasks can clean up cooperatively when Airflow
 terminates the task subprocess with SIGTERM or SIGINT.
 
+## Compatibility matrix
+
+Which Airflow TaskInstance states and capabilities this SDK supports. This 
table is generated from
+[`capabilities.yaml`](capabilities.yaml); the conformance dimensions are 
defined in the
+[Language SDK conformance 
spec](https://github.com/apache/airflow/blob/main/contributing-docs/30_new_language_sdk.rst).
+Do not edit the table by hand — update the manifest and run the
+`update-ts-sdk-readme-matrix` prek hook.
+
+<!-- BEGIN AUTO-GENERATED LANG-SDK COMPAT MATRIX -->
+
+*Min. Airflow version: 3.4 · supervisor schema: 2026-10-30*
+
+| Dimension | Tier | Supported | Since | Notes |
+|---|---|---|---|---|
+| **TaskInstance states** |  |  |  |  |
+| state: `success` | MUST | ✓ | 3.4 |  |
+| state: `failed` | MUST | ✓ | 3.4 |  |
+| state: `up_for_retry` | MUST | ✓ | 3.4 | RetryTask |
+| state: `skipped` | SHOULD | ✗ | – | runtime does not emit TaskState skipped 
yet |
+| state: `deferred` | MAY | ✗ | – | runtime does not emit DeferTask yet |
+| state: `up_for_reschedule` | MAY | ✗ | – | runtime does not emit 
RescheduleTask yet |
+| state: `awaiting_input` | MAY | ✗ | – | runtime does not emit AwaitInputTask 
yet |
+| state: `removed` | MAY | ✓ | 3.4 |  |
+| **Runtime capabilities** |  |  |  |  |
+| capability: `mixed-lang-stub-target` | MUST | ✓ | 3.4 | @task.stub |
+| capability: `task-logging` | MUST | ✓ | 3.4 | structured records over the 
log socket |
+| capability: `xcom-read-write` | MUST | ✓ | 3.4 | getXCom / setXCom |
+| capability: `connection-read` | MUST | ✓ | 3.4 | getConnection |
+| capability: `variable-read-write` | MUST | ✗ | – | getVariable only; no 
write over the comm socket yet |
+| capability: `self-contained-bundle` | MUST | ✓ | 3.4 | Airflow metadata 
embedded in the bundle |
+| capability: `retry-policy` | MAY | ✗ | – | no task-facing retry-policy API 
yet |
+| capability: `task-state-store` | MAY | ✗ | – | no task-facing state-store 
API yet |
+| capability: `asset-state-store` | MAY | ✗ | – | no task-facing state-store 
API yet |
+| capability: `asset-event-emit` | MAY | ✗ | – | runtime does not emit asset 
events yet |
+| capability: `asset-event-read` | MAY | ✗ | – | no task-facing asset-event 
API yet |
+| **Native-Dag authoring** |  |  |  |  |
+| capability: `native-dag-authoring` | SHOULD | ✗ | – | native Dag authoring 
not implemented yet |
+| capability: `task-args` | MUST † | n/a | – |  |
+| capability: `dag-params` | MUST † | n/a | – |  |
+| capability: `taskflow-dependencies` | MUST † | n/a | – |  |
+| capability: `branching` | SHOULD † | n/a | – |  |
+| capability: `dag-test` | SHOULD † | n/a | – |  |
+| capability: `task-group` | MAY † | n/a | – |  |
+| capability: `dynamic-task-mapping` | MAY † | n/a | – |  |
+| capability: `asset-inlets-outlets` | MAY † | n/a | – |  |
+| capability: `asset-scheduling` | MAY † | n/a | – |  |
+| capability: `object-store` | MAY † | n/a | – | no object-storage API yet |
+
+*Marks: ✓ supported · ✗ not supported · n/a not applicable. A tier marked † 
applies only when `native-dag-authoring` is supported.*
+
+<!-- END AUTO-GENERATED LANG-SDK COMPAT MATRIX -->
+
 ## Development
 
 ```bash
diff --git a/ts-sdk/capabilities.yaml b/ts-sdk/capabilities.yaml
new file mode 100644
index 00000000000..4972a07fa11
--- /dev/null
+++ b/ts-sdk/capabilities.yaml
@@ -0,0 +1,119 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+---
+sdk: ts
+
+min_airflow_version: "3.4"
+
+# Keep in sync with SUPERVISOR_API_VERSION in src/generated/supervisor.ts. The 
render hook fails
+# if the two disagree.
+supervisor_schema_version: "2026-10-30"
+
+# The runtime terminates a task with SucceedTask, RetryTask, or TaskState 
(failed/removed); it does
+# not yet emit skipped, DeferTask, RescheduleTask, or AwaitInputTask.
+states:
+  success:
+    supported: true
+    since: "3.4"
+  failed:
+    supported: true
+    since: "3.4"
+  up_for_retry:
+    supported: true
+    since: "3.4"
+    note: "RetryTask"
+  skipped:
+    supported: false
+    note: "runtime does not emit TaskState skipped yet"
+  deferred:
+    supported: false
+    note: "runtime does not emit DeferTask yet"
+  up_for_reschedule:
+    supported: false
+    note: "runtime does not emit RescheduleTask yet"
+  awaiting_input:
+    supported: false
+    note: "runtime does not emit AwaitInputTask yet"
+  removed:
+    supported: true
+    since: "3.4"
+
+# Runtime capabilities reflect the task-facing coordinator client surface; 
native-Dag authoring is
+# not implemented yet, so every native capability is unsupported.
+capabilities:
+  mixed-lang-stub-target:
+    supported: true
+    since: "3.4"
+    note: "@task.stub"
+  task-logging:
+    supported: true
+    since: "3.4"
+    note: "structured records over the log socket"
+  xcom-read-write:
+    supported: true
+    since: "3.4"
+    note: "getXCom / setXCom"
+  connection-read:
+    supported: true
+    since: "3.4"
+    note: "getConnection"
+  variable-read-write:
+    supported: false
+    note: "getVariable only; no write over the comm socket yet"
+  self-contained-bundle:
+    supported: true
+    since: "3.4"
+    note: "Airflow metadata embedded in the bundle"
+  retry-policy:
+    supported: false
+    note: "no task-facing retry-policy API yet"
+  task-state-store:
+    supported: false
+    note: "no task-facing state-store API yet"
+  asset-state-store:
+    supported: false
+    note: "no task-facing state-store API yet"
+  asset-event-emit:
+    supported: false
+    note: "runtime does not emit asset events yet"
+  asset-event-read:
+    supported: false
+    note: "no task-facing asset-event API yet"
+  native-dag-authoring:
+    supported: false
+    note: "native Dag authoring not implemented yet"
+  task-args:
+    supported: false
+  dag-params:
+    supported: false
+  taskflow-dependencies:
+    supported: false
+  branching:
+    supported: false
+  dag-test:
+    supported: false
+  task-group:
+    supported: false
+  dynamic-task-mapping:
+    supported: false
+  asset-inlets-outlets:
+    supported: false
+  asset-scheduling:
+    supported: false
+  object-store:
+    supported: false
+    note: "no object-storage API yet"

Reply via email to