Skip to content

RFC: Runtime Hook 能力完善与开发体验优化(单一真源 / 契约闭环 / lint+dry-run+trace) #679

@Cai-Tang-www

Description

@Cai-Tang-www

背景

当前 Runtime Hook 系统已经覆盖 core 执行链路(registry / executor / timeout / failure policy / runtime events),并接入了 user/repo hooks 与 trust gate。

但随着功能扩展,出现了以下结构性问题:

  1. 点位与能力定义存在双份真源风险
  • internal/runtime/hooks/types.gointernal/config/runtime_hooks.go 都在维护 hook point 与能力约束,后续容易漂移。
  1. 事件契约在生产-传输-消费链路存在"半闭环"风险
  • 新增 hook/verification 事件时,runtime、gateway stream decode、TUI handler 需要三端同步,缺少一套自动防漏机制。
  1. Hook 开发调试成本偏高
  • 缺少标准化 lint / dry-run / trace 工具,用户与开发者难以快速定位配置错误、上下文裁剪问题和时序问题。
  1. 治理能力尚未形成可持续演进模型
  • 缺少版本化/兼容策略与可观测 SLO(例如 hook 耗时、失败率、阻断率、异步回灌成功率)。

目标

将 Hook 系统提升为稳定的一等扩展面,达到:

  • 单一真源:Hook 点位、能力、scope/mode 约束只在一处定义,config/runtime 共用。
  • 契约闭环:新增事件具备强约束检查,防止 decode/handler 漏接。
  • 开发体验升级:提供 lint、dry-run、trace,降低调试门槛。
  • 可演进治理:建立可观测指标与兼容演进策略。

提案(分阶段)

Phase 1: 单一真源收敛

  • 将 HookPoint/Capability 定义收敛到 runtime hooks 包。
  • config 校验改为复用 runtime 导出的能力查询,不再硬编码点位集合。
  • 增加一致性测试:新增点位时,config/runtime 自动对齐校验。

Phase 2: 事件契约闭环

  • 建立 runtime event registry(type -> payload schema -> consumer requirements)。
  • 在 CI 增加契约检查:
    • runtime 新事件是否被 gateway_stream_client decode
    • decode 后是否在 TUI update handler 注册
  • 对"未知事件默认透传"保留,但新增事件必须显式声明消费策略。

Phase 3: Hook 开发工具链

  • hook lint:静态校验 hooks.yaml
    • point/mode/failure policy/kind 兼容性
    • params schema 与必填项
    • URL/host 安全约束(observe http)
  • hook dry-run:基于样本 HookContext 模拟执行
    • 输出 RunOutput、block/not block、annotation
  • hook trace:一次 run 内 hook 时序追踪
    • started/finished/failed/blocked
    • duration、message、source、point

Phase 4: 可观测与治理

  • 增加指标(本地日志 + 事件聚合)
    • hook_duration_ms (p50/p95)
    • hook_failure_rate
    • hook_block_rate
    • async_rewake_delivery_rate
  • 定义变更兼容策略(payload_version 与升级说明模板)。

非目标(当前 RFC 不覆盖)

  • 引入复杂多租户权限模型
  • 远程中心化 hook 管理平台
  • 跨 repo 的 hook marketplace

验收标准

  1. 新增 hook point 时,无需在 config 侧重复维护点位字符串列表。
  2. 新增 runtime 事件若未接入 decode/handler,CI 必须失败。
  3. 提供 hook linthook dry-runhook trace 三个开发命令或等效能力。
  4. hooks 关键指标可在日志或事件流中查询。
  5. 文档更新:docs/runtime-hooks-design.md 与示例配置同步。

建议任务拆分

  • Task A: Hook point capability 单一真源重构
  • Task B: Runtime event contract checker(CI)
  • Task C: Hook lint 实现
  • Task D: Hook dry-run 实现
  • Task E: Hook trace 实现
  • Task F: 指标与文档补齐

如认可该方向,可按 A->B->C->D->E->F 顺序推进,确保每步可独立合并与回滚。


补充范围:Claude 风格 hook 对齐面(2026-05-21 增补)

原 RFC 聚焦"治理 + DX",但若目标是把 hook 系统做成对外开放面(接近 Claude Code 的扩展性),需要补齐以下对外协议层。对当前实现(internal/runtime/hooksinternal/config/runtime_hooks.godocs/runtime-hooks-design.md)的差距分析结论:

已具备

  • 13 个挂点 + 能力矩阵(CanBlock / CanAnnotate / CanUpdateInput / UserAllowed)
  • internal/user/repo 三层 scope + workspace trust gate
  • HookContext metadata 白名单裁剪
  • kind=http observe(仅 loopback)+ async_rewake 回灌
  • 3 个 builtin handler

关键缺口(issue 原文未覆盖或仅一笔带过)

缺口 原 RFC 状态 影响
command kind + stdin/stdout JSON 协议 "P6 未实现"一笔带过 用户无法编写任意脚本 hook
Hook matcher / tool 选择器(对齐 Claude matcher 未提 当前只有 warn_on_tool_call 私有 params
HookContext payload schema 公开 + 版本化 仅 Phase 4 提及 payload_version 一句 user/repo hook 无稳定契约可写
accept_gate 点位(types 已声明,文档未列) 未提 现有代码与文档不一致
command kind 安全模型(argv vs shell / 环境变量白名单) 未提 直接放开会引入命令注入风险
update_input 落地路径(CanUpdateInput=true 的点位实际改写通道) 未提 能力建模存在但无运行时通道
async_rewake 对话可见性契约 仅声明实现,无 spec hook 作者无法预测异步结果可见性

任务拆分(已创建子 issue,按依赖关系排序)

# 子 issue 状态
Task A #681 Hook 点位/能力单一真源重构
Task B #682 Runtime 事件契约闭环检查器 开(依赖 A)
P6 核心 #683 command kind 与 stdin/stdout JSON 协议 开(依赖 A,与 Schema 并行)
Matcher #684 Hook tool 选择器与 matcher DSL 开(依赖 A)
Schema #685 HookContext payload schema 公开与版本化
DX #686 hook lint / dry-run / trace CLI 开(依赖 A/Schema)
Observability #687 hooks 指标与治理 开(依赖 B)

推进顺序建议

A → (B || Schema) → (Command || Matcher) → DX → Observability

A 与 Schema 是基座;Command 与 Matcher 互不阻塞;DX 在前两组完成后落地价值最大;Observability 最后封顶。

仍未拆出(保留在本主 issue 跟踪)

  • accept_gate 点位文档/配置补齐 → 并入 Task A
  • repo trust gate 首次发现 UX → 待 user feedback 后单独立项
  • settings 分层(local-only / managed policy) → 设计阶段,暂不立项
  • kind=prompt / kind=agent → 保持延后

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions