refactor(cli): extract explore feishu sink commands into their own module - #3309
Conversation
…dule explore.py was the largest cli_commands module at 989 lines, only 11 under the modularization smoke's default budget, as the remaining oversized seam after the quota/status/todo/history/scheduler plumbing extractions. Move the cohesive feishu-* sink family (feishu-setup, feishu-visual-configure, feishu-sync, feishu-card) -- registration, dispatch branches, and the sync-only _target_config helper -- into loopx/cli_commands/explore_feishu_commands.py, mirroring the explore_planning_commands sibling pattern with shared arg helpers injected as callables. explore.py drops to 723 lines. Public invocations are unchanged: loopx.cli still calls register_explore_commands/handle_explore_command, subcommand flags and explore --help output are byte-identical, and the singleflight smoke now patches the moved names in their new namespace instead of keeping a compatibility alias. Also drop the stale LEGACY_MODULE_LIMITS entries for benchmark_review_lifecycle.py and terminal_bench_environment_result.py: the native-runner benchmark reset (huangruiteng#3267) removed both modules, which left the size/ownership smoke failing on main with "size budgets reference missing modules". Signed-off-by: 牛瑞博 <912906590@qq.com>
huangruiteng
left a comment
There was a problem hiding this comment.
评审对象:59911d1e8daf8a7b72669c9e3fae80273025982d
动机
这次改动解决的是一个真实且已经接近阈值的维护性问题:loopx/cli_commands/explore.py 在主干上已达到 989 行,Feishu/Lark 展示 sink 的四个子命令又恰好形成一组边界清楚、共同依赖同一扩展 provider 的职责。把这组注册与执行逻辑移出 hot module,能让后续 Explore 核心命令和 Lark 展示侧分别演进,也避免继续用扩大行数预算来掩盖所有权混杂。
改动思路
整体方案是一次保持行为的内聚提取,而不是再造一层通用抽象:
- 新模块
explore_feishu_commands.py直接拥有feishu-setup、feishu-visual-configure、feishu-sync、feishu-card的参数注册和执行分支; explore.py只保留入口编排,通过register_explore_feishu_commands和handle_explore_feishu_command委派,并把已有的配置路径、projection 构造器和 runtime root 注入进去;FEISHU_SINK_EXPLORE_COMMANDS同时驱动扩展激活检查和 dispatch,避免注册集合与执行集合各自漂移;- 没有留下旧私有函数的兼容 wrapper,也没有把 Lark provider 细节提升成新的核心 capability,归属符合现有扩展边界。
具体改动
-
loopx/cli_commands/explore.py- 删除仅由 Feishu sink 使用的 17 个 import、四段 argparse 注册和四个执行分支;
register_explore_commands改为调用register_explore_feishu_commands;handle_explore_command在完成 registry/runtime/source-route/config-path 解析后,把 Feishu 子命令交给新 handler;外层仍统一追加source_runtime_route、extension_activation,并统一把异常收敛成 CLI error packet。
-
loopx/cli_commands/explore_feishu_commands.pyregister_explore_feishu_commands完整保留四个公开子命令的参数、默认值、choices 和 help;_target_config继续按“显式参数优先、本地配置兜底”解析 Base/table/CLI identity,缺少完整目标时抛出明确错误;handle_explore_feishu_command保留 setup、visual configure、singleflight sync 和 card 文件/消息 ID 持久化四条路径;- 正向
feishu-sync路径仍是:获取 singleflight → 构造 projection → 解析 target → 同步表格 → 同步单/多 visual sink → 汇总ok;锁已占用时直接返回not_attempted_sync_busy,明确标记未做外部写入。配置不完整或 provider 调用失败时,异常继续由外层 CLI handler fail closed。
-
两个 smoke
- singleflight smoke 只把 monkeypatch 目标迁到真实查找位置,继续证明锁外不误写、锁内按顺序同步 rows/visual;
- module-size smoke 删除已经随 #3267 模块删除而失效的两个 legacy budget,恢复“预算不能指向不存在模块”的自检。该清理在 pristine main 上可复现红灯,因此与本次维护性任务相容。
对主干的风险
主要风险在于提取时遗漏 argparse 默认值、改变 dispatch/扩展激活顺序、破坏 singleflight 的 fail-closed 行为,或让 source-runtime 路由不再进入 projection。逐文件对照后未发现这些变化:四个命令仍共享同一个集合常量,projection callback 收到原 runtime root 和 override 参数,busy 分支仍不执行 rows/visual 写入,handler 返回后仍经过外层 route/activation 装饰与错误渲染。
本次没有新增或修改 typed state 规则;没有把产品/benchmark 文案写入通用 control-plane 合约;公开默认行为声明为 refactor,并由 help/schema parity 覆盖;也没有把机器义务误称为 guidance。
独立验证结果:
git diff --check origin/main...HEAD:通过;- CLI module-size smoke:通过;且 pristine main 的两个 stale legacy budget 失败可复现;
- Explore Feishu singleflight smoke:通过;
- CLI command module regression:通过;
tests/cli_commands+tests/canary:81 passed;tests/architecture:13 passed;- 变更文件 Ruff:通过;
explore --help与explore schema相对主干逐字节无差异;- GitHub 上 DCO、dependency review、pytest、build 均为 green。
我的整体评价
APPROVE。 这是一次边界清楚、范围克制、可回滚的模块提取:它减少了 hot module 的所有权负担,同时保留了公开 CLI、扩展激活、source-runtime 路由、singleflight 和错误路径的语义。附带的 stale budget 清理有独立可复现依据,不是借机扩 scope。当前 exact head 未发现 blocker 或需要作者额外修改的 P2 项。
|
APPROVE — reviewed exact head The extraction keeps the public Explore CLI contract and failure semantics intact: the four Feishu sink commands retain their arguments/defaults, extension activation and source-runtime routing stay in the outer handler, and Independent validation: diff check; both focused smokes; CLI command regression; 81 CLI/canary tests; 13 architecture tests; Ruff on all changed files; byte-identical |
Addresses task-board row GH-C06 ("CLI ownership and hot-module extraction", Available): characterize one remaining oversized CLI ownership seam and move one cohesive command group into its bounded module.
Characterization
The size/ownership smoke governs
loopx/cli_commands/*.pyonly, sobootstrap_command_pack.py(tracked separately by the canary ratchet) is out of scope for this row. After the recent quota/status/todo/history/scheduler extractions, the remaining oversized seam under the smoke isloopx/cli_commands/explore.pyat 989/1000 lines — the largest module in the directory and 11 lines from the default budget (runner-up: registry_admin.py at 975).What moved
The four
feishu-*Lark sink subcommands (feishu-setup,feishu-visual-configure,feishu-sync,feishu-card): their registration blocks, dispatch branches, the sync-only_target_confighelper, and the 17 imports only they use — into a newloopx/cli_commands/explore_feishu_commands.py(320 lines), mirroring the existingexplore_planning_commands.pysibling pattern: shared arg helpers injected as callables, no compatibility wrappers. Public invocations unchanged —loopx/cli.pystill callsregister_explore_commands/handle_explore_command, andexplore --help/explore schemaoutput is byte-identical to main.Validation (task-specified commands)
python examples/cli-command-module-size-ownership-command-modularization-smoke.py→ okpython regression/cli-command-module-contract.py→ ok (requirespip install -e .for theloopxentry point and aLOOPX_REGISTRYfixture; the local-machine registry miss reproduces on main too — environmental)tests/cli_commands/+tests/canary/→ 81 passed;-k explore→ 152 passed;examples/explore-feishu-singleflight-smoke.py(monkeypatch target updated to the new namespace) → okTwo honest notes:
LEGACY_MODULE_LIMITSentries, tripping the smoke's own stale-budgets assertion. This PR removes the two stale entries so the task's validation command is usable again (5 lines in the smoke script, called out here for review visibility).tests/extensions/test_extension_scaffold.pyhas a collection error from a missing optional dependency that reproduces identically on base — pre-existing, untouched.tests/cli_commands/, canary, and import-boundary suites stay green; mypy delta vs main is line-number drift plus one_SubParsersActiontype-arg in the new register function matching the sibling modules' existing style.Refs GH-C06.