Skip to content

fix(runtime-work): stabilize local task flow - #1552

Closed
FicoHu wants to merge 2 commits into
wecode-ai:mainfrom
FicoHu:codex/runtime-local-task-flow
Closed

FicoHu wants to merge 2 commits into
wecode-ai:mainfrom
FicoHu:codex/runtime-local-task-flow

Conversation

@FicoHu

@FicoHu FicoHu commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Refactor
    • Updated several internal implementations for consistency and readability.
    • No user-facing behavior, workflow, or output changes were introduced.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a261d4f0-cdb9-4dde-95ea-e8b1126e2c7a

📥 Commits

Reviewing files that changed from the base of the PR and between 101c44f and a5f4aca.

📒 Files selected for processing (3)
  • executor/runtime_work/codex_discovery.py
  • executor/runtime_work/codex_global_state.py
  • executor/runtime_work/rpc_handler.py
✅ Files skipped from review due to trivial changes (1)
  • executor/runtime_work/rpc_handler.py

📝 Walkthrough

Walkthrough

This PR only reformats several expressions and comprehensions in runtime Codex discovery, global state loading, and RPC handler code. No control flow, data shape, or returned values change.

Changes

Runtime formatting cleanup

Layer / File(s) Summary
Expression wrapping and lookup formatting
executor/runtime_work/codex_discovery.py, executor/runtime_work/codex_global_state.py, executor/runtime_work/rpc_handler.py
Return expressions, dictionary comprehensions, a conditional metadata assignment, and a record replace(...) call are wrapped across multiple lines without changing behavior.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Possibly related PRs

  • wecode-ai/Wegent#1547: Touches the same runtime Codex and RPC handler paths, including the files updated here.

Suggested reviewers

  • Micro66
  • feifei325

Poem

A bunny hopped by with a pen so neat,
and wrapped those lines to a gentler beat.
No logic changed, just a tidier tree,
with whiskers twitching in code harmony.
🐇✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title suggests a behavioral fix for local task flow, but the changes are only formatting and no logic changes. Use a title that reflects the actual scope, such as formatting updates in runtime-work files.
Docstring Coverage ⚠️ Warning Docstring coverage is 3.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wework/src/features/workbench/WorkbenchProvider.tsx (1)

2356-2375: 🩺 Stability & Availability | 🟡 Minor

Verify stream event filtering doesn't drop early events when localTaskId changes.

The isCurrentLocalTaskEvent filter requires payload.local_task_id to match currentRuntimeTaskRef.current.localTaskId. Since currentRuntimeTaskRef is only updated after createRuntimeTask resolves, any stream events arriving with the new device-confirmed localTaskId before this update occurs will be rejected, potentially losing onChatStart or initial onChatChunk events.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/features/workbench/WorkbenchProvider.tsx` around lines 2356 -
2375, The stream-event filter can drop early events because
currentRuntimeTaskRef.current is only updated after createRuntimeTask resolves,
so isCurrentLocalTaskEvent may reject payloads carrying the new localTaskId too
soon. Update the task identity earlier in the createRuntimeTask flow, or relax
the filter to accept the pending optimistic address until the confirmed address
is dispatched, using the existing currentRuntimeTaskRef, optimisticAddress, and
isCurrentLocalTaskEvent logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@executor/runtime_work/codex_discovery.py`:
- Around line 876-885: The _normalize_local_image_path helper is rejecting valid
Windows drive-letter paths because urlparse treats the drive letter as a scheme;
update the scheme validation so it only filters out real URLs by rejecting
schemes longer than one character, while still allowing single-letter drive
paths like C:/... to pass through. Keep the existing normalization flow in
_normalize_local_image_path and adjust only the parsed.scheme check accordingly.

---

Outside diff comments:
In `@wework/src/features/workbench/WorkbenchProvider.tsx`:
- Around line 2356-2375: The stream-event filter can drop early events because
currentRuntimeTaskRef.current is only updated after createRuntimeTask resolves,
so isCurrentLocalTaskEvent may reject payloads carrying the new localTaskId too
soon. Update the task identity earlier in the createRuntimeTask flow, or relax
the filter to accept the pending optimistic address until the confirmed address
is dispatched, using the existing currentRuntimeTaskRef, optimisticAddress, and
isCurrentLocalTaskEvent logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a01bdcea-6e0a-4f75-94e8-7f2c3a917444

📥 Commits

Reviewing files that changed from the base of the PR and between b30c562 and 101c44f.

📒 Files selected for processing (18)
  • backend/app/schemas/runtime_work.py
  • backend/app/services/runtime_work_service.py
  • backend/tests/services/test_runtime_work_service.py
  • docs/en/developer-guide/runtime-local-work.md
  • docs/zh/developer-guide/runtime-local-work.md
  • executor/runtime_work/codex_discovery.py
  • executor/tests/runtime_work/test_local_task_store.py
  • wework/src/components/chat/blocks/ToolBlockItem.tsx
  • wework/src/components/chat/blocks/ToolBlocksDisplay.test.tsx
  • wework/src/components/chat/blocks/ToolBlocksDisplay.tsx
  • wework/src/components/chat/blocks/toolBlockActivity.ts
  • wework/src/components/layout/DesktopWorkbenchLayout.tsx
  • wework/src/components/layout/DesktopWorkbenchMain.tsx
  • wework/src/components/layout/MobileWorkbenchLayout.tsx
  • wework/src/features/workbench/WorkbenchProvider.test.tsx
  • wework/src/features/workbench/WorkbenchProvider.tsx
  • wework/src/pages/WorkbenchPage.tsx
  • wework/src/types/api.ts

@coderabbitai coderabbitai 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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wework/src/features/workbench/WorkbenchProvider.tsx (1)

2356-2375: 🩺 Stability & Availability | 🟡 Minor

Verify stream event filtering doesn't drop early events when localTaskId changes.

The isCurrentLocalTaskEvent filter requires payload.local_task_id to match currentRuntimeTaskRef.current.localTaskId. Since currentRuntimeTaskRef is only updated after createRuntimeTask resolves, any stream events arriving with the new device-confirmed localTaskId before this update occurs will be rejected, potentially losing onChatStart or initial onChatChunk events.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/features/workbench/WorkbenchProvider.tsx` around lines 2356 -
2375, The stream-event filter can drop early events because
currentRuntimeTaskRef.current is only updated after createRuntimeTask resolves,
so isCurrentLocalTaskEvent may reject payloads carrying the new localTaskId too
soon. Update the task identity earlier in the createRuntimeTask flow, or relax
the filter to accept the pending optimistic address until the confirmed address
is dispatched, using the existing currentRuntimeTaskRef, optimisticAddress, and
isCurrentLocalTaskEvent logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@executor/runtime_work/codex_discovery.py`:
- Around line 876-885: The _normalize_local_image_path helper is rejecting valid
Windows drive-letter paths because urlparse treats the drive letter as a scheme;
update the scheme validation so it only filters out real URLs by rejecting
schemes longer than one character, while still allowing single-letter drive
paths like C:/... to pass through. Keep the existing normalization flow in
_normalize_local_image_path and adjust only the parsed.scheme check accordingly.

---

Outside diff comments:
In `@wework/src/features/workbench/WorkbenchProvider.tsx`:
- Around line 2356-2375: The stream-event filter can drop early events because
currentRuntimeTaskRef.current is only updated after createRuntimeTask resolves,
so isCurrentLocalTaskEvent may reject payloads carrying the new localTaskId too
soon. Update the task identity earlier in the createRuntimeTask flow, or relax
the filter to accept the pending optimistic address until the confirmed address
is dispatched, using the existing currentRuntimeTaskRef, optimisticAddress, and
isCurrentLocalTaskEvent logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a01bdcea-6e0a-4f75-94e8-7f2c3a917444

📥 Commits

Reviewing files that changed from the base of the PR and between b30c562 and 101c44f.

📒 Files selected for processing (18)
  • backend/app/schemas/runtime_work.py
  • backend/app/services/runtime_work_service.py
  • backend/tests/services/test_runtime_work_service.py
  • docs/en/developer-guide/runtime-local-work.md
  • docs/zh/developer-guide/runtime-local-work.md
  • executor/runtime_work/codex_discovery.py
  • executor/tests/runtime_work/test_local_task_store.py
  • wework/src/components/chat/blocks/ToolBlockItem.tsx
  • wework/src/components/chat/blocks/ToolBlocksDisplay.test.tsx
  • wework/src/components/chat/blocks/ToolBlocksDisplay.tsx
  • wework/src/components/chat/blocks/toolBlockActivity.ts
  • wework/src/components/layout/DesktopWorkbenchLayout.tsx
  • wework/src/components/layout/DesktopWorkbenchMain.tsx
  • wework/src/components/layout/MobileWorkbenchLayout.tsx
  • wework/src/features/workbench/WorkbenchProvider.test.tsx
  • wework/src/features/workbench/WorkbenchProvider.tsx
  • wework/src/pages/WorkbenchPage.tsx
  • wework/src/types/api.ts
🛑 Comments failed to post (1)
executor/runtime_work/codex_discovery.py (1)

876-885: 🎯 Functional Correctness | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm urlparse treats a Windows drive letter as a scheme
python3 - <<'PY'
from urllib.parse import urlparse
for p in ("C:/Users/me/img.png", r"C:\Users\me\img.png", "/abs/img.png", "file:///C:/img.png"):
    print(repr(p), "-> scheme=", repr(urlparse(p).scheme))
PY

Repository: wecode-ai/Wegent

Length of output: 299


Local Windows paths are incorrectly rejected, causing missing image previews.

urlparse interprets the drive letter in C:/path as a scheme (c), causing the current check parsed.scheme != "file" to reject valid local paths. Update the check to only block schemes longer than a single character (standard URLs) to preserve Windows drive-letter handling.

     parsed = urlparse(path)
-    if parsed.scheme and parsed.scheme != "file":
+    # Single-letter schemes are Windows drive letters (e.g., "C:...").
+    if len(parsed.scheme) > 1 and parsed.scheme != "file":
         return None
     return path
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

def _normalize_local_image_path(value: Any) -> Optional[str]:
    if not isinstance(value, str):
        return None
    path = value.strip()
    if not path:
        return None
    parsed = urlparse(path)
    # Single-letter schemes are Windows drive letters (e.g., "C:...").
    if len(parsed.scheme) > 1 and parsed.scheme != "file":
        return None
    return path
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@executor/runtime_work/codex_discovery.py` around lines 876 - 885, The
_normalize_local_image_path helper is rejecting valid Windows drive-letter paths
because urlparse treats the drive letter as a scheme; update the scheme
validation so it only filters out real URLs by rejecting schemes longer than one
character, while still allowing single-letter drive paths like C:/... to pass
through. Keep the existing normalization flow in _normalize_local_image_path and
adjust only the parsed.scheme check accordingly.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@executor/runtime_work/codex_discovery.py`:
- Around line 393-402: The transcript cache cleanup is using a different key
than the one used by read_transcript_page(), so deleted pages can remain cached
for relative or symlinked paths. Update the deletion loop in codex_discovery.py
to remove entries from _transcript_cache using the same str(path) key shape that
read_transcript_page() uses, rather than only the resolved deleted_path returned
by _delete_codex_owned_file(). Keep the existing deletion flow in the candidate
loop, but ensure the cache pop targets the original session path key as well so
stale transcript pages are fully cleared.
- Around line 338-341: Validate the thread ID in unarchive_thread() before
calling thread_unarchive by using the same _required_thread_id() helper that
archive_thread() and rename_thread() use. This keeps blank or whitespace-only
IDs from reaching the Codex SDK and makes unarchive_thread() consistent with the
other thread operations. Keep the fix localized to unarchive_thread() and
preserve the existing client/context flow.

In `@executor/runtime_work/codex_global_state.py`:
- Around line 279-300: Serialize the read-modify-write in
_update_global_state_payload so concurrent ensure_* / rename_* / remove_* calls
cannot overwrite each other. Add a lock around the full sequence that reads with
_read_global_state_payload, mutates, writes the temp file, and calls os.replace,
so the atomic swap is protected by mutual exclusion as well. Use the
_update_global_state_payload helper as the main place to introduce the lock and
keep the existing temporary-file replace flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a261d4f0-cdb9-4dde-95ea-e8b1126e2c7a

📥 Commits

Reviewing files that changed from the base of the PR and between 101c44f and a5f4aca.

📒 Files selected for processing (3)
  • executor/runtime_work/codex_discovery.py
  • executor/runtime_work/codex_global_state.py
  • executor/runtime_work/rpc_handler.py
✅ Files skipped from review due to trivial changes (1)
  • executor/runtime_work/rpc_handler.py

@coderabbitai coderabbitai 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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@executor/runtime_work/codex_discovery.py`:
- Around line 393-402: The transcript cache cleanup is using a different key
than the one used by read_transcript_page(), so deleted pages can remain cached
for relative or symlinked paths. Update the deletion loop in codex_discovery.py
to remove entries from _transcript_cache using the same str(path) key shape that
read_transcript_page() uses, rather than only the resolved deleted_path returned
by _delete_codex_owned_file(). Keep the existing deletion flow in the candidate
loop, but ensure the cache pop targets the original session path key as well so
stale transcript pages are fully cleared.
- Around line 338-341: Validate the thread ID in unarchive_thread() before
calling thread_unarchive by using the same _required_thread_id() helper that
archive_thread() and rename_thread() use. This keeps blank or whitespace-only
IDs from reaching the Codex SDK and makes unarchive_thread() consistent with the
other thread operations. Keep the fix localized to unarchive_thread() and
preserve the existing client/context flow.

In `@executor/runtime_work/codex_global_state.py`:
- Around line 279-300: Serialize the read-modify-write in
_update_global_state_payload so concurrent ensure_* / rename_* / remove_* calls
cannot overwrite each other. Add a lock around the full sequence that reads with
_read_global_state_payload, mutates, writes the temp file, and calls os.replace,
so the atomic swap is protected by mutual exclusion as well. Use the
_update_global_state_payload helper as the main place to introduce the lock and
keep the existing temporary-file replace flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a261d4f0-cdb9-4dde-95ea-e8b1126e2c7a

📥 Commits

Reviewing files that changed from the base of the PR and between 101c44f and a5f4aca.

📒 Files selected for processing (3)
  • executor/runtime_work/codex_discovery.py
  • executor/runtime_work/codex_global_state.py
  • executor/runtime_work/rpc_handler.py
✅ Files skipped from review due to trivial changes (1)
  • executor/runtime_work/rpc_handler.py
🛑 Comments failed to post (3)
executor/runtime_work/codex_discovery.py (2)

338-341: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate the thread ID before unarchiving.

unarchive_thread() bypasses _required_thread_id(), so blank or whitespace IDs can reach the SDK and fail differently from archive_thread() / rename_thread().

Proposed fix
 def unarchive_thread(self, thread_id: str) -> None:
+    normalized_thread_id = _required_thread_id(thread_id)
     client = self._create_codex_client()
     with client as codex:
-        codex.thread_unarchive(thread_id)
+        codex.thread_unarchive(normalized_thread_id)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    def unarchive_thread(self, thread_id: str) -> None:
        normalized_thread_id = _required_thread_id(thread_id)
        client = self._create_codex_client()
        with client as codex:
            codex.thread_unarchive(normalized_thread_id)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@executor/runtime_work/codex_discovery.py` around lines 338 - 341, Validate
the thread ID in unarchive_thread() before calling thread_unarchive by using the
same _required_thread_id() helper that archive_thread() and rename_thread() use.
This keeps blank or whitespace-only IDs from reaching the Codex SDK and makes
unarchive_thread() consistent with the other thread operations. Keep the fix
localized to unarchive_thread() and preserve the existing client/context flow.

393-402: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clear the transcript cache with the same key shape used to populate it.

read_transcript_page() caches under str(path), but deletion only pops the resolved path returned by _delete_codex_owned_file(). Relative or symlinked session paths can leave stale pages cached after deletion.

Proposed fix
         for candidate in _unique_texts(
             session_path,
             _thread_state_text(thread_state, "rollout_path"),
         ):
             deleted_path = _delete_codex_owned_file(self.codex_home, candidate)
             if deleted_path:
                 deleted_files.append(deleted_path)
+                self._transcript_cache.pop(candidate, None)
                 self._transcript_cache.pop(deleted_path, None)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        deleted_files = []
        for candidate in _unique_texts(
            session_path,
            _thread_state_text(thread_state, "rollout_path"),
        ):
            deleted_path = _delete_codex_owned_file(self.codex_home, candidate)
            if deleted_path:
                deleted_files.append(deleted_path)
                self._transcript_cache.pop(candidate, None)
                self._transcript_cache.pop(deleted_path, None)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@executor/runtime_work/codex_discovery.py` around lines 393 - 402, The
transcript cache cleanup is using a different key than the one used by
read_transcript_page(), so deleted pages can remain cached for relative or
symlinked paths. Update the deletion loop in codex_discovery.py to remove
entries from _transcript_cache using the same str(path) key shape that
read_transcript_page() uses, rather than only the resolved deleted_path returned
by _delete_codex_owned_file(). Keep the existing deletion flow in the candidate
loop, but ensure the cache pop targets the original session path key as well so
stale transcript pages are fully cleared.
executor/runtime_work/codex_global_state.py (1)

279-300: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Serialize global-state updates.

_update_global_state_payload() is a read-modify-write cycle with no lock, so concurrent ensure_* / rename_* / remove_* calls can clobber each other’s changes. os.replace() only makes the final swap atomic; it does not protect the mutation window.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@executor/runtime_work/codex_global_state.py` around lines 279 - 300,
Serialize the read-modify-write in _update_global_state_payload so concurrent
ensure_* / rename_* / remove_* calls cannot overwrite each other. Add a lock
around the full sequence that reads with _read_global_state_payload, mutates,
writes the temp file, and calls os.replace, so the atomic swap is protected by
mutual exclusion as well. Use the _update_global_state_payload helper as the
main place to introduce the lock and keep the existing temporary-file replace
flow.

@FicoHu

FicoHu commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Closing this PR to keep the work consolidated into a single open MR. The runtime-work patch is already present on main via #1544, so #1553 remains the only MR to continue with.

@FicoHu FicoHu closed this Jun 25, 2026
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.

1 participant