Skip to content

feat: MCP backend 运行态完善 + AI 编码 harness + runtime 启动器 + dev skills - #604

Open
DoctorReid wants to merge 26 commits into
mainfrom
feat/mcp-and-harness-infra
Open

feat: MCP backend 运行态完善 + AI 编码 harness + runtime 启动器 + dev skills#604
DoctorReid wants to merge 26 commits into
mainfrom
feat/mcp-and-harness-infra

Conversation

@DoctorReid

@DoctorReid DoctorReid commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

概述

本会话积累的全部工作(25 commit,6 块),照搬 ZZZ(绝区零一条龙)已验证实现 + 按 token 清单(common-package-sync.md §5)适配 SR 语境。

内容

1. AI 编码 harness 体系(基础)

  • AGENTS.md + .claude/CLAUDE.md@import 单源)
  • ruff / pytest / pyright 工具链 + gitignore 对齐
  • harness 方法论文档(context_layering / entry_files / settings_scope / ai_tool_rules
  • common 包同步维护说明 + 照搬 token 清单

2. sr_od 重构

  • app/{div_uni, treasures_lightward}application/(沿用 ApplicationFactory 模式)

3. MCP server 基础

  • sr_od/backend(schemas / backend_context / mcp / http / entry),照搬 ZZZ
  • tools/mcp/daemonsr_od_daemon,端口 24000)
  • backend 6 篇接入文档
  • pyproject dev 组加 mcp / uvicorn / psutil

4. runtime 启动器(可分发完整包)

  • sr_od/win_exe/runtime_launcher.py
  • generate_module_manifest + hook_path_inject + RuntimeLauncher.spec + build_full.bat
  • runtime_launcher 架构文档

5. dev skills + harness 勘误

  • sr-od-dev-* 3 个开发 skill(deciding-a-fix / pr-finishing / skill-guide),采纳 superpowers 流程方法论
  • harness README MCP 状态勘误 + skills 入口登记

6. MCP backend 运行态完善(本 PR 重点)

  • RunSlot 单跑道运行槽start_run / query_status / stopblock 同步/异步 + 中断安全语义)
  • close_game + analyze 画面匹配增强(依赖 common 的 screen_match.py
  • 7 MCP tool / 7 HTTP 端点(+ get_run_status / stop_run / close,enter 加 block
  • design-principles.md + adapted async-operation spec
  • 74 测试(sr-od-test)

验证

  • 74 测试全过(RunSlot 状态机固化判据 / 7-tool-7-端点装配 / screen_match 匹配逻辑,全 MagicMock)
  • pyright 0 error、GUI 启动 OK、sr_od 零失配
  • per-task review(忠实照搬:token 归一化后与 ZZZ 源 diff 为空)+ opus final review clean

照搬 token 清单缺口(已补进 common-package-sync.md §5)

本轮发现 5 类 sed+grep 都漏的 token:端口须用裸形式 / zzz_backend_run(小写前缀)/ ZPcController(Z 前缀业务子类)/ ZenlessZoneZero 字面量 / :2300 端口片段 / spec 文件名引用。

端口约定

主 server 24001、daemon 24000(避与 ZZZ 同机并存冲突)。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 新功能

    • 新增后端服务与远程控制入口:支持窗口检查、截图、OCR识别、进入游戏、运行状态查询与停止。
    • 新增应用级通知设置入口与推入式通知配置面板。
    • 提升滚动容器与画面匹配体验。
  • Bug 修复/优化

    • OCR/模型加载与下载流程更稳定,减少无效重复写入与异常中断。
    • 运行时同步与打包模块清单机制更可靠。
  • 文档

    • 补全开发、协作、调试与打包相关规范与指南。

DoctorReid and others added 25 commits July 2, 2026 12:03
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- one_dragon: 新增 context_notify_event.py 等,对齐 ZZZ 框架层
- one_dragon_qt: 新增 app_notify_setting_interface/flyout、fast_scroll_area,移除 notify_dialog
- onnxocr: 新增 inference_engine.py,含 PaddleOCR v6 代码支持

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- 新增 docs/develop/one_dragon/common-package-sync.md:common 三包性质、整包镜像同步法、模型下载机制
- AGENTS.md 架构落点:说明三个 common 包是游戏无关的公共框架
- AGENTS.md 硬约束:模型走运行时下载、不进 git、勿 git add

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
完成 sr_od 业务代码向 application/ 架构的统一:
- app/div_uni → application/div_uni(5 文件)
- app/treasures_lightward → application/treasures_lightward(18 文件)
- 删除 app/sr_application_launcher.py(转发 stub,application/ 已有真实实现)+ 空 app/__init__.py
- 导入路径 sr_od.app.{div_uni,treasures_lightward} → sr_od.application.*
- 清理空 app/ 目录

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- schemas: OcrText/AnalyzeScreenResult/WindowStatus(照搬)
- backend_context: SrBackendContext 收敛层(check_window/capture/analyze/enter_game)
- mcp/app: FastMCP 4 tool(check_game_window/capture_game_screen/analyze_screen/open_and_enter_game)
- http/routes: /game/{window,capture,analyze,enter} 4 端点
- entry/server: uvicorn 入口,端口 24001

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- sr_od_daemon.py: 管理 server daemon,端口 24000,4 个管理 tool(start/stop/restart/status)
- start_daemon.ps1: 启 daemon(默认 24000)
- create_startup_shortcut.ps1: 开机自启快捷方式

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
照搬 ZZZ docs/develop/zzz/backend(README/architecture/mcp/http/entry/remote-ssh),
命名/端口/文案替换为 sr_od / 24001·24000 / 星穹铁道;ai_coding.md 的 MCP 小节
由「尚未实现」更新为「已实现」并接入启动命令与文档链接。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
从 MCP backend 照搬实战提炼:token 形式多样(包名/模块文件名/类名/文案/路径/端口),
单一 sed/grep pattern 覆盖不全。补完整清单 + sed 顺序 + 验证纪律(grep pattern
须含 zzz/ 路径形式、pyright 兜底、.md 单独通读)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
SrLauncher(RuntimeLauncher): _do_run_gui→sr_full_app.main、
_do_run_onedragon→sr_application_launcher.main;文案星穹铁道。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
…fest,照搬 ZZZ

generate 扫 src/ 生成依赖清单,EXCLUDE_SRCPATHS=sr_od/backend(backend dev-only
不进发布 bundle);hook_path_inject 为 runtime_hook,注入 exe 旁 src/ 到 sys.path。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
入口 src/sr_od/win_exe/runtime_launcher.py;KEEP_TREES=one_dragon.launcher/version;
collect_submodules 收集源码包后 excludes 业务(runtime 只含依赖+Python,源码外部加载)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
build_full 一键打 3 exe + 拼 .runtime + 拷 config/assets/pyproject + 打 zip;
去掉不存在的 uv.toml 行;project.yml 加 manifest_path 启用 runtime 兼容性闸门。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
照搬 ZZZ docs/develop/one_dragon/runtime_launcher.md,命名替换(zzz_od→sr_od、
ZLauncher→SrLauncher、绝区零→星穹铁道、app.py→sr_full_app.py);CI/产物段
适配 SR 现状(无 CI、build_full.bat 产物 StarRailOneDragon*.zip、完整包不含 src)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- skills/sr-od-dev-{deciding-a-fix,pr-finishing,skill-guide}/(SKILL.md + design.md),从 ZZZ 同步并按 token 清单适配(CodeRabbit 内容保留)
- ai_coding.md:加「推荐安装 superpowers」节、symlink→junction(mklink /J 免管理员)、skill 表更新
- quickstart.md:新建,从 ZZZ 适配(sr_full_app.py / 端口 24001 / sr_od backend / sr-od-test)
- entry_files.md:补 path-scoped rule 说明段(非 always-on 规范在 AGENTS.md 提及并指向 docs)

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- README.md:方向A 补 superpowers+skills/ 方法论;方向B「暂未实施」→「已落地」(SrBackendContext / 4 tool / 端口 24001 / sr_od/backend);A-2/B-1 状态表更新;entry-files 表加 skills/ 行
- settings_scope.md:坑1 例子改 sr_od;表格行「无项目自有 MCP」→ 3 个 mcp__*(context7/sr_od/sr_od_daemon);整体归口补 server 定义落点

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- ZZZ 397b5b22 新增的 one_dragon/base/screen/screen_match.py(ScreenMatch dataclass + find_screen_matches)
- SR 的 one_dragon 其余部分已与 ZZZ 对齐,本次实质新增仅此一文件
- 验证:文件数 205、pyright 0 error、GUI 启动 OK、sr_od 零失配
- 解锁 Phase B:sr_od/backend analyze 画面匹配增强

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- schemas: + RunStatusResult、AnalyzeScreenResult +screens(import ScreenMatch)
- backend_context: + RunSlot 单跑道(start_run/query_status/stop)+ close_game + analyze 增强画面匹配
- mcp/app: 7 tool 工厂模式(+ get_run_status/stop_run/close_game,enter 加 block)
- http/routes: 7 端点(+ status/stop/close,enter 改 start_run)
- entry: docstring 勘误 4→7 tool
照搬 ZZZ backend 演进,token 清单适配(enter_game 单→复、sr_od_mcp 等)

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
- README/architecture/mcp/http/entry 更新为运行态版本(7 tool、7 端点、start_run/query_status/stop、close_game)
- 新增 design-principles.md(backend 设计原则 P1-P12)
- 适配 async-operation 设计 spec(docs/superpowers/specs/,gitignore 不入库)
- 通读勘误:README tool 数 4→7;architecture ZPcController→SrPcController;删 SR 不存在的 one_dragon_architecture.md 链接
照搬 ZZZ backend 文档,token 清单适配(sr_od 路径、端口 24001 等)

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
…te-design)

final review 发现:B3 sed 集(代码文件)未覆盖 spec 文件名 token,
backend_context.py:64 仍指向 ZZZ 的 2026-07-02 spec(SR 已适配为 2026-07-05)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
…匹配 + 7 tool/7 端点 + docs)

- common: 带进 screen_match.py(analyze 画面匹配依赖)
- backend: RunSlot 运行态管理(start_run/query_status/stop)+ close_game + analyze 增强
- mcp: 7 tool(+ get_run_status/stop_run/close_game,enter 加 block)
- http: 7 端点(+ status/stop/close,enter 改 start_run)
- docs: 运行态文档 + design-principles + adapted spec
- tests: 74 用例(sr-od-test)
照搬 ZZZ backend 演进,token 清单适配 SR。final opus review clean。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
MCP backend 照搬轮靠通读/final review 抓到 5 类 sed+grep 都漏的 token:
- 端口 sed 须用裸形式(不带反引号)
- 小写前缀 zzz_backend_run(thread_name_prefix)
- Z 前缀业务子类 ZPcController
- 英文游戏名字面量 ZenlessZoneZero
- 端口片段 :2300(findstr)
- spec 文件名引用
§5.2 残留 grep pattern 同步补 Zenless|ZPc|zzz_backend|:2300。

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Walkthrough

本次变更新增了 AI 协作与开发规范文档、PyInstaller 集成打包与 sr_od 后端服务链路,并重构了通知、画面、OCR、日志、下载、YAML、Qt 滚动组件及多个界面交互与基础设施实现。

Changes

AI 协作与开发规范

Layer / File(s) Summary
入口与忽略规则
.claude/CLAUDE.md, AGENTS.md, .gitignore, .github/dev.md, pyproject.toml
新增仓库级 AI 协作入口文档与忽略规则,更新开发环境说明,并补充开发依赖与 Ruff/Pyright 配置。
Harness 方法论
docs/develop/harness/*
新增上下文分层、入口文件维护、settings scope 与工具规则等方法论文档。
上手与接入
docs/develop/setup/*, docs/develop/one_dragon/*
新增 quickstart、AI coding、提交 trailer、公共包同步与 RuntimeLauncher 架构/同步文档。
Skills 规范
skills/sr-od-dev-*/*
新增修复决策、PR 收尾与 skill 编写规范文档。

Estimated code review effort: 5 (Critical) | ~150 minutes

打包、清单与后端服务

Layer / File(s) Summary
模块清单生成
config/project.yml, deploy/*manifest*, deploy/hook_path_inject.py
新增 manifest 路径配置、依赖扫描脚本、PyInstaller hook 与自动生成的模块清单。
集成启动器与构建
deploy/OneDragon-RuntimeLauncher.spec, deploy/build_full.bat, src/sr_od/win_exe/runtime_launcher.py
新增集成启动器打包配置、完整构建脚本与启动入口。
后端服务与 daemon
src/sr_od/backend/*, tools/mcp/daemon/*
新增 sr_od 后端上下文、MCP/HTTP 适配器、服务入口与远程 daemon 管理脚本。

Estimated code review effort: 5 (Critical) | ~150 minutes

核心框架、通知、画面、OCR 与 UI

Layer / File(s) Summary
通知配置与发送
src/one_dragon/base/config/*, src/one_dragon/base/operation/*
通知配置迁移为生命周期/节点细节二维模式,并调整通知池与发送逻辑。
画面 Scope 与匹配
src/one_dragon/base/screen/*
画面加载支持 app_id、插件 screen 与 scope 过滤,并新增强化版画面匹配。
OCR 与 GPU 执行
src/one_dragon/base/matcher/ocr/*, src/one_dragon/utils/gpu_executor.py, src/one_dragon/yolo/*, src/onnxocr/*
重命名 OCR GPU 配置并重构 ONNX/OCR 执行、供应商与推理链路。
基础设施修复
src/one_dragon/envs/*, src/one_dragon/utils/*, src/one_dragon/base/controller/*
修复 Git 拉取进度、HTTP 下载、日志装配、YAML 幂等写入、点击延迟与版本字符串清洗。
Qt 视图与组件
src/one_dragon_qt/*
统一滚动组件为 FastScrollArea,并新增应用通知设置、密码开关与若干 UI 交互改动。

Estimated code review effort: 5 (Critical) | ~180 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant server as sr_od.backend.entry.server
    participant backend as SrBackendContext
    participant runslot as RunSlot
    participant ctx as SrContext

    Client->>server: /game/enter 或 open_and_enter_game
    server->>backend: start_run(source, op_factory)
    backend->>runslot: _start_run(source, op_factory)
    runslot->>ctx: run_context.start_running()
    runslot->>runslot: 执行 Operation
    runslot-->>backend: Future / 运行结果
    backend-->>server: 运行状态或结果
    server-->>Client: JSON / 文本响应
Loading
sequenceDiagram
    participant Operation
    participant notify as operation_notify
    participant config as NotifyConfig
    participant pool as NotifyPool
    participant channel as 通知渠道

    Operation->>notify: send_node_notify(operation, node)
    notify->>config: get_app_lifecycle_mode / get_app_detail_mode
    config-->>notify: NotifyLifecycleMode, NotifyDetailMode
    alt detail_mode = MERGE
        notify->>pool: 追加节点消息
    else detail_mode = ALL/ERROR_ONLY
        notify->>channel: 立即推送节点通知
    end
    Operation->>notify: send_application_notify(app, result)
    notify->>pool: 读取合并消息与图片
    notify->>channel: push_merged_async / push_async
Loading

Estimated code review effort: 5 (Critical) | ~480 minutes

Poem

我是一只小兔兔,跳进代码丛林里,
文档、打包、后端路,咕噜咕噜全整理。
滚轮换成新飞轮,通知开关更细腻,
OCR、日志与下载,统统都要稳稳地。
评审大人请轻踩,胡萝卜已备齐 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题覆盖了本次变更的主要主题:MCP 后端运行态、AI 编码 harness、Runtime 启动器和开发技能,且语义清晰。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mcp-and-harness-infra

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Caution

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

⚠️ Outside diff range comments (2)
src/one_dragon/base/screen/template_loader.py (1)

45-54: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

恢复按 only_mask 区分的存在性校验

need_raw=False 会让 only_mask=Falseget_template() 也接受缺少原图的模板;而后续特征匹配、二值化匹配和裁剪匹配都直接依赖 TemplateInfo.raw,这会把不完整模板带入运行时并在 template.raw.shape / to_binary(template.raw) 等路径上出错。

🐛 建议恢复原有逻辑
-        if not is_template_existed(sub_dir, template_id, need_raw=False):
+        if not is_template_existed(sub_dir, template_id, need_raw=not only_mask):
             return 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 `@src/one_dragon/base/screen/template_loader.py` around lines 45 - 54, The
existence check in load_template is no longer respecting only_mask, so non-mask
loads can admit templates without a raw image. Update load_template to pass
need_raw based on only_mask (or equivalent logic) when calling
is_template_existed, so get_template and downstream users of TemplateInfo.raw
continue to reject incomplete templates. Keep the fix localized to load_template
and the template existence validation path.
src/one_dragon/base/config/yaml_operator.py (1)

103-131: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

file_path 回写提前到内容比较之前

_copy_on_write_source_path 场景下,save() 先把配置复制到可写的 write_path,但一旦内容相同就直接返回,self.file_path 仍停留在 sample/资源路径。后续 is_file_existsdelete() 之类的逻辑会继续指向旧路径。
建议在内容比较前先同步 self.file_path / old_file_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 `@src/one_dragon/base/config/yaml_operator.py` around lines 103 - 131, In
`YamlOperator.save`, the in-memory path state is updated too late, so when
`_copy_on_write_source_path` resolves to a writable `write_path` and the content
is unchanged, `self.file_path` and `old_file_path` can remain on the original
sample/resource path. Move the `file_path`/`old_file_path` synchronization to
happen immediately after `write_path` is determined and before the old/new
content comparison, keeping the path state aligned even when `save()` returns
early.
🧹 Nitpick comments (22)
src/one_dragon/base/screen/screen_loader.py (2)

165-174: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

load_extra_screen_dir 参数建议直接使用 Path 类型。

调用方 _load_plugin_screensscreen_dir 本身已经是 Path 对象,却被 str() 转换后再传入本函数重新构造为 Path,存在不必要的往返转换。

♻️ 建议的修复
-    def load_extra_screen_dir(self, dir_path: str, default_app_id: str = '') -> None:
+    def load_extra_screen_dir(self, dir_path: Path, default_app_id: str = '') -> None:
         """从额外目录加载 screen YAML 并注册(用于插件 screen 注入)

         加载后会重新计算路由和全局 screen 集合。

         Args:
-            dir_path: 包含 screen YAML 文件的目录路径
+            dir_path: 包含 screen YAML 文件的目录路径(Path)
             default_app_id: 如果 YAML 中未设置 app_id,使用此默认值
         """
-        screen_dir = Path(dir_path)
+        screen_dir = dir_path
         if not screen_dir.is_dir():
             return

As per coding guidelines, **/*.{py,pyi}: "路径操作使用 pathlib,字符串格式化使用 f-string。"

🤖 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 `@src/one_dragon/base/screen/screen_loader.py` around lines 165 - 174,
`load_extra_screen_dir` is forcing a Path-to-str-to-Path round trip even though
`_load_plugin_screens` already has a Path, so update the API to accept and use a
Path directly. Change `load_extra_screen_dir` to take a `Path` argument instead
of `str`, remove the redundant `Path(...)` conversion inside the method, and
adjust the call site in `_load_plugin_screens` to pass the existing `screen_dir`
through unchanged.

Source: Coding guidelines


244-310: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

插件画面重命名场景下会触发重复 reload。

save_screen 在处理普通画面重命名时会先 delete_screen(old_id, save=False)(内部已执行一次 reload(from_memory=True)),随后又调用 self.save(...)(默认 reload_after_save=True,内部再执行一次 reload(from_memory=True))。两次 reload 都会重算 init_screen_route()(Floyd-Warshall,O(n³))和 _global_screen_names。该路径仅在管理界面手动重命名/保存画面时触发,频率低,实际影响有限。

🤖 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 `@src/one_dragon/base/screen/screen_loader.py` around lines 244 - 310,
save_screen is triggering two reloads during a normal screen rename:
delete_screen(..., save=False) already calls reload(from_memory=True), then
self.save(...) triggers another reload via its default save flow. Update
save_screen to avoid the redundant second reload for the rename path, either by
saving without reload or by adding a way to skip reload_after_save in the save
call, while keeping _save_extra_screen and delete_screen behavior unchanged.
tools/mcp/daemon/create_startup_shortcut.ps1 (1)

33-44: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

建议用 try/finally 包裹 COM 对象生命周期。

$ErrorActionPreference = "Stop" 触发的异常发生在 New-Object 之后、ReleaseComObject 之前(例如快捷方式保存失败),COM 对象将不会被释放。脚本进程退出时系统通常会回收,实际影响很小。

♻️ 建议的修复
-$WshShell = New-Object -ComObject WScript.Shell
-
-# Create shortcut
-$Shortcut = $WshShell.CreateShortcut($ShortcutPath)
-$Shortcut.TargetPath = "powershell.exe"
-$Shortcut.Arguments = "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$StartDaemonScript`""
-$Shortcut.WorkingDirectory = $ProjectRoot
-$Shortcut.Description = "SR OD MCP Server Daemon - Manages game operation server lifecycle"
-$Shortcut.Save()
-
-# Release COM object
-[System.Runtime.Interopservices.Marshal]::ReleaseComObject($WshShell) | Out-Null
+$WshShell = New-Object -ComObject WScript.Shell
+try {
+    $Shortcut = $WshShell.CreateShortcut($ShortcutPath)
+    $Shortcut.TargetPath = "powershell.exe"
+    $Shortcut.Arguments = "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$StartDaemonScript`""
+    $Shortcut.WorkingDirectory = $ProjectRoot
+    $Shortcut.Description = "SR OD MCP Server Daemon - Manages game operation server lifecycle"
+    $Shortcut.Save()
+} finally {
+    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WshShell) | Out-Null
+}
🤖 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 `@tools/mcp/daemon/create_startup_shortcut.ps1` around lines 33 - 44, Wrap the
WScript.Shell COM object lifecycle in a try/finally block in
create_startup_shortcut.ps1 so the object is always released even if
CreateShortcut, Save, or another step fails under $ErrorActionPreference =
"Stop". Keep the shortcut creation logic in the try section around $WshShell,
$Shortcut, and $Shortcut.Save(), and move the ReleaseComObject call for
$WshShell into the finally section with a null check.
src/one_dragon_qt/widgets/app_run_list.py (1)

106-113: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

通知可见性判断逻辑重复三处,建议抽取公共方法。

app.app_id in self.ctx.notify_config.app_map 这条表达式在本文件的 _update_existing_cards(Line 112)与 _create_new_cards(Line 155)中各出现一次,另外在 one_dragon_run_interface.py_update_setting_btn_visibility 中也重复出现同样逻辑。三处保持一致依赖人工同步,建议抽取为共享方法(如 NotifyConfig.is_app_enabled(app_id)AppRunList._is_notify_visible(app_id)),减少后续修改遗漏的风险。

♻️ 提议的重构方向
+    def _is_notify_visible(self, app_id: str) -> bool:
+        return app_id in self.ctx.notify_config.app_map
+
     def _update_existing_cards(...):
         ...
-                card.set_notify_visible(app.app_id in self.ctx.notify_config.app_map)
+                card.set_notify_visible(self._is_notify_visible(app.app_id))

Also applies to: 129-156

🤖 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 `@src/one_dragon_qt/widgets/app_run_list.py` around lines 106 - 113, The notify
visibility check is duplicated across AppRunList and the run interface, so
extract it into one shared helper and reuse it everywhere. Add a single method
such as NotifyConfig.is_app_enabled(app_id) or
AppRunList._is_notify_visible(app_id), then replace the repeated app.app_id in
self.ctx.notify_config.app_map checks in _update_existing_cards,
_create_new_cards, and _update_setting_btn_visibility with that helper to keep
behavior consistent.
docs/develop/setup/claude-code/commit-trailer.md (1)

131-136: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

补充围栏代码块的语言标注。

markdownlint 提示该处围栏代码块缺少语言声明(MD040)。

📝 修复建议
-```
+```text
 <你的提交标题>
🤖 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 `@docs/develop/setup/claude-code/commit-trailer.md` around lines 131 - 136, The
fenced code block in commit-trailer.md is missing a language identifier,
triggering markdownlint MD040. Update the fenced block that contains the commit
title and Co-Authored-By lines to include an explicit language tag (use the same
identifier shown in the review, via the markdown fence in that section) so the
block is properly annotated and lint passes.

Source: Linters/SAST tools

src/onnxocr/inference_engine.py (2)

157-161: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

路径操作应使用 pathlib

As per coding guidelines, **/*.{py,pyi}: "路径操作使用 pathlib,字符串格式化使用 f-string。" 此处仍用 os.path.exists

♻️ 建议修复
+from pathlib import Path
...
-    if not os.path.exists(model_path):
+    if not Path(model_path).exists():
🤖 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 `@src/onnxocr/inference_engine.py` around lines 157 - 161, The model existence
check in `inference_engine.py` still uses `os.path.exists`, which violates the
pathlib path-handling guideline. Update the path check in the same block that
raises `FileNotFoundError` to use `pathlib.Path`-based operations instead,
keeping the existing `model_path` logic and error message behavior intact. Use
the relevant `model_path` handling in `inference_engine.py` so the code
consistently follows the project’s pathlib convention.

Source: Coding guidelines


71-77: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

docstring 使用英文,违反中文注释规范。

As per coding guidelines, **/*.{py,pyi}: "注释与 docstring 必须使用中文,保持现有项目风格。" 这三处 docstring(build_providers_from_engine_cfgProviderConfig_default_session_options)均为英文。

Also applies to: 94-96, 139-143

🤖 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 `@src/onnxocr/inference_engine.py` around lines 71 - 77, 当前多个 docstring
仍使用英文,需按项目规范统一改为中文;请在 build_providers_from_engine_cfg、ProviderConfig 和
_default_session_options 这几个符号对应的 docstring 中,将说明性文本改写为中文,并保持含义一致、风格统一,确保整个
Python 文件的注释与 docstring 都符合中文注释规范。

Source: Coding guidelines

src/one_dragon/yolo/onnx_model_loader.py (1)

163-164: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

run_session 缺少返回类型注解。

As per coding guidelines, **/*.{py,pyi}: "所有函数签名与类成员变量都必须有类型注解。" input_feed: dict 也建议补充泛型参数(如 dict[str, Any])。

♻️ 建议修复
-    def run_session(self, output_names: list[str], input_feed: dict):
+    def run_session(self, output_names: list[str], input_feed: dict[str, Any]) -> Any:
         return gpu_executor.run_session(self.session, output_names, input_feed=input_feed)
🤖 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 `@src/one_dragon/yolo/onnx_model_loader.py` around lines 163 - 164, The
run_session method in OnnxModelLoader is missing an explicit return type
annotation, and its input_feed parameter should use a fully typed mapping
instead of a bare dict. Update the run_session signature to include a precise
return annotation matching gpu_executor.run_session’s result, and change
input_feed to a generic form such as dict[str, Any] (or the most accurate typed
mapping used in this module) while keeping the existing output_names annotation
intact.

Source: Coding guidelines

src/one_dragon_qt/view/code_interface.py (1)

74-79: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

两处 auto_update_code_opt 卡片配置重复。

setting_env_interface.py 与本文件对同一设置(图标、标题、password_hashreverse_mode)各写一份完全相同的初始化代码,未来修改密码或文案需要同步两处,存在漂移风险。可考虑抽取共享工厂函数(如 build_auto_update_code_card())复用。该模式在 force_update_opt 上已有先例,非本次新增紧迫问题,优先级较低。

🤖 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 `@src/one_dragon_qt/view/code_interface.py` around lines 74 - 79,
`auto_update_code_opt` is initialized with the same icon, title, password_hash,
and reverse_mode in multiple places, creating duplicated configuration that can
drift over time. Refactor the setup in `CodeInterface` to reuse a shared
factory/helper, similar to the existing `force_update_opt` pattern, so the
`auto_update_code_opt` card is built from one source of truth rather than
repeated inline initialization.
src/one_dragon/base/controller/pc_controller_base.py (1)

528-528: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

pos 参数类型标注未使用现代 X | Y 语法,与同文件其余函数不一致。

同文件 _foreground_click(Line 293)、_background_click(Line 355)均为 pos: Point | None,此处 win_click 仍是 pos: Point = None

♻️ 建议修复
-def win_click(pos: Point = None, press_time: float = 0.1, primary: bool = True):
+def win_click(pos: Point | None = None, press_time: float = 0.1, primary: bool = True):

As per coding guidelines, **/*.{py,pyi}: "优先使用 list[str]X | Y 这类现代类型语法。"

🤖 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 `@src/one_dragon/base/controller/pc_controller_base.py` at line 528, Update the
win_click function signature to use the modern optional type syntax for pos so
it matches _foreground_click and _background_click in pc_controller_base.py;
change the annotation from Point = None to Point | None while keeping the same
default value and other parameters unchanged.

Source: Coding guidelines

deploy/hook_path_inject.py (1)

12-25: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

建议为 _src 增加存在性校验,快速失败而非深层晦涩报错。

当前若 _srcsys.executable 同级 src/ 目录)因打包遗漏或部署路径变化而不存在,import one_dragon.xxx 等后续导入会在深层代码处以难以定位的 ImportError 失败。作为集成启动器的关键引导路径,建议在此提前显式校验并给出清晰报错信息。

♻️ 建议的防御性校验
 _src = Path(sys.executable).parent / "src"
+if not _src.is_dir():
+    raise RuntimeError(f"未找到运行时源码目录: {_src},请检查打包产物是否完整")

 sys.path.insert(0, str(_src))
🤖 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 `@deploy/hook_path_inject.py` around lines 12 - 25, Add an explicit existence
check for _src in hook_path_inject.py before mutating sys.path or importing
one_dragon; if the sys.executable-relative src directory is missing, fail fast
with a clear error message instead of letting later import one_dragon /
one_dragon.launcher calls raise a deeper ImportError. Keep the fix localized
around the _src setup block so the startup path clearly reports the missing
deployment directory.
src/sr_od/backend/mcp/app.py (1)

35-52: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

截图落盘无清理机制,长期运行可能占用磁盘空间。

_save_screenshot 每次调用都生成带时间戳的新文件,当前无过期清理或数量上限,长期运行的 daemon/主 server 可能导致 .debug/sr_od_mcp/screenshot 目录无限增长。

🤖 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 `@src/sr_od/backend/mcp/app.py` around lines 35 - 52, The _save_screenshot
helper in app.py always creates a new timestamped file and never removes old
screenshots, so the .debug/sr_od_mcp/screenshot directory can grow without
bound. Add a cleanup policy inside or alongside _save_screenshot (or in the
screenshot directory management path) to enforce either a retention window or a
maximum file count, and delete older files before or after writing the new
image. Keep the existing screenshot naming and write flow, but make sure the
cleanup runs reliably in the long-lived MCP server process.
src/sr_od/backend/entry/server.py (1)

57-68: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

建议保留启动/运行期异常的完整上下文。

finally 中的 backend.shutdown() 若自身抛出异常,会覆盖 backend.start()/server.serve() 的原始异常,不利于日志排障(daemon 场景下用户只能通过日志文件定位,见 remote-ssh.md 排查小节)。建议在异常路径显式记录原始异常。

♻️ 建议的修改
     try:
         log.info("SR 后端:初始化 SrContext(线程池,不阻塞事件循环)……")
         await backend.start()
         app = create_app(backend)
         config = uvicorn.Config(app, host=host, port=port, log_level="info")
         server = uvicorn.Server(config)
         log.info(f"SR 后端监听: http://{host}:{port}/mcp 与 /game/*")
         await server.serve()
+    except Exception:
+        log.error("SR 后端异常退出", exc_info=True)
+        raise
     finally:
         await backend.shutdown()
🤖 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 `@src/sr_od/backend/entry/server.py` around lines 57 - 68, 启动/运行期异常会被最终的
backend.shutdown() 覆盖,导致 backend.start() 或 server.serve() 的原始错误上下文丢失。请在
SrContext/SrBackendContext 的启动流程中,把 shutdown 放到独立的异常处理里,先记录并保留 start/serve
期间的原始异常,再执行清理。重点检查 await backend.start()、await server.serve() 和 finally 中的 await
backend.shutdown(),确保 shutdown 失败不会吞掉前一个异常,并在异常路径显式写入日志。
tools/mcp/daemon/start_daemon.ps1 (1)

39-44: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

try/catch 无法可靠捕获 daemon 启动失败。

原生进程(uv/python)以非零退出码退出时不会抛出 PowerShell 终止性错误,try/catch 大概率捕获不到真实的启动失败,只能捕获类似"命令找不到"这类情况。建议显式检查 $LASTEXITCODE

🔧 建议修复
 try {
     uv run --env-file .env python $DaemonScript --host $HostName --port $Port
+    if ($LASTEXITCODE -ne 0) {
+        Write-Host "[ERROR] Daemon 进程退出码非零: $LASTEXITCODE" -ForegroundColor Red
+        exit $LASTEXITCODE
+    }
 } catch {
     Write-Host "[ERROR] Daemon 启动失败: $_" -ForegroundColor Red
     exit 1
 }
🤖 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 `@tools/mcp/daemon/start_daemon.ps1` around lines 39 - 44, The daemon launch in
start_daemon.ps1 relies on try/catch around uv run, but that won’t reliably
catch native process failures from uv/python. Update the startup flow to invoke
the existing daemon launch command, then explicitly inspect $LASTEXITCODE after
uv run completes and treat any non-zero value as a startup failure. Keep the
current error reporting in the daemon-start script, but move the failure
handling to the exit-code check so the script reliably reports and exits when
the daemon fails to start.
src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py (1)

42-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

新增函数使用 os.path.join,未遵循 pathlib 规范。

get_ocr_model_dict_nameget_final_file_list 均为本次新增代码,但仍使用 os.path.exists/os.listdir/os.path.join

♻️ 建议改为 pathlib
-def get_ocr_model_dict_name(ocr_model_name: str) -> str | None:
-    base_dir = get_ocr_model_dir(ocr_model_name)
-    if os.path.exists(base_dir):
-        for f in os.listdir(base_dir):
-            if f.endswith('_dict.txt'):
-                return f
-    return None
+def get_ocr_model_dict_name(ocr_model_name: str) -> str | None:
+    base_dir = Path(get_ocr_model_dir(ocr_model_name))
+    if base_dir.exists():
+        for f in sorted(base_dir.iterdir()):
+            if f.name.endswith('_dict.txt'):
+                return f.name
+    return None

Based on path instructions: "**/*.{py,pyi}: ...路径操作使用 pathlib,字符串格式化使用 f-string。"

🤖 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 `@src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py` around lines 42 - 70,
The new OCR helper functions `get_ocr_model_dict_name` and `get_final_file_list`
are still using `os.path` APIs for directory checks, listing, and path assembly,
which violates the pathlib style guideline. Update these helpers to use
`Path`-based operations throughout: resolve the model directory with the
existing `get_ocr_model_dir` flow, iterate directory contents via
`Path.iterdir()` or equivalent, and build the final file list with `Path` joins
instead of string-based path concatenation. Keep the function behavior unchanged
while aligning the implementation with the project’s pathlib convention.

Sources: Coding guidelines, Path instructions

src/one_dragon/devtools/python_launcher.py (2)

297-301: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

app_path 参数缺少类型注解。

本行在本次改动中被修改(args 类型更新为 list[str] | None),但 app_path 仍未标注类型。As per path instructions, "所有函数签名与类成员变量都必须有类型注解"。建议一并补充(如 app_path: strPath,视实际调用方而定)。

🤖 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 `@src/one_dragon/devtools/python_launcher.py` around lines 297 - 301, The issue
is that `run_python` now has a partially typed signature, but `app_path` still
lacks a type annotation even though this codebase requires all function
parameters to be annotated. Update the `run_python` function signature to add
the appropriate type for `app_path` (for example `str` or `Path`, matching its
actual use elsewhere) and keep the existing `args: list[str] | None` annotation
consistent with the rest of the function.

Source: Path instructions


54-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

补充 create_git_progress_callback 的返回类型注解。

As per path instructions, "所有函数签名与类成员变量都必须有类型注解,优先使用 list[str]X | Y 这类现代类型语法。" 当前函数缺少返回类型标注。

♻️ 建议补充类型注解
-def create_git_progress_callback():
+def create_git_progress_callback() -> Callable[[float, str], None]:
     def _report(_progress: float, message: str) -> None:
         refresh = message.startswith(gt('拉取对象')) and not message.endswith('(100%)')
         print_message(message, 'INFO', flush=refresh)
     return _report

(需要 from collections.abc import Callable

🤖 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 `@src/one_dragon/devtools/python_launcher.py` around lines 54 - 59, The
create_git_progress_callback function is missing an explicit return type
annotation. Update the function signature to declare that it returns a Callable
matching the nested _report callback’s parameter and return types, and make sure
the needed Callable import from collections.abc is added or reused. Keep the
internal _report logic unchanged and let the annotation clearly reflect the
callback shape.

Source: Path instructions

src/onnxocr/logger.py (1)

23-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

四个方法体几乎完全重复,可提取公共逻辑。

info/debug/warning/error 均是"按需 .format() + 前缀 + 转发到 od_log"的重复模式,可抽出一个内部 _dispatch 辅助方法减少重复。

♻️ 参考重构
+    def _dispatch(self, level_fn, msg: str, *args: Any, **kwargs: Any) -> None:
+        if args or kwargs:
+            msg = str(msg).format(*args, **kwargs)
+        level_fn(self._format(msg))
+
     def info(self, msg: str, *args: Any, **kwargs: Any) -> None:
-        if args or kwargs:
-            msg = str(msg).format(*args, **kwargs)
-        od_log.info(self._format(msg))
+        self._dispatch(od_log.info, msg, *args, **kwargs)
🤖 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 `@src/onnxocr/logger.py` around lines 23 - 41, The info, debug, warning, and
error methods in Logger重复了相同的“按需 format + _format 前缀 + 转发到
od_log”逻辑,建议抽出一个内部辅助方法来统一处理。请在 Logger 类中新增一个私有 dispatch/helper(例如负责接收
level、msg、args、kwargs 并调用 od_log),然后让 info/debug/warning/error
只保留各自的级别入口并复用该公共逻辑,保持现有行为不变。
src/one_dragon_qt/widgets/color_channel_dialog.py (1)

132-134: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

channels/channel_names 语义上应始终等长,strict=True 更能表达意图。

三个色彩空间通道与通道名始终是一一对应的三元组,理论上永不会出现长度不一致;用 strict=True 既能满足 Ruff B905,又能在未来重构引入不等长数据时及早暴露错误,比 strict=False(静默截断)更安全。

♻️ 建议调整
-        for channel, name in zip(channels, channel_names, strict=False):
+        for channel, name in zip(channels, channel_names, strict=True):
🤖 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 `@src/one_dragon_qt/widgets/color_channel_dialog.py` around lines 132 - 134,
The loop in ColorChannelDialog that iterates over channels and channel_names
should assume they are always paired, so update the zip call in the
widget-building logic to use strict pairing instead of silent truncation. Keep
the change in the channel creation path that uses _create_channel_widget and
channels_layout.addWidget so any future mismatch between channels and
channel_names fails fast and aligns with the intended one-to-one mapping.
src/one_dragon/utils/cv2_utils.py (1)

1283-1286: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

清理遗留的调试注释代码

# save_image(img, 'y:\\debug.png')# is_colorful(img) 属于调试遗留代码,建议移除以保持代码整洁。

🤖 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 `@src/one_dragon/utils/cv2_utils.py` around lines 1283 - 1286, Remove the
leftover debug-only commented calls in the cv2_utils logic around the confidence
logging, specifically the commented save_image and is_colorful lines near the
percent/log.debug statements. Keep the functional code that computes percent and
logs the gray mask confidence, but delete the unused debug comments so the
surrounding utility code stays clean and maintainable.
src/one_dragon_qt/widgets/app_setting/app_notify_setting_flyout.py (1)

101-136: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

避免直接读写兄弟类的 _current_tip
这里把“当前弹窗”状态分散在 AppNotifySettingFlyoutAppSettingFlyout 两个类里,后续新增 flyout 时还要同步改多处。建议抽一个共享管理器或公共基类属性统一维护这份状态。

🤖 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 `@src/one_dragon_qt/widgets/app_setting/app_notify_setting_flyout.py` around
lines 101 - 136, The current flyout state is being duplicated and directly
mutated across both AppNotifySettingFlyout and AppSettingFlyout, which makes the
shared “current tip” handling fragile. Refactor show_flyout to use a single
shared owner for this state, such as a common base class property or a small
flyout manager, and update the close/reset logic plus destroyed cleanup to read
and write only that shared location instead of touching the sibling class
directly.
deploy/OneDragon-RuntimeLauncher.spec (1)

15-29: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议改用 SPEC_DIR 定位路径 deploy/build_full.bat 已经先切到脚本目录再调用 PyInstaller,所以当前写法在这条入口下可用;不过 Path.cwd() 仍依赖工作目录,改成 SPEC/SPEC_DIR 后更稳妥。

🤖 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 `@deploy/OneDragon-RuntimeLauncher.spec` around lines 15 - 29, The path
resolution in OneDragon-RuntimeLauncher.spec still relies on Path.cwd(), which
can break when the spec is invoked from a different working directory. Update
the path setup near REPO_ROOT, SRC_DIR, and GEN_PATH to use PyInstaller’s
SPEC/SPEC_DIR-based location instead of the current working directory, keeping
the existing KEEP_TREES and generate_module_manifest import flow intact.
🤖 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 `@deploy/build_full.bat`:
- Around line 11-28: The build script in build_full.bat copies project.yml into
the config subdirectory, but the config folder is never created first, so the
file may not land in the intended package path. Update the packaging steps
around TARGET_DIR and the final copy of project.yml to ensure
"%TARGET_DIR%\config" exists before copying, so the config file is placed
correctly alongside the other bundled assets.

In `@docs/develop/one_dragon/common-package-sync.md`:
- Line 92: The table row in the documentation contains a bare pipe inside the
example command, which breaks Markdown column parsing. Update the affected table
entry so the `|` in the `netstat | findstr :2300` example is escaped or
otherwise protected, using the existing table row near the port-fragment
guidance to keep the column count consistent and avoid markdownlint errors.

In `@src/one_dragon_qt/view/one_dragon/one_dragon_run_interface.py`:
- Around line 289-301: The helper methods `_find_app_card_setting_btn` and
`_find_app_card_notify_btn` are missing explicit return type annotations, which
violates the project’s typing requirements. Update both method signatures in
`OneDragonRunInterface` to declare the return type as `QWidget | None`, matching
the fact that they either return a button widget from `card.setting_btn` /
`card.more_btn` or `None` when no matching card is found.

In `@src/one_dragon/base/config/yaml_operator.py`:
- Around line 113-118: The old-content read in yaml_operator.py is swallowing
all exceptions with a silent pass, which hides useful diagnostics. In the block
that reads write_path in the old_content flow, keep the try/except but replace
the bare exception handling with at least a debug-level log that records the
failure context and exception details, using the existing logger or logging
pattern in yaml_operator.py. Make the change around the read/compare logic so
future issues in this path can be traced without changing the behavior of
falling back to old_content being None.

In `@src/one_dragon/base/operation/application_base.py`:
- Around line 82-90: `Application.execute()` is clearing the active screen scope
unconditionally, which breaks nested `execute()` calls such as
`OneDragonApp.run_group_app()` invoking `GroupApplication`. Update the scope
management in `Application.execute()` and the related `screen_loader` handling
so nested executions save and restore the previous scope (stack-like behavior)
instead of always calling a plain `exit_scope()`, or limit scope enter/exit to
the top-level entry path only.

In `@src/one_dragon/base/screen/screen_loader.py`:
- Around line 430-447: The early-return comment in enter_scope is inverted
relative to the actual _global_screen_names check. Update the comment to match
the real condition in ScreenLoader.enter_scope: when _global_screen_names is
empty, it means there are no global screens and every screen has an app_id, so
scope should not be enabled. Keep the logic as-is unless you intend to change
behavior, and make the wording consistent with the ScreenInfo/app_id and
_global_screen_names semantics.

In `@src/one_dragon/utils/cv2_utils.py`:
- Around line 1240-1279: Add the same input-shape validation used by is_colorful
to is_in_gray_mask so only 3-channel images are processed; currently grayscale
or other non-RGB inputs can be reduced along the wrong axis and return a
misleading result. Update is_in_gray_mask to check img.shape before the
cond1/cond2 calculations, and return False for non-3-channel inputs so the
crop_image and mask logic only runs on valid RGB data.

In `@src/one_dragon/utils/gpu_executor.py`:
- Around line 56-68: `should_serialize_session` 和 `run_session`
这两个函数缺少完整的参数与返回值类型注解,需要按本文件中 `create_onnx_session`、`should_serialize_providers`
的风格补齐;为 `session`、`output_names`、`input_feed` 以及 `**kwargs` 添加合适的现代类型注解,并显式从
`typing` 导入 `Any` 以标注可变参数/未知类型,保持整个 `gpu_executor.py` 的函数签名一致性。

In `@src/one_dragon/yolo/onnx_model_loader.py`:
- Line 37: The session attribute in OnnxModelLoader has a type/default mismatch
because self.session is initialized to None but annotated as
ort.InferenceSession only. Update the self.session declaration in the
OnnxModelLoader class to use an optional union type such as ort.InferenceSession
| None so it matches the None default and stays consistent with pyright-clean
typing rules.

In `@src/onnxocr/onnx_paddleocr.py`:
- Around line 21-26: `_normalize_ppocrv6_size` currently ignores its
`model_size` argument and always collapses any `ppocrv6` model to `small`, which
makes the size API misleading. Update `_normalize_ppocrv6_size` and
`_build_ppocrv6_defaults` so the returned size is either explicitly restricted
to `small` or mapped from `model_size` to distinct model paths; do not silently
overwrite caller input. Apply the same fix pattern in `OnnxOcrParam.__init__` in
`onnx_ocr_matcher.py`, where the unconditional override should be replaced with
size-aware selection or a clear single-size constraint.

In `@src/onnxocr/predict_base.py`:
- Around line 49-50: `run_onnx_session` is missing required type annotations for
its parameters and return value, unlike `get_onnx_session` in the same class.
Update the `run_onnx_session` signature in `predict_base.py` to annotate
`onnx_session`, `output_names`, and `input_feed`, and add an explicit return
type using modern typing syntax consistent with the rest of `BasePredict`.

In `@src/onnxocr/predict_cls.py`:
- Around line 19-27: The warmup path in predict_cls.py bypasses the new
run_onnx_session wrapper by calling cls_onnx_session.run directly. Update the
classifier warmup in the relevant initializer to use self.run_onnx_session
instead, so it follows the same gpu_executor submission path as normal inference
and avoids keeping a direct session-run entry point. Use the existing symbols
cls_onnx_session and run_onnx_session to locate and align the call site.

In `@src/onnxocr/predict_det.py`:
- Around line 51-59: The warm-up inference in predict_det.py bypasses the shared
ONNX execution wrapper, so update the detection model initialization flow in the
relevant predictor class to use run_onnx_session instead of calling
self.det_onnx_session.run directly. Keep the warm-up dummy input logic, but
route it through the same execution path used by predict_cls.py and
predict_rec.py so the ONNX session is submitted via
one_dragon.utils.gpu_executor.submit and does not directly invoke multiple
sessions concurrently.

In `@src/onnxocr/predict_rec.py`:
- Around line 220-223: The `resize_norm_img_spin` method is passing
`cv2.INTER_CUBIC` as the third positional argument to `cv2.resize`, which binds
it to `dst` instead of `interpolation`; update this call in
`resize_norm_img_spin` to use the `interpolation` keyword argument so the resize
uses cubic interpolation correctly.
- Around line 25-33: The warm-up path in the recognition model bypasses the new
`run_onnx_session` wrapper by calling `self.rec_onnx_session.run(...)` directly,
which skips the `gpu_executor` path used by normal inference. Update the warm-up
logic in `PredictRec` to invoke `run_onnx_session` instead of calling the ONNX
session directly, so both warm-up and regular inference follow the same
execution flow and concurrency handling.

In `@src/sr_od/backend/backend_context.py`:
- Around line 67-70: SrBackendContext.shutdown() currently only runs
after_app_shutdown() and leaves the RunSlot work and its ThreadPoolExecutor
alive, which can keep the process from exiting; update the shutdown path in
SrBackendContext to first stop/cancel any active run_slot operations, then shut
down the executor created in __init__ using shutdown(cancel_futures=True) for
Python 3.11.9+, and keep the cleanup order explicit so backend tasks are
terminated before after_app_shutdown() completes.

In `@tools/mcp/daemon/sr_od_daemon.py`:
- Around line 28-44: `find_sr_od_mcp_server_process` uses a loose substring
check on each argv element, which can misidentify unrelated processes and break
`stop_sr_od_mcp_server`/`restart_sr_od_mcp_server`. Update the matching logic to
look for the exact module-launch argv pattern for `sr_od.backend.entry.server`
(for example, an explicit `-m` plus module name pair, or another exact argv
sequence used by the daemon), and keep the search limited to
`proc.info['cmdline']` in this function so only the intended server process is
returned.

---

Outside diff comments:
In `@src/one_dragon/base/config/yaml_operator.py`:
- Around line 103-131: In `YamlOperator.save`, the in-memory path state is
updated too late, so when `_copy_on_write_source_path` resolves to a writable
`write_path` and the content is unchanged, `self.file_path` and `old_file_path`
can remain on the original sample/resource path. Move the
`file_path`/`old_file_path` synchronization to happen immediately after
`write_path` is determined and before the old/new content comparison, keeping
the path state aligned even when `save()` returns early.

In `@src/one_dragon/base/screen/template_loader.py`:
- Around line 45-54: The existence check in load_template is no longer
respecting only_mask, so non-mask loads can admit templates without a raw image.
Update load_template to pass need_raw based on only_mask (or equivalent logic)
when calling is_template_existed, so get_template and downstream users of
TemplateInfo.raw continue to reject incomplete templates. Keep the fix localized
to load_template and the template existence validation path.

---

Nitpick comments:
In `@deploy/hook_path_inject.py`:
- Around line 12-25: Add an explicit existence check for _src in
hook_path_inject.py before mutating sys.path or importing one_dragon; if the
sys.executable-relative src directory is missing, fail fast with a clear error
message instead of letting later import one_dragon / one_dragon.launcher calls
raise a deeper ImportError. Keep the fix localized around the _src setup block
so the startup path clearly reports the missing deployment directory.

In `@deploy/OneDragon-RuntimeLauncher.spec`:
- Around line 15-29: The path resolution in OneDragon-RuntimeLauncher.spec still
relies on Path.cwd(), which can break when the spec is invoked from a different
working directory. Update the path setup near REPO_ROOT, SRC_DIR, and GEN_PATH
to use PyInstaller’s SPEC/SPEC_DIR-based location instead of the current working
directory, keeping the existing KEEP_TREES and generate_module_manifest import
flow intact.

In `@docs/develop/setup/claude-code/commit-trailer.md`:
- Around line 131-136: The fenced code block in commit-trailer.md is missing a
language identifier, triggering markdownlint MD040. Update the fenced block that
contains the commit title and Co-Authored-By lines to include an explicit
language tag (use the same identifier shown in the review, via the markdown
fence in that section) so the block is properly annotated and lint passes.

In `@src/one_dragon_qt/view/code_interface.py`:
- Around line 74-79: `auto_update_code_opt` is initialized with the same icon,
title, password_hash, and reverse_mode in multiple places, creating duplicated
configuration that can drift over time. Refactor the setup in `CodeInterface` to
reuse a shared factory/helper, similar to the existing `force_update_opt`
pattern, so the `auto_update_code_opt` card is built from one source of truth
rather than repeated inline initialization.

In `@src/one_dragon_qt/widgets/app_run_list.py`:
- Around line 106-113: The notify visibility check is duplicated across
AppRunList and the run interface, so extract it into one shared helper and reuse
it everywhere. Add a single method such as NotifyConfig.is_app_enabled(app_id)
or AppRunList._is_notify_visible(app_id), then replace the repeated app.app_id
in self.ctx.notify_config.app_map checks in _update_existing_cards,
_create_new_cards, and _update_setting_btn_visibility with that helper to keep
behavior consistent.

In `@src/one_dragon_qt/widgets/app_setting/app_notify_setting_flyout.py`:
- Around line 101-136: The current flyout state is being duplicated and directly
mutated across both AppNotifySettingFlyout and AppSettingFlyout, which makes the
shared “current tip” handling fragile. Refactor show_flyout to use a single
shared owner for this state, such as a common base class property or a small
flyout manager, and update the close/reset logic plus destroyed cleanup to read
and write only that shared location instead of touching the sibling class
directly.

In `@src/one_dragon_qt/widgets/color_channel_dialog.py`:
- Around line 132-134: The loop in ColorChannelDialog that iterates over
channels and channel_names should assume they are always paired, so update the
zip call in the widget-building logic to use strict pairing instead of silent
truncation. Keep the change in the channel creation path that uses
_create_channel_widget and channels_layout.addWidget so any future mismatch
between channels and channel_names fails fast and aligns with the intended
one-to-one mapping.

In `@src/one_dragon/base/controller/pc_controller_base.py`:
- Line 528: Update the win_click function signature to use the modern optional
type syntax for pos so it matches _foreground_click and _background_click in
pc_controller_base.py; change the annotation from Point = None to Point | None
while keeping the same default value and other parameters unchanged.

In `@src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py`:
- Around line 42-70: The new OCR helper functions `get_ocr_model_dict_name` and
`get_final_file_list` are still using `os.path` APIs for directory checks,
listing, and path assembly, which violates the pathlib style guideline. Update
these helpers to use `Path`-based operations throughout: resolve the model
directory with the existing `get_ocr_model_dir` flow, iterate directory contents
via `Path.iterdir()` or equivalent, and build the final file list with `Path`
joins instead of string-based path concatenation. Keep the function behavior
unchanged while aligning the implementation with the project’s pathlib
convention.

In `@src/one_dragon/base/screen/screen_loader.py`:
- Around line 165-174: `load_extra_screen_dir` is forcing a Path-to-str-to-Path
round trip even though `_load_plugin_screens` already has a Path, so update the
API to accept and use a Path directly. Change `load_extra_screen_dir` to take a
`Path` argument instead of `str`, remove the redundant `Path(...)` conversion
inside the method, and adjust the call site in `_load_plugin_screens` to pass
the existing `screen_dir` through unchanged.
- Around line 244-310: save_screen is triggering two reloads during a normal
screen rename: delete_screen(..., save=False) already calls
reload(from_memory=True), then self.save(...) triggers another reload via its
default save flow. Update save_screen to avoid the redundant second reload for
the rename path, either by saving without reload or by adding a way to skip
reload_after_save in the save call, while keeping _save_extra_screen and
delete_screen behavior unchanged.

In `@src/one_dragon/devtools/python_launcher.py`:
- Around line 297-301: The issue is that `run_python` now has a partially typed
signature, but `app_path` still lacks a type annotation even though this
codebase requires all function parameters to be annotated. Update the
`run_python` function signature to add the appropriate type for `app_path` (for
example `str` or `Path`, matching its actual use elsewhere) and keep the
existing `args: list[str] | None` annotation consistent with the rest of the
function.
- Around line 54-59: The create_git_progress_callback function is missing an
explicit return type annotation. Update the function signature to declare that
it returns a Callable matching the nested _report callback’s parameter and
return types, and make sure the needed Callable import from collections.abc is
added or reused. Keep the internal _report logic unchanged and let the
annotation clearly reflect the callback shape.

In `@src/one_dragon/utils/cv2_utils.py`:
- Around line 1283-1286: Remove the leftover debug-only commented calls in the
cv2_utils logic around the confidence logging, specifically the commented
save_image and is_colorful lines near the percent/log.debug statements. Keep the
functional code that computes percent and logs the gray mask confidence, but
delete the unused debug comments so the surrounding utility code stays clean and
maintainable.

In `@src/one_dragon/yolo/onnx_model_loader.py`:
- Around line 163-164: The run_session method in OnnxModelLoader is missing an
explicit return type annotation, and its input_feed parameter should use a fully
typed mapping instead of a bare dict. Update the run_session signature to
include a precise return annotation matching gpu_executor.run_session’s result,
and change input_feed to a generic form such as dict[str, Any] (or the most
accurate typed mapping used in this module) while keeping the existing
output_names annotation intact.

In `@src/onnxocr/inference_engine.py`:
- Around line 157-161: The model existence check in `inference_engine.py` still
uses `os.path.exists`, which violates the pathlib path-handling guideline.
Update the path check in the same block that raises `FileNotFoundError` to use
`pathlib.Path`-based operations instead, keeping the existing `model_path` logic
and error message behavior intact. Use the relevant `model_path` handling in
`inference_engine.py` so the code consistently follows the project’s pathlib
convention.
- Around line 71-77: 当前多个 docstring 仍使用英文,需按项目规范统一改为中文;请在
build_providers_from_engine_cfg、ProviderConfig 和 _default_session_options
这几个符号对应的 docstring 中,将说明性文本改写为中文,并保持含义一致、风格统一,确保整个 Python 文件的注释与 docstring
都符合中文注释规范。

In `@src/onnxocr/logger.py`:
- Around line 23-41: The info, debug, warning, and error methods in
Logger重复了相同的“按需 format + _format 前缀 + 转发到 od_log”逻辑,建议抽出一个内部辅助方法来统一处理。请在 Logger
类中新增一个私有 dispatch/helper(例如负责接收 level、msg、args、kwargs 并调用 od_log),然后让
info/debug/warning/error 只保留各自的级别入口并复用该公共逻辑,保持现有行为不变。

In `@src/sr_od/backend/entry/server.py`:
- Around line 57-68: 启动/运行期异常会被最终的 backend.shutdown() 覆盖,导致 backend.start() 或
server.serve() 的原始错误上下文丢失。请在 SrContext/SrBackendContext 的启动流程中,把 shutdown
放到独立的异常处理里,先记录并保留 start/serve 期间的原始异常,再执行清理。重点检查 await backend.start()、await
server.serve() 和 finally 中的 await backend.shutdown(),确保 shutdown
失败不会吞掉前一个异常,并在异常路径显式写入日志。

In `@src/sr_od/backend/mcp/app.py`:
- Around line 35-52: The _save_screenshot helper in app.py always creates a new
timestamped file and never removes old screenshots, so the
.debug/sr_od_mcp/screenshot directory can grow without bound. Add a cleanup
policy inside or alongside _save_screenshot (or in the screenshot directory
management path) to enforce either a retention window or a maximum file count,
and delete older files before or after writing the new image. Keep the existing
screenshot naming and write flow, but make sure the cleanup runs reliably in the
long-lived MCP server process.

In `@tools/mcp/daemon/create_startup_shortcut.ps1`:
- Around line 33-44: Wrap the WScript.Shell COM object lifecycle in a
try/finally block in create_startup_shortcut.ps1 so the object is always
released even if CreateShortcut, Save, or another step fails under
$ErrorActionPreference = "Stop". Keep the shortcut creation logic in the try
section around $WshShell, $Shortcut, and $Shortcut.Save(), and move the
ReleaseComObject call for $WshShell into the finally section with a null check.

In `@tools/mcp/daemon/start_daemon.ps1`:
- Around line 39-44: The daemon launch in start_daemon.ps1 relies on try/catch
around uv run, but that won’t reliably catch native process failures from
uv/python. Update the startup flow to invoke the existing daemon launch command,
then explicitly inspect $LASTEXITCODE after uv run completes and treat any
non-zero value as a startup failure. Keep the current error reporting in the
daemon-start script, but move the failure handling to the exit-code check so the
script reliably reports and exits when the daemon fails to start.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f144a30-ea65-46cf-92ff-7a8f6f79f6c3

📥 Commits

Reviewing files that changed from the base of the PR and between f24784b and 7bb747e.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (142)
  • .claude/CLAUDE.md
  • .github/dev.md
  • .gitignore
  • AGENTS.md
  • config/project.yml
  • deploy/OneDragon-RuntimeLauncher.spec
  • deploy/build_full.bat
  • deploy/generate_module_manifest.py
  • deploy/hook_path_inject.py
  • deploy/module_manifest.py
  • docs/develop/harness/README.md
  • docs/develop/harness/ai_tool_rules.md
  • docs/develop/harness/context_layering.md
  • docs/develop/harness/entry_files.md
  • docs/develop/harness/settings_scope.md
  • docs/develop/one_dragon/common-package-sync.md
  • docs/develop/one_dragon/runtime_launcher.md
  • docs/develop/setup/ai_coding.md
  • docs/develop/setup/claude-code/commit-trailer.md
  • docs/develop/setup/quickstart.md
  • docs/develop/sr_od/backend/README.md
  • docs/develop/sr_od/backend/architecture.md
  • docs/develop/sr_od/backend/design-principles.md
  • docs/develop/sr_od/backend/entry.md
  • docs/develop/sr_od/backend/http.md
  • docs/develop/sr_od/backend/mcp.md
  • docs/develop/sr_od/backend/remote-ssh.md
  • pyproject.toml
  • skills/sr-od-dev-deciding-a-fix/SKILL.md
  • skills/sr-od-dev-deciding-a-fix/design.md
  • skills/sr-od-dev-pr-finishing/SKILL.md
  • skills/sr-od-dev-pr-finishing/design.md
  • skills/sr-od-dev-skill-guide/SKILL.md
  • skills/sr-od-dev-skill-guide/design.md
  • src/one_dragon/base/conditional_operation/state_handler.py
  • src/one_dragon/base/config/basic_model_config.py
  • src/one_dragon/base/config/game_account_config.py
  • src/one_dragon/base/config/notify_config.py
  • src/one_dragon/base/config/yaml_operator.py
  • src/one_dragon/base/controller/pc_controller_base.py
  • src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
  • src/one_dragon/base/operation/application/application_factory_manager.py
  • src/one_dragon/base/operation/application_base.py
  • src/one_dragon/base/operation/context_event_bus.py
  • src/one_dragon/base/operation/context_notify_event.py
  • src/one_dragon/base/operation/notify_pool.py
  • src/one_dragon/base/operation/one_dragon_app.py
  • src/one_dragon/base/operation/one_dragon_context.py
  • src/one_dragon/base/operation/operation_notify.py
  • src/one_dragon/base/screen/screen_info.py
  • src/one_dragon/base/screen/screen_loader.py
  • src/one_dragon/base/screen/screen_match.py
  • src/one_dragon/base/screen/screen_utils.py
  • src/one_dragon/base/screen/template_info.py
  • src/one_dragon/base/screen/template_loader.py
  • src/one_dragon/devtools/python_launcher.py
  • src/one_dragon/envs/env_config.py
  • src/one_dragon/envs/git_service.py
  • src/one_dragon/launcher/runtime_launcher.py
  • src/one_dragon/utils/app_utils.py
  • src/one_dragon/utils/cv2_utils.py
  • src/one_dragon/utils/gpu_executor.py
  • src/one_dragon/utils/http_utils.py
  • src/one_dragon/utils/log_utils.py
  • src/one_dragon/yolo/onnx_model_loader.py
  • src/one_dragon/yolo/yolov8_onnx_cls.py
  • src/one_dragon/yolo/yolov8_onnx_det.py
  • src/one_dragon_qt/demo/draggable_list_demo.py
  • src/one_dragon_qt/services/app_setting/app_setting_manager.py
  • src/one_dragon_qt/view/app_run_interface.py
  • src/one_dragon_qt/view/code_interface.py
  • src/one_dragon_qt/view/devtools/devtools_image_analysis_interface.py
  • src/one_dragon_qt/view/devtools/devtools_screen_manage_interface.py
  • src/one_dragon_qt/view/devtools/devtools_template_helper_interface.py
  • src/one_dragon_qt/view/one_dragon/one_dragon_run_interface.py
  • src/one_dragon_qt/view/setting/app_notify_setting_interface.py
  • src/one_dragon_qt/view/setting/resource_download_interface.py
  • src/one_dragon_qt/view/setting/setting_env_interface.py
  • src/one_dragon_qt/view/setting/setting_instance_interface.py
  • src/one_dragon_qt/view/setting/setting_push_interface.py
  • src/one_dragon_qt/widgets/app_run_list.py
  • src/one_dragon_qt/widgets/app_setting/app_notify_setting_flyout.py
  • src/one_dragon_qt/widgets/color_channel_dialog.py
  • src/one_dragon_qt/widgets/fast_scroll_area.py
  • src/one_dragon_qt/widgets/horizontal_setting_card_group.py
  • src/one_dragon_qt/widgets/install_card/code_install_card.py
  • src/one_dragon_qt/widgets/notify_dialog.py
  • src/one_dragon_qt/widgets/scroll_credits.py
  • src/one_dragon_qt/widgets/setting_card/app_run_card.py
  • src/one_dragon_qt/widgets/setting_card/password_switch_setting_card.py
  • src/one_dragon_qt/widgets/vertical_scroll_interface.py
  • src/one_dragon_qt/windows/main_app_window_base.py
  • src/onnxocr/inference_engine.py
  • src/onnxocr/logger.py
  • src/onnxocr/onnx_paddleocr.py
  • src/onnxocr/operators.py
  • src/onnxocr/predict_base.py
  • src/onnxocr/predict_cls.py
  • src/onnxocr/predict_det.py
  • src/onnxocr/predict_rec.py
  • src/onnxocr/predict_system.py
  • src/onnxocr/readme.md
  • src/onnxocr/utils.py
  • src/sr_od/app/sr_application_launcher.py
  • src/sr_od/application/div_uni/__init__.py
  • src/sr_od/application/div_uni/operations/__init__.py
  • src/sr_od/application/div_uni/operations/choose_oe_file.py
  • src/sr_od/application/div_uni/operations/choose_oe_support.py
  • src/sr_od/application/div_uni/operations/ornamenet_extraction.py
  • src/sr_od/application/trailblaze_power/trailblaze_power_app.py
  • src/sr_od/application/treasures_lightward/__init__.py
  • src/sr_od/application/treasures_lightward/op/__init__.py
  • src/sr_od/application/treasures_lightward/op/challenge_mission.py
  • src/sr_od/application/treasures_lightward/op/check_max_unlock_mission.py
  • src/sr_od/application/treasures_lightward/op/check_mission_star.py
  • src/sr_od/application/treasures_lightward/op/check_star.py
  • src/sr_od/application/treasures_lightward/op/choose_character.py
  • src/sr_od/application/treasures_lightward/op/forgotten_hall/__init__.py
  • src/sr_od/application/treasures_lightward/op/forgotten_hall/choose_mission.py
  • src/sr_od/application/treasures_lightward/op/forgotten_hall/choose_team_in_fh.py
  • src/sr_od/application/treasures_lightward/op/forgotten_hall/get_reward_in_fh.py
  • src/sr_od/application/treasures_lightward/op/tl_battle.py
  • src/sr_od/application/treasures_lightward/op/tl_wait.py
  • src/sr_od/application/treasures_lightward/treasures_lightward_app.py
  • src/sr_od/application/treasures_lightward/treasures_lightward_config.py
  • src/sr_od/application/treasures_lightward/treasures_lightward_const.py
  • src/sr_od/application/treasures_lightward/treasures_lightward_record.py
  • src/sr_od/application/treasures_lightward/treasures_lightward_team_module.py
  • src/sr_od/backend/__init__.py
  • src/sr_od/backend/backend_context.py
  • src/sr_od/backend/entry/__init__.py
  • src/sr_od/backend/entry/server.py
  • src/sr_od/backend/http/__init__.py
  • src/sr_od/backend/http/routes.py
  • src/sr_od/backend/mcp/__init__.py
  • src/sr_od/backend/mcp/app.py
  • src/sr_od/backend/schemas.py
  • src/sr_od/win_exe/__init__.py
  • src/sr_od/win_exe/runtime_launcher.py
  • tools/mcp/daemon/create_startup_shortcut.ps1
  • tools/mcp/daemon/sr_od_daemon.py
  • tools/mcp/daemon/start_daemon.ps1
💤 Files with no reviewable changes (3)
  • src/one_dragon_qt/widgets/notify_dialog.py
  • src/sr_od/app/sr_application_launcher.py
  • src/one_dragon/base/conditional_operation/state_handler.py

Comment thread deploy/build_full.bat
Comment thread docs/develop/one_dragon/common-package-sync.md Outdated
Comment thread src/one_dragon_qt/view/one_dragon/one_dragon_run_interface.py
Comment thread src/one_dragon/base/config/yaml_operator.py
Comment thread src/one_dragon/base/operation/application_base.py
Comment thread src/onnxocr/predict_det.py
Comment thread src/onnxocr/predict_rec.py
Comment thread src/onnxocr/predict_rec.py
Comment thread src/sr_od/backend/backend_context.py
Comment thread tools/mcp/daemon/sr_od_daemon.py
- build_full.bat: copy 前先 mkdir config 目录(原 copy 到不存在的 config/ 会失败,包里缺 config/project.yml;ZZZ 也有此 bug)
- common-package-sync.md: 表格内转义 |(markdown 列解析,markdownlint MD056)
- backend_context: SrBackendContext.shutdown() 关闭 RunSlot._executor(原漏关致线程泄漏;加 RunSlot.shutdown() 封装)
- sr_od_daemon: 主 server 进程检测改精确 argv 匹配(-m sr_od.backend.entry.server),避免子串误匹配;与同文件 --port 解析风格一致

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: glm-5.2 <noreply@bigmodel.cn>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
deploy/build_full.bat (1)

7-9: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

构建/拷贝步骤缺少失败检测。

批处理未对 pyinstallercopyxcopy 的执行结果做 errorlevel 判断,任一步骤失败(如 PyInstaller 构建报错、源文件缺失)后脚本仍会继续执行并生成不完整的发行包,且不会有明显的失败提示。建议在关键步骤后添加 errorlevel 检查并在失败时提前退出。

♻️ 建议的修复方向
 uv run pyinstaller --noconfirm --clean "OneDragon-Installer.spec"
+if errorlevel 1 (
+    echo Build failed: OneDragon-Installer.spec
+    exit /b 1
+)
 uv run pyinstaller --noconfirm --clean "OneDragon-Launcher.spec"
+if errorlevel 1 (
+    echo Build failed: OneDragon-Launcher.spec
+    exit /b 1
+)
 uv run pyinstaller --noconfirm --clean "OneDragon-RuntimeLauncher.spec"
+if errorlevel 1 (
+    echo Build failed: OneDragon-RuntimeLauncher.spec
+    exit /b 1
+)

Also applies to: 17-32

🤖 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 `@deploy/build_full.bat` around lines 7 - 9, The build script’s
pyinstaller/copy/xcopy sequence does not stop on failures, so later packaging
steps can run after an earlier error. Add errorlevel checks after each critical
command in the batch flow around the pyinstaller invocations and the copy/xcopy
steps, and exit early with a clear failure message when any command returns
non-zero. Keep the checks consistent for all build stages so the script cannot
produce a partial release package.
🤖 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.

Nitpick comments:
In `@deploy/build_full.bat`:
- Around line 7-9: The build script’s pyinstaller/copy/xcopy sequence does not
stop on failures, so later packaging steps can run after an earlier error. Add
errorlevel checks after each critical command in the batch flow around the
pyinstaller invocations and the copy/xcopy steps, and exit early with a clear
failure message when any command returns non-zero. Keep the checks consistent
for all build stages so the script cannot produce a partial release package.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 41f9c2fa-24f2-4e59-9f38-26f4a73513a0

📥 Commits

Reviewing files that changed from the base of the PR and between 7bb747e and c4743d8.

📒 Files selected for processing (4)
  • deploy/build_full.bat
  • docs/develop/one_dragon/common-package-sync.md
  • src/sr_od/backend/backend_context.py
  • tools/mcp/daemon/sr_od_daemon.py
✅ Files skipped from review due to trivial changes (1)
  • docs/develop/one_dragon/common-package-sync.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/sr_od/backend/backend_context.py
  • tools/mcp/daemon/sr_od_daemon.py

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