Skip to content

fix(mcp): surface BaseExceptionGroup from add_tool_server connect - #443

Open
openjiuwen-sync-bot[bot] wants to merge 292 commits into
openJiuwen-ai:mainfrom
openjiuwenai:sync/pr-2260
Open

fix(mcp): surface BaseExceptionGroup from add_tool_server connect#443
openjiuwen-sync-bot[bot] wants to merge 292 commits into
openJiuwen-ai:mainfrom
openjiuwenai:sync/pr-2260

Conversation

@openjiuwen-sync-bot

@openjiuwen-sync-bot openjiuwen-sync-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Paired: GitHub #443GitCode !2260

Summary

Fixes #​1497: MCP server connection failures wrapped in an exception group were silently swallowed by ToolMgr.add_tool_server, and task cancellation was broken.

Root cause

asyncio.CancelledError and BaseExceptionGroup both inherit from BaseException, NOT Exception. The old handler was a bare:

except Exception as e:
    raise build_error(StatusCode.RESOURCE_MCP_SERVER_ADD_ERROR, ...) from e

So a connection failure raised inside asyncio.gather/TaskGroup (wrapped in a BaseExceptionGroup) escaped the handler entirely and propagated as an untyped error instead of the proper RESOURCE_MCP_SERVER_ADD_ERROR (110512). Similarly, CancelledError escaping mid-connect could not be distinguished from a real failure.

Change (openjiuwen/core/runner/resources_manager/tool_manager.py)

  1. except asyncio.CancelledError: raise — task cancellation now propagates correctly instead of being mis-wrapped into a business error (cooperative cancellation preserved).
  2. except BaseExceptionGroup as e — group-wrapped failures now become RESOURCE_MCP_SERVER_ADD_ERROR. A single-exception group (the common asyncio.gather case) is unwrapped so the real cause (RuntimeError("boom")) appears in the error message instead of the unhelpful "… (1 sub-exception)".
  3. except Exception remains for ordinary failures (unchanged behavior).

Tests (tests/unit_tests/core/runner/test_tool_manager_mcp_exception.py, new)

  • BaseExceptionGroup from connect()WorkflowError with code 110512 and the inner cause surfaced
  • asyncio.CancelledError from connect() → propagates unwrapped
  • plain ConnectionError → still wrapped as 110512 (regression guard)

Verification

  • Windows (Python 3.12 + uv): uv run pytest tests/unit_tests/core/runner/test_tool_manager_mcp_exception.py3 passed
  • Linux (Docker, python:3.12-slim + uv): same command — 3 passed

Linked Closing Issues:

Shuo93 added 30 commits July 16, 2026 10:47
…space

Clarify in the swarmflow tool description (cn+en) that when the leader
hand-writes a script file to pass via script_path (as opposed to inline
script, which the framework materializes automatically), the file must be
written into the team workspace, not /tmp or outside it.

Refs: #1047
… tag notices

external/format.py now renders messages/events as <team-inbound> / <team-event>
XML via inbound_render, mirroring the in-process dispatcher, so external CLI
members read the same shape. The inbound-tag notice moves into
build_team_static_sections unconditionally (every member renders the XML); the
attachment notice is gated behind include_attachment_notice (in-process only —
external CLI has no attachment channel).

Refs: #751
Fold the human roster into the single team_members attachment tagged
[human] (gated by expose_human_agents_to_teammates) and drop the
separate team_hitt_roster. Bridge members are ordinary team_members
entries, so bridge_leader/bridge_teammate templates are removed and only
the bridge avatar keeps a self-contract. The HITT contract becomes a
static builder section gated on hitt_enabled, so _sync_dynamic_sections
only writes the attachment tail (team_members / team_info) and never the
system prompt builder. Also rename the self-name placeholder peers ->
self_line and move it to the top of the human_agent contract.

Refs: #751
Gate the idle-teammate board nudge on events that can grow the claimable
pool (TASK_CREATED / TASK_UNBLOCKED / TASK_RELEASED) and render only
claimable (pending + unassigned) tasks, so a teammate is no longer woken
by others' in-flight task churn. Leader still surveys the full board on
every event.

Add TASK_RELEASED, published by TeamTaskManager.reset, so a task freed
back into the pending pool (member cleanup / leader reassignment) wakes
idle teammates to pick it up.

Refs: #751
Collapse the four stale-task nudge paths to self-only: every member
sweeps its own claimed tasks on POLL_TASK and self-nudges, dropping the
leader's cross-process nudges (poll + member-status-change). Nudges now
carry just task_id + title (details via view_task) and are appended
(use_steer=False) instead of steering the running round.

Refs: #751
- retry a round's query once when it dies abnormally (crash or
  completion-timeout error), emit kind=failed to round subscribers,
  and give up loudly on a second death instead of looping
- warn every 120s while blocked on the context processor lock
- run DbSessions read/write session blocks under a 30s watchdog

Refs: #751
… per member

Reassignment now resets only the target task and notifies the former assignee via a targeted TASK_REVOKED event, instead of cancel_member tearing down the member's whole agent (all its claims + in-flight round). This also drops the cancel_member+reset double-reset that made a live-member reassignment fail. Enforce one active claim per member at the claim_task / update_task tool boundary via TeamTaskManager.get_other_claimed_task.

Refs: #751
task_manager: get_other_claimed_task semantics + reassign (transfer with TASK_REVOKED, missing-member no-op). tool boundary: reject a second concurrent claim / assign to a busy member. coordination: on_task_revoked self-steer vs other-member ignore. Update the old reassign test to assert cancel_member is never called.

Refs: #751
… commit

Add a front-matter rule to the archiving section: read the relevant S_NN / F_NN docs as a design input before changing code design, and sync them as the plan lands — instead of back-filling docs at commit time. Frames the existing three constraints as the produce-time half and this as the consume-first half of bidirectional sync.

Refs: #751
…ce member-wide cancel

Reassign swaps the assignee via a DAO atomic CAS (task stays CLAIMED, never bounces through PENDING) and fires only TASK_REVOKED + TASK_CLAIMED — no spurious TASK_RELEASED waking idle teammates. Cancel and content-edit stop calling cancel_member: they fire targeted TASK_CANCELLED / TASK_UPDATED carrying the affected member (on_task_cancelled / on_task_updated). Editing a claimed task keeps it claimed and tells the assignee to re-read; editing a human-agent task is refused (HITT lock). Remove the dead _cancel_member helpers; rewrite update_task / claim_task descriptions.

Refs: #751
… dispatch routing

task_manager: reassign fires no TASK_RELEASED; cancel/edit notify the assignee with member_name. tool boundary: cancel/edit no longer call cancel_member; edit keeps the task claimed; human-locked edit refused. coordination: on_task_cancelled / on_task_updated self-branches + integration via dispatcher.dispatch routing TASK_REVOKED / TASK_CANCELLED / TASK_UPDATED. database: DAO now permits editing CLAIMED (PLAN_APPROVED still locked).

Refs: #751
…l variants

Rename the task state machine to condition names: CLAIMED/STARTED/PLAN_APPROVED
collapse into PLANNING/IN_PROGRESS, with IN_REVIEW reserved for the verify gate.
"Plan approved" is now the PLANNING->IN_PROGRESS edge; assign is mode-aware
(plan_mode -> PLANNING gate, build_mode -> IN_PROGRESS). Folds the uncommitted
STARTED work so it never enters history.

Also lands the previously-uncommitted F_57 tool-variant / dispatch_mode
framework (create_task/send_message/member_complete variants, assignee
atomic landing, templated tool descriptions) that the state machine builds on.

Refs: #751
Update task-status assertions to PLANNING/IN_PROGRESS/IN_REVIEW across DAO,
manager, tools, hitt, observability, external and coordination tests; drop the
folded STARTED-mirror scheduled-plan test and rename the dependency-reject
test. Add the F_57 tool-variant / locale-variant coverage.

Refs: #751
Archive F_57 (tool variants) and F_59 (condition-named state machine + verify
gate; delivered in phases, Phase 1 done). Rewrite the TaskStatus section of
S_12 and invariants 16/17/19 of S_08 to the PLANNING/IN_PROGRESS/IN_REVIEW
machine. The folded F_58 doc is dropped (never committed).

Refs: #751
Tasks carry a reviewer list (leader-assigned via create_task/update_task).
An author's completion of a reviewed task enters IN_REVIEW instead of
COMPLETED, and a reviewer's verify_task passes it (-> COMPLETED, unblocking
dependents) or fails it (-> IN_PROGRESS rework, feedback to the author).

Adds the reviewer column + dynamic-table migration (also folding legacy
execution statuses into in_progress), the member-scoped verify_task tool with
reviewer/author guards, view_task(action=in_review), three verify events
(submitted-for-review / verified / revision-requested) with coordination
routing that wakes reviewers and the author, and reviewer-aware policy prompts.

Refs: #751
New test_verify_gate.py exercises reviewer routing (complete -> IN_REVIEW),
verify pass/fail loops, reviewer/author guards, one-active with IN_REVIEW, and
get_review_tasks filtering. Adds verify-gate tool coverage in test_tool_variants,
three coordination handler cases (reviewer / author wakes), a DB migration case
(reviewer column + legacy-status fold), and updates the MCP member tool set.

Refs: #751
F_59 records the Phase 2 reviewer/verify implementation (reviewer storage,
completion routing, verify_task guards, in-process framework dispatch, deferred
human-reviewer auto-notify). S_08 gains invariant 20 (leader-assigned reviewers,
reviewer-decided verification); S_12's TaskStatus section and TaskDetail reflect
the now-reachable IN_REVIEW gate and the reviewer field.

Refs: #751
Shuo93 and others added 19 commits August 6, 2026 22:33
When parent matching failed, chunk / usage / completion callbacks fell back
to "the most recently opened llm.call span in this trace", so a detached
request — the image-modality probe being the common one — wrote its result
onto whichever span an agent had just opened.

Model.invoke/stream now open a call scope naming the request, the span is
indexed under that id, and parent matching is only a fallback that answers
when it is unambiguous.
…r invoke

Two gaps the agent tier had: before_invoke refused any agent without a
team_name, which no harness-built sub-agent has, so a dispatched sub-agent
got no span and its llm/tool calls attached to the dispatching agent; and an
agent receiving both hooks emitted its invoke and iteration spans as siblings
under the team span, the invoke one empty.
Cached prompt tokens and reasoning tokens are subsets of the provider's
prompt / completion counts, but were reported beside them as their own
gen_ai.usage keys. Langfuse sums every usage key, so a run whose prompts are
mostly cache hits reported far more tokens than were consumed — 981,833 vs
598,615 on a 20-call coding run. Carve the subsets out of their parent for
that backend; OTLP consumers keep the semconv meaning.
Reasoning time is measured from stream chunks, so a non-streaming call has
none. Those spans were created at finalize time — zero-length, parked at the
end of the llm.call, after the answer the reasoning preceded. Anchor them at
the call start and say why the duration is absent instead of implying zero.
A present-but-blank *_API_URL fell through os.environ.get(name, default),
which only substitutes the default when the key is absent. The request then
targeted an empty URL and aiohttp raised InvalidUrlClientError, whose str()
is empty, so the tool reported "paid search failed. bocha:" with no reason.

Route every endpoint through _env_url so unset and blank behave alike, and
let serper/jina read their overrides instead of hardcoding the official host.
The swarmflow tool is gated on the worker-model resolver, but the leader
policy that tells it to weigh build_team against swarmflow was static —
so a leader without the tool still deliberated over a mechanism it could
not invoke.

Move the mechanism-choice section into leader_swarmflow.md and fill it
into leader_policy's {{collaboration_mechanism}} slot only when the rail
sees the same signal the tool factory gates on. Drop the swarmflow note
from leader_workflow.md and the swarmflow example from the async tool
descriptions, which are never gated.

Refs: #984
Paired: [GitHub openJiuwen-ai#359](openJiuwen-ai#359) ↔ [GitCode !2214](https://gitcode.com/openJiuwen/agent-core/merge_requests/2214)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind bug

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [x] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [x] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [x] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [x] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [x] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2214
github_repo: openJiuwen-ai/agent-core
github_pr: 359
github_branch: sync/pr-2214
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1478](https://gitcode.com/openJiuwen/agent-core/issues/1478)
<!-- /related-issues -->
Refs: #1275

Paired: [GitHub openJiuwen-ai#372](openJiuwen-ai#372) ↔ [GitCode !2223](https://gitcode.com/openJiuwen/agent-core/merge_requests/2223)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind feature

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [x] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [x] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [x] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [x] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [x] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2223
github_repo: openJiuwen-ai/agent-core
github_pr: 372
github_branch: sync/pr-2223
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1275](https://gitcode.com/openJiuwen/agent-core/issues/1275)
<!-- /related-issues -->
Paired: [GitHub openJiuwen-ai#361](openJiuwen-ai#361) ↔ [GitCode !2216](https://gitcode.com/openJiuwen/agent-core/merge_requests/2216)

# 新增 fork 机制

**What type of PR is this?**

/kind feature

## 背景

团队中多个并行的执行者需要对同一个代码仓库有共同的理解(如基类接口、项目架构),但每个执行者独立启动时会重新读取文件和搜索代码,造成重复的 IO 和 token 消耗。需要一种机制让已理解的代理将上下文继承给新成员。

## 方案

新增 **Fork(上下文继承)** 机制,允许任意本地 harness 成员将自己的对话上下文注入到新 spawn 的成员中。核心能力:

### 1. ForkContext — 上下文捕获
- `agent_teams/fork.py`:`ForkContext.from_agent(agent, checkpoint=N)` 捕获代理的当前全部对话历史
- 捕获的是 `UserMessage` / `AssistantMessage` / `ToolMessage` 三类消息——`SystemMessage` 不在 `ContextEngine` 的消息池中,不在继承范围
- 目标代理的角色由 `TeamPolicyRail` 注入,与 fork 源无关
- `checkpoint=N` 可截断消息列表到指定位置,不传则全量

### 2. CheckpointTool — 命名快照
- `checkpoint(name="code-ready")`:保存当前消息数量为命名快照,存于 leader 的共享 `_named_checkpoints` 字典中
- 任意成员可调用,快照不绑定语义方向,由 `spawn_teammate` 的 `fork` / `compact` 参数决定使用方式

### 3. Fork Compaction — 上下文压缩
- `agent_teams/fork_compact.py`:`compact_context(agent, split_at=N)` 在 fork 注入后压缩旧消息
- `checkpoint` 位置之前的消息通过一次模型调用压缩为摘要,之后的全量保留
- 仅当 `spawn_teammate(fork="ckpt", compact=true)` 时触发

### 4. SpawnTeammateTool 扩展
- 新增 `fork` 参数:`true`(全量)、字符串(checkpoint 名)
- 新增 `fork_source` 参数:指定来源成员名,默认 leader
- 新增 `compact` 参数:启用上下文压缩,仅配合 checkpoint fork 使用

## Fork 语义

| fork | compact | 行为 |
|------|---------|------|
| `true` | — | 全量注入,不压缩 |
| `"ckpt"` | false | 截断到 ckpt 之前 |
| `"ckpt"` | true | ckpt 为分界:之前压缩为摘要,之后全量保留 |

### 5. 封装约定
- `TeamHarness.get_deep_agent()` 替代 `harness._native`
- `TeamAgent.share_checkpoints_with()` / `set_checkpoint()` / `_set_checkpoints_from()` 替代 `_named_checkpoints` 直接访问
- `TeamBackend.set_snapshot_length()` / `set_store_checkpoint_fn()` 替代外部赋值
- `fork_compact` 使用公开 `react_agent` property

### 6. 日志分级
- 成功 fork → INFO(`live/checkpoint/compacted fork into member`)
- 压缩结果 → INFO(`compressing X, keeping Y` → `done — Z`)
- 参数异常 → WARNING(`checkpoint not found` / `compact ignored`)
- 内部生命周期 → DEBUG(mark/consume/snapshot/store/inject)

## 修改文件

### 新增文件

| 文件 | 说明 |
|------|------|
| `openjiuwen/agent_teams/fork.py` | `ForkContext` dataclass |
| `openjiuwen/agent_teams/fork_compact.py` | `compact_context()` 压缩函数 |
| `tools/locales/descs/*/checkpoint.md` | checkpoint 工具描述 |
| `openjiuwen/agent_teams/docs/features/F_73_fork-context-inheritance.md` | fork 特性归档文档 |
| `tests/unit_tests/agent_teams/test_fork.py` | 25 个测试用例 |

### 修改文件

| 文件 | 变更 |
|------|------|
| `agent_teams/__init__.py` | 导出 `ForkContext` |
| `agent_teams/tools/tool_permissions.py` | `checkpoint` 加入 `SHARED_TOOLS` |
| `agent_teams/tools/tool_member.py` | 新增 `CheckpointTool`;`SpawnTeammateTool` 加 `fork`/`fork_source`/`compact` 参数 |
| `agent_teams/tools/tool_factory.py` | 注册 `checkpoint` 工具 |
| `agent_teams/tools/team.py` | `TeamBackend` 加 `_pending_forks`、`_checkpoints`、`set_snapshot_length()`、`set_store_checkpoint_fn()` 等公开方法 |
| `agent_teams/agent/agent_configurator.py` | 注入 `_snapshot_length` 回调,使用 `get_deep_agent()` |
| `agent_teams/agent/team_agent.py` | `_on_teammate_created` 重写(fork 决策 + 校验);新增 `_resolve_fork_native`、`share_checkpoints_with`、`set_checkpoint`、`_set_checkpoints_from`;`_named_checkpoints` 字段 |
| `agent_teams/agent/spawn_manager.py` | `fork_from: ForkContext \| None` 参数透传 |
| `agent_teams/spawn/inprocess_spawn.py` | `share_checkpoints_with()` / `get_deep_agent()` / `set_store_checkpoint_fn()` lambda + fork 注入 + compaction 调用 |
| `agent_teams/harness/team_harness.py` | 新增 `get_deep_agent()` 公开方法 |
| `agent_teams/external/client.py` | `create_team_tools` 排除 `checkpoint` 工具 |
| `agent_teams/external/cli_agent/claude/sdk_mcp.py` | `create_team_tools` 排除 `checkpoint` 工具 |
| `tests/unit_tests/agent_teams/external/test_mcp_server.py` | 外部 MCP 成员工具集不包含 `checkpoint` |
| `tools/locales/cn.py`、`en.py` | checkpoint + fork/compact 参数字符串 |
| `tools/locales/descs/*/checkpoint.md` | checkpoint 工具描述 |
| `tools/locales/descs/*/spawn_teammate.md` | fork 使用文档 |

## 使用示例

```
# 1. 拉起理解者
Leader:   spawn_teammate(name="reader", desc="理解 base.py")

# 2. 理解者分析代码
Leader:   send_message(to="reader", content="请阅读 base.py 并理解所有接口")
reader:   read_file("base.py") → "class Base: def foo()..."

# 3. 打快照
Leader:   send_message(to="reader", content="调 checkpoint(name='base-ready')")
reader:   checkpoint(name="base-ready")

# 4. Fork 四个执行者
Leader:   spawn_teammate(name="dev-1", desc="实现 Derived1",
                        fork="base-ready", fork_source="reader")
Leader:   spawn_teammate(name="dev-2", desc="实现 Derived2",
                        fork="base-ready", fork_source="reader")
```

## 验证

四个模式均通过测试:

| 模式 | 结果 |
|------|------|
| Live fork (`fork=true`) | ✅ 全量注入 |
| Checkpoint fork (`fork="ckpt"`) | ✅ 截断到 ckpt 前 |
| Compaction fork (`fork="ckpt" compact=true`) | ✅ ckpt 前压缩为摘要、后全量保留 |
| 无 fork 成员 | ✅ 不改行为 |

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [ ] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [x] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [x] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [x] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [x] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2216
github_repo: openJiuwen-ai/agent-core
github_pr: 361
github_branch: sync/pr-2216
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1435](https://gitcode.com/openJiuwen/agent-core/issues/1435)
<!-- /related-issues -->
Paired: [GitHub openJiuwen-ai#381](openJiuwen-ai#381) ↔ [GitCode !2229](https://gitcode.com/openJiuwen/agent-core/merge_requests/2229)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind bug

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [ ] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [x] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [x] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [ ] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [ ] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2229
github_repo: openJiuwen-ai/agent-core
github_pr: 381
github_branch: sync/pr-2229
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1487](https://gitcode.com/openJiuwen/agent-core/issues/1487)
<!-- /related-issues -->
…atible

Refs: #1465

Paired: [GitHub openJiuwen-ai#385](openJiuwen-ai#385) ↔ [GitCode !2232](https://gitcode.com/openJiuwen/agent-core/merge_requests/2232)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind bug

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [ ] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [x] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [x] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [ ] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [ ] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2232
github_repo: openJiuwen-ai/agent-core
github_pr: 385
github_branch: sync/pr-2232
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1465](https://gitcode.com/openJiuwen/agent-core/issues/1465)
<!-- /related-issues -->
Refs: #1435

Paired: [GitHub openJiuwen-ai#387](openJiuwen-ai#387) ↔ [GitCode !2233](https://gitcode.com/openJiuwen/agent-core/merge_requests/2233)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/openJiuwen/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openJiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
/kind feature

**What does this PR do / why do we need it**:

为调度指派模式团队引入多类型 reviewer 系统,替代原来的单类型 pass/fail reviewer。

核心改动:
- **verifier + challenger**:二元 pass/fail 投票,一票否决制(任一 fail 即打回)
- **inspector**:0~1 浮点分数投票,全部 inspector 平均分 ≥ 0.85 才算通过
- `reviewer_id` 由系统按类型自动编号(verifier_1、inspector_1 等),leader 不可见
- temp reviewer harness 遇到 181001(模型断连)自动重试 3 次,每次重建 harness
- `enable_task_verification` 改为 AND 语义(用户 spec 天花板 × leader 选择),false 时拦截 reviewer 分配
- escalate 升级增强:轮数耗尽时先让 assignee 发返工总结给 leader,leader 综合 reviewer 反馈和 assignee 复盘再做决策
- inspector 打分表可由 leader 在 create_task 时提供,留空则回退默认 6 维通用打分表
- `verify_vote_threshold` spec 字段删除,`settle_review_tally` 替代 `judge()` 硬编码一票否决
- `create_task`/`update_task` 的 reviewer 字段从 `list[string]` 改为 `list[object]`

**Which issue(s) this PR fixes**:
Fixes #1435

**What scenarios were tested, and what were the verification results(Function, performance, reliability, etc.)**:

- **单元测试**:87 passed(新增 9 例),覆盖 structured reviewer create、reviewer_id 自动编号、旧格式兼容、settle_review_tally 纯函数 6 个场景
- **端到端**:排序算法验证任务完整跑通(verifier + inspector + challenger 三类型联合验收),escalation 流程正常(leader 等 inbox 总结后再决策),inspector 加权打分正确,challenger 重构后不再无限阻塞
- **enable_task_verification**:spec=false 天花板有效,spec=true + leader=false 时 reviewer 正确清空
- coordination 层有 20 个预存 failing test(autonomous 模式 stale claim / task board),与本次改动无关

**Self-checklist**:(**Please check carefully,and mark an x in the [] brackets. We will review your completion status.**)

+ - [x] **Design**: Has the solution corresponding to the PR been reviewed by the Maintainer, and have all review comments been replied to and revised
+ - [x] **Test**: Has the code in the PR been fully covered by UT/ST test cases, and have the newly added test cases been uploaded to the repository along with this PR or already uploaded.
+ - [x] **Verification**: Does the PR description contains a detailed description of the verification results regarding the achievement of the expected goals for the Feature, Refactor, and Bugfix to this PR.
+ - [x] **Interface**: Does it involve changes to external interfaces? The corresponding changes have been approved by the interface review organization, and the annotation information for the API has been correctly refreshed.
  涉及 `verify_vote_threshold` 字段删除、`create_task`/`update_task` 的 `reviewer` schema 变更(`list[string]` → `list[object]`)。向后兼容:旧格式字符串自动升级为 verifier 类型。
+ - [x] **Document**: Does it involve modifications to the official website documentation? If so, please submit the materials to the Doc repository in a timely manner.
  新增 `docs/features/F_73_reviewer-role-split-and-flexible-verification.md` 特性文档,更新 `agent/scheduling/AGENTS.md`。不涉及官网文档。

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] Whether it causes forward compatibility failure -->
<!-- + - [ ] Whether the dependent third-party library change is involved -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2233
github_repo: openJiuwen-ai/agent-core
github_pr: 387
github_branch: sync/pr-2233
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1435](https://gitcode.com/openJiuwen/agent-core/issues/1435)
<!-- /related-issues -->
Paired: [GitHub openJiuwen-ai#322](openJiuwen-ai#322) ↔ [GitCode !2187](https://gitcode.com/openJiuwen/agent-core/merge_requests/2187)

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [ ] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [ ] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [ ] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [ ] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [ ] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2187
github_repo: openJiuwen-ai/agent-core
github_pr: 322
github_branch: sync/pr-2187
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1483](https://gitcode.com/openJiuwen/agent-core/issues/1483)
<!-- /related-issues -->
Paired: [GitHub openJiuwen-ai#355](openJiuwen-ai#355) ↔ [GitCode !2212](https://gitcode.com/openJiuwen/agent-core/merge_requests/2212)
## 简述:
同步修改jiuwenswarm和agent-core仓库,实现后端与前端结合的通过验证流程结果进行成员skill,全局skill自演进的功能,保留原有普通自演进流程,在每个leader分配的task下进行成员skill演进,在所有任务最后进行全局skill演进。
例:
![ebd0b0edcd497cf728f9f5ef0e8d1922.png](https://raw.gitcode.com/user-images/assets/8766961/acd666bf-eb35-4574-b0e9-d3ca335cf0fb/ebd0b0edcd497cf728f9f5ef0e8d1922.png 'ebd0b0edcd497cf728f9f5ef0e8d1922.png')
![image.png](https://raw.gitcode.com/user-images/assets/8766961/1a4d3887-9c41-4e67-b33c-b413a813028c/image.png 'image.png')
## 修改部分
| 模块 | 修改功能 |
| --- | --- |
| `agent_evolving/signal/review_feedback.py` | 新增 Reviewer Feedback 结构化归因模块 |
| `trajectory/registry.py` | 支持按 team、session、member 获取成员独立轨迹 |
| `scheduler.py` | Task 验收失败后触发 Feedback callback;团队结束时触发汇总 callback |
| `skill_evolution_rail.py` | 新增外部演进信号入口,复用现有 optimizer、审批、存储和 semaphore |
| `team_skill_create_rail.py` | 支持根据重复 Feedback 证据生成新 Skill 审批 |
| 单元测试与 API 文档 | 覆盖归因、安全限制、调度回调、外部演进入口和新 Skill 审批 |

## 功能

- Task Reviewer 判定失败后,Scheduler 将任务信息、Reviewer Feedback、assignee 和 review round 发送给宿主回调。

- ReviewFeedbackAttributor 使用一次结构化 LLM 调用,将问题归类为:
  1. skill_issue:已有 Skill 的规范存在缺陷。
  2. executor_error:执行者没有遵循已有 Skill。
  3. new_skill_pattern:出现可复用但没有对应 Skill 的工作模式。
  4. unattributed:证据不足,无法归因。
- 第二次输入llm则与普通自演进相同。
- 在满足对应条件下会自动/提出审批卡修改skill,或新建skill(现只支持全局skill)

## 后续修改
- 当验证流程修改后,会根据验证流程的变化修改对feedback的解析流程,给出更合理的标准。

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2212
github_repo: openJiuwen-ai/agent-core
github_pr: 355
github_branch: sync/pr-2212
-->
Paired: [GitHub openJiuwen-ai#409](openJiuwen-ai#409) ↔ [GitCode !2244](https://gitcode.com/openJiuwen/agent-core/merge_requests/2244)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind bug

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [ ] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [ ] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [ ] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [ ] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [ ] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2244
github_repo: openJiuwen-ai/agent-core
github_pr: 409
github_branch: sync/pr-2244
-->
Paired: [GitHub openJiuwen-ai#411](openJiuwen-ai#411) ↔ [GitCode !2245](https://gitcode.com/openJiuwen/agent-core/merge_requests/2245)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind bug

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [ ] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [ ] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [ ] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [ ] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [ ] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2245
github_repo: openJiuwen-ai/agent-core
github_pr: 411
github_branch: sync/pr-2245
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1500](https://gitcode.com/openJiuwen/agent-core/issues/1500)
<!-- /related-issues -->
Paired: [GitHub openJiuwen-ai#418](openJiuwen-ai#418) ↔ [GitCode !2249](https://gitcode.com/openJiuwen/agent-core/merge_requests/2249)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind bug

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [ ] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [ ] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [ ] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [ ] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [ ] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2249
github_repo: openJiuwen-ai/agent-core
github_pr: 418
github_branch: sync/pr-2249
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1501](https://gitcode.com/openJiuwen/agent-core/issues/1501)
<!-- /related-issues -->
…ification

Refs: #1435

Paired: [GitHub openJiuwen-ai#416](openJiuwen-ai#416) ↔ [GitCode !2248](https://gitcode.com/openJiuwen/agent-core/merge_requests/2248)

<!--  Thanks for sending a pull request!  Here are some tips for you:

1) If this is your first time, please read our contributor guidelines: https://gitcode.com/openJiuwen/community/blob/master/CONTRIBUTING.md

2) If you want to contribute your code but don't know who will review and merge, please add label `openjiuwen-assistant` to the pull request, we will find and do it as soon as possible.
-->

**What type of PR is this?**
<!-- 
选择下面一种标签替换下方 `/kind <label>`,可选标签类型有:
- /kind bug 
- /kind task
- /kind feature
- /kind refactor
- /kind clean_code
如PR描述不符合规范,修改PR描述后需要/check-pr重新检查PR规范。
-->
/kind bug

**Self-checklist**:(**请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入**)

+ - [x] **设计**:PR对应的方案是否已经经过Maintainer评审,方案检视意见是否均已答复并完成方案修改
+ - [x] **测试**:PR中的代码是否已有UT/ST测试用例进行充分的覆盖,新增测试用例是否随本PR一并上库或已经上库
+ - [x] **验证**:PR描述信息中是否已包含对该PR对应的Feature、Refactor、Bugfix的预期目标达成情况的详细验证结果描述
+ - [x] **接口**:是否涉及对外接口变更,相应变更已得到接口评审组织的通过,API对应的注释信息已经刷新正确
+ - [x] **文档**:是否涉及官网文档修改,如果涉及请及时提交资料到Doc仓

<!-- **Special notes for your reviewers**: -->
<!-- + - [ ] 是否导致无法前向兼容 -->
<!-- + - [ ] 是否涉及依赖的三方库变更 -->

<!-- bot4-pr-sync-meta
schema_version: 1
source: gitcode
gitcode_repo: openJiuwen/agent-core
gitcode_mr: 2248
github_repo: openJiuwen-ai/agent-core
github_pr: 416
github_branch: sync/pr-2248
-->

<!-- related-issues -->
Linked Closing Issues:
- [#1435](https://gitcode.com/openJiuwen/agent-core/issues/1435)
- [#1498](https://gitcode.com/openJiuwen/agent-core/issues/1498)
<!-- /related-issues -->
asyncio.CancelledError and BaseExceptionGroup both inherit from
BaseException, NOT Exception, so a bare `except Exception` in
add_tool_server silently let MCP connection failures wrapped in a
group escape (and broke cooperative cancellation).

- re-raise CancelledError so task cancellation propagates correctly
- catch BaseExceptionGroup and wrap it into RESOURCE_MCP_SERVER_ADD_ERROR
- unwrap single-exception groups so the real cause (not
  "… (1 sub-exception)") reaches the error message

Closes #1497.

Co-Authored-By: AtomCode (deepseek-v4-flash) <noreply@atomgit.com>
@CLAassistant

CLAassistant commented Aug 10, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
2 out of 21 committers have signed the CLA.

✅ ShowHsiang
✅ ZhCoding
❌ tangfei0306
❌ openJiuwen-bot
❌ z2tng
❌ zhouziliang1015
❌ yanmenxue
❌ lindada11
❌ xiao-yu-lin
❌ yzqcjdtc
❌ Li-111
❌ ggg66
❌ chenchunzhou1995
❌ yan-zj722
❌ doujzc
❌ Shuo93
❌ hwxiajing
❌ ChenfromChina123
❌ Mavs-32
❌ layShang264
❌ Little-Shepherd


openJiuwen-bot seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: ff698d8f1d405b346ba56ed788edda81b5ce538c

⚠️ 本次变更过大(1296 个可审文件、252713 行),已超出 AI 代码评审的处理范围,本次跳过。建议拆分为更小的 PR 以获得有效评审。

1 similar comment
@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: ff698d8f1d405b346ba56ed788edda81b5ce538c

⚠️ 本次变更过大(1296 个可审文件、252713 行),已超出 AI 代码评审的处理范围,本次跳过。建议拆分为更小的 PR 以获得有效评审。

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: ff698d8f1d405b346ba56ed788edda81b5ce538c

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ✅SUCCESS 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

@openjiuwen-collaboration-bot

Copy link
Copy Markdown

head_sha: ff698d8f1d405b346ba56ed788edda81b5ce538c

任务名称 结果 日志操作
静态检查 ✅SUCCESS 点此跳转
防投毒检查 ✅SUCCESS 点此跳转
开源合规检查 ✅SUCCESS 点此跳转
UT测试 ❌FAILED 点此跳转
ST测试 N/A N/A
build 编译包 N/A N/A
ruff codecheck ✅SUCCESS N/A

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.