Skip to content

04 - CEL 预钩子

预钩子(Prehook)是工作流步骤上的条件门控。在步骤运行前,其预钩子 CEL 表达式被求值;如果返回 false,该步骤在当前循环或项中被跳过。

预钩子语法

yaml
- id: qa_testing
  prehook:
    engine: cel                # 仅支持 "cel"
    when: "is_last_cycle"      # CEL 表达式 —— 必须求值为布尔值
    reason: "QA 延迟到最后一个循环"   # 人类可读的说明(可选)

when 求值为 true 时步骤运行。求值为 false 时步骤被跳过,reason 被记录到日志。

可用变量(预钩子上下文)

以下变量可在预钩子 when 表达式中使用:

循环与任务状态

变量类型说明
cycleint当前循环轮次(从 1 开始)
max_cyclesint配置的总循环数
is_last_cycleboolcycle == max_cycles 时为 true
task_idstring当前任务 ID
task_item_idstring当前项 ID(task 作用域步骤为空)
task_statusstring当前任务状态
item_statusstring当前项状态
stepstring当前步骤 ID

QA 与工单状态

变量类型说明
qa_file_pathstring此项的 QA 文件路径
qa_exit_codeint?上次 QA 步骤的退出码(未运行则为 null
qa_failedbool上次 QA 步骤是否失败
active_ticket_countint活动(未解决)工单数量
new_ticket_countint当前循环中创建的工单数量

修复与重测状态

变量类型说明
fix_exit_codeint?上次 fix 步骤的退出码
fix_requiredbool是否需要修复
retest_exit_codeint?上次 retest 步骤的退出码

构建与测试状态

变量类型说明
build_exit_codeint?上次 build 步骤的退出码
test_exit_codeint?上次 test 步骤的退出码
build_errorsint构建错误数
test_failuresint测试失败数
self_test_exit_codeint?上次 self_test 步骤的退出码
self_test_passedbool上次 self_test 是否通过

代理输出状态

变量类型说明
qa_confidencefloat?代理 QA 置信度分数(可空;来自 AgentOutput.confidence
qa_quality_scorefloat?代理质量评估分数(可空;来自 AgentOutput.quality_score
fix_confidencefloat?修复代理置信度分数(可空)

安全

变量类型说明
self_referential_safebool此项是否可安全用于自引用执行

常见模式

延迟到最后一个循环

在多循环工作流中仅在最后一个循环运行 QA:

yaml
prehook:
  engine: cel
  when: "is_last_cycle"
  reason: "QA 延迟到最后一个循环"

条件修复

仅在有活动工单时运行修复:

yaml
prehook:
  engine: cel
  when: "active_ticket_count > 0"
  reason: "没有需要修复的工单"

组合条件

将 QA 延迟到最后一个循环,并按安全文件过滤:

yaml
prehook:
  engine: cel
  when: >-
    is_last_cycle
    && self_referential_safe
    && qa_file_path.startsWith("docs/qa/")
    && qa_file_path.endsWith(".md")
  reason: "QA 测试延迟到最后一个循环;跳过不安全的文档"

基于置信度的门控

如果 QA 置信度足够高则跳过修复:

yaml
prehook:
  engine: cel
  when: "qa_confidence != null && qa_confidence < 0.8"
  reason: "QA 置信度高于阈值 —— 无需修复"

构建失败门控

仅在构建成功后运行部署:

yaml
prehook:
  engine: cel
  when: "build_exit_code != null && build_exit_code == 0"
  reason: "部署前构建必须通过"

CEL 表达式快速参考

CEL(Common Expression Language)支持标准操作:

cel
# 比较
cycle > 1
active_ticket_count == 0

# 逻辑运算符
is_last_cycle && qa_failed
fix_required || active_ticket_count > 0

# 空值检查(对可选值很重要)
qa_exit_code != null && qa_exit_code == 0

# 字符串操作
qa_file_path.startsWith("docs/qa/")
qa_file_path.endsWith(".md")
step == "qa_testing"

# 取反
!qa_failed
!(is_last_cycle && fix_required)

重要:可选整数变量(qa_exit_codefix_exit_code 等)可能为 null。比较前务必进行空值检查:

cel
# 错误 —— 如果 qa_exit_code 为 null 会出错
qa_exit_code == 0

# 正确
qa_exit_code != null && qa_exit_code == 0

终结规则(CEL 上下文)

终结规则使用相同的 CEL 引擎,但具有扩展的变量集。除了上述预钩子变量外,终结规则还可以访问:

变量类型说明
retest_new_ticket_countint重测期间创建的工单数
qa_configuredbool工作流中存在 QA 步骤
qa_observedbool此循环中观察到了 QA 步骤
qa_enabledboolQA 步骤已启用
qa_ranboolQA 步骤实际执行了
qa_skippedboolQA 步骤被跳过(预钩子返回 false)
fix_configuredbool工作流中存在 Fix 步骤
fix_enabledboolFix 步骤已启用
fix_ranboolFix 步骤已执行
fix_skippedboolFix 步骤被跳过
fix_successboolFix 成功完成
retest_enabledboolRetest 步骤已启用
retest_ranboolRetest 已执行
retest_successboolRetest 通过
is_last_cyclebool是否为最后一个循环
qa_confidencefloat?代理 QA 置信度(预钩子上下文中同样可用)
qa_quality_scorefloat?代理质量评分(预钩子上下文中同样可用)
fix_confidencefloat?修复代理置信度(预钩子上下文中同样可用)

默认终结规则

如果未指定自定义终结规则,引擎按以下顺序应用 12 条内置规则(第一条匹配的生效):

#规则 ID条件(简化)状态
1skip_without_ticketsqa_skipped && active_ticket_count == 0 && is_last_cycleskipped
2qa_passed_without_ticketsqa_ran && qa_exit_code == 0 && active_ticket_count == 0qa_passed
3fix_disabled_with_tickets!fix_enabled && active_ticket_count > 0unresolved
4fix_failedfix_ran && !fix_successunresolved
5fixed_without_retestfix_success && !retest_enabledfixed
6fix_skipped_and_retest_disabledfix_enabled && !fix_ran && !retest_enabled && active_ticket_count > 0unresolved
7fixed_retest_skipped_after_fix_successretest_enabled && !retest_ran && fix_successfixed
8unresolved_retest_skipped_without_fixretest_enabled && !retest_ran && !fix_success && active_ticket_count > 0unresolved
9verified_after_retestretest_ran && retest_success && retest_new_ticket_count == 0verified
10unresolved_after_retestretest_ran && (!retest_success || retest_new_ticket_count > 0)unresolved
11fallback_unresolved_with_ticketsactive_ticket_count > 0unresolved
12fallback_qa_passedactive_ticket_count == 0qa_passed

最后两条规则是兜底回退。工作流中 finalize.rules 的自定义规则会完全替换这些默认规则。

自定义终结规则示例

yaml
finalize:
  rules:
    # QA 干净通过
    - id: qa_clean_pass
      engine: cel
      when: "qa_ran && active_ticket_count == 0"
      status: qa_passed
      reason: "QA 通过,无活动工单"

    # 修复经重测验证
    - id: fix_verified
      engine: cel
      when: "fix_ran && retest_ran && retest_success"
      status: fix_verified
      reason: "修复已应用并验证通过"

    # 非最终循环中 QA 被跳过 —— 保持 pending
    - id: qa_deferred
      engine: cel
      when: "qa_skipped && !is_last_cycle"
      status: pending
      reason: "QA 延迟到下一个循环"

    # 兜底
    - id: fallback
      engine: cel
      when: "true"
      status: pending
      reason: "无规则匹配 —— 保持 pending"

下一步