Skip to content

checkers DI 重构:Provider 注入替代全局状态获取 #978

Description

@hrygo

背景

internal/cli/checkers 的 Checker 接口只有 Name()/Category()/Check(ctx),依赖全部从包级全局或进程环境隐式获取,而非显式注入:

init() 注册把真实实现(如 defaultBuiltinSkillsStatus)绑死在全局函数,绕过了已有的注入雏形 NewBuiltinSkillsChecker(statusFn)

三个具体危害

  1. 可测性缺口(本次 ErrRootOutsideHome bug 的直接温床,见 doctor 报 skills 检查恒失败:ErrRootOutsideHome(checker 与 reconciler 契约分叉) #974):真实构造逻辑不可注入 → 无法单测 → 现有测试全为 mock statusFn → 契约分叉只能靠线上暴露
  2. 隐式契约:依赖无显式声明,改全局状态需全文 grep 引用点(checkers 包级 configPath 全局变量测试竞态与环境敏感(根治) #976 涉及 30+ 处)
  3. 状态重复构造:每次 Check 重建 registry + runner(性能无碍,但构造-复用未固化)

参照模式(仓库已确立)

  • internal/admin/admin.go:Provider 接口 + cmd/hotplex/main.go 桥接(见 CLAUDE.md「Admin API 包隔离模式」)
  • NewBuiltinSkillsChecker 已有构造注入雏形,init() 注册未使用

理想形态

注册时注入 provider(持有 userHome/hotplexHome/runner),而非绑死全局函数:

cli.DefaultRegistry.Register(builtinSkillsChecker{
    statusFn: (&skillsStatusProvider{}).Status,
})

测试可注入假 provider 或真 provider + t.TempDir() 直接测真实构造逻辑。

范围建议

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions