先把任务清单读完再跑分——LifeVal 的分数只认最终状态

文章导读
跑分前把任务清单从头读一遍,重点不是记住有多少条任务,而是把每条任务的目标状态改写成可检查的条件:字段是否存在、值是否等于某个期望、接口返回是否落在某个枚举里。执行时按终态驱动动作,不要用刷题思路去优化中间步骤,因为 LifeVal 这类评测只认最终状态,中间步骤再顺也不会被计入。同时准备好一份运行记录,跑完能回看某条任务做过什么、最终状态是什么、哪条验收条件没过。没有这份记录,分数出来只能看到总
📋 目录
  1. 壹 在任务清单里逐条确认最终状态的定义
  2. 贰 搭一个最小的运行记录结构
  3. 叁 用一条任务跑通全流程再批量
  4. 肆 按最终状态判断任务是否完成
  5. 伍 把不达标的任务按缺失条件归类
A A

跑分前把任务清单从头读一遍,重点不是记住有多少条任务,而是把每条任务的目标状态改写成可检查的条件:字段是否存在、值是否等于某个期望、接口返回是否落在某个枚举里。执行时按终态驱动动作,不要用刷题思路去优化中间步骤,因为 LifeVal 这类评测只认最终状态,中间步骤再顺也不会被计入。同时准备好一份运行记录,跑完能回看某条任务做过什么、最终状态是什么、哪条验收条件没过。没有这份记录,分数出来只能看到总数,定位不到错在哪。

把任务清单读完、把每条任务的目标状态改写成可检查条件,再开始跑分;执行过程中把动作序列和最终状态写进同一份运行记录。判定完成只看最终状态是否满足验收条件,不看中间过程是否顺畅。未达标时按缺失条件归类,转成可修改的清单。这套做法适用于验收条件能被逐条读出来的评测任务;如果任务文件里的目标状态本身写得含糊,需要先回到任务文件确认,而不是靠日志反推。

在任务清单里逐条确认最终状态的定义

任务文件里给出的往往是一段描述性文字,例如「任务执行完成后,目标资源处于可用状态,并且绑定了指定标签」。这句话能读懂,但不能直接拿来判定,因为「可用状态」「指定标签」在检查时需要落到具体字段和具体值。建议把每条任务的目标状态原文摘录下来,再改写成一行行可检查的条件。

改写的方法通常是三步:定位检查对象(哪个文件、哪个接口、哪个字段路径)、写明期望值(字符串、数字、布尔、集合包含关系)、指定检查手段(读取文件、调用接口、执行一条只读命令)。下面是一组示例,左边是任务文件里的原话,右边是改写后的条件:

  • 原文「资源创建成功」→ 条件:接口返回体中 status 字段等于 ready,且 id 字段非空。
  • 原文「完成了配置写入」→ 条件:目标配置文件存在 key=value 这一行,且重复执行读取时值不变。
  • 原文「清理了临时产物」→ 条件:指定目录下匹配的临时文件数量为 0。

改写时不要补任务文件里没有的要求,也不要把「大概做到了」写成条件。如果某条任务的目标状态实在无法落到具体字段,先标记为「待确认」,不要带着模糊条件进入批量跑分;模糊条件在事后无法判定,等于没有验收条件。

先把任务清单读完再跑分——LifeVal 的分数只认最终状态

搭一个最小的运行记录结构

运行记录不需要多复杂,但必须包含三类信息:这条任务是谁、执行了哪些动作、最终状态是什么。下面是一份通用的 YAML 骨架,字段名可以按自己的脚本习惯替换,结构保持不变即可:

# 通用结果记录骨架,字段名自拟
run_record:
  run_id: "<本次运行标识,自行定义>"
  task_id: "<任务清单中的唯一标识>"
  goal_state_quote: "<从任务文件里摘录的目标状态原文>"
  actions:                      # 按执行顺序追加,不要事后补写
    - step: 1
      action: "<动作名,如 create_resource / call_endpoint>"
      target: "<作用对象>"
      result: "<返回摘要或退出码>"
  final_state:                  # 跑完后由检查脚本或人工填写
    checked_at: "<检查时间>"
    conditions:
      - name: "<条件名>"
        expected: "<期望值>"
        actual: "<实测值>"
        pass: false
    missing_conditions: []      # 未通过的条件名列表

几个容易踩的取舍:actions 建议在执行时逐条追加,而不是全部跑完再回忆着补写,否则动作序列和真实执行顺序会对不上;final_state 建议由一段固定的检查逻辑填写,而不是靠人工判断后敲一个 pass: true;goal_state_quote 虽然不参与判定,但在复查时能快速看出条件改写有没有偏离任务原意。

用一条任务跑通全流程再批量

直接批量跑最大的问题是:记录结构缺字段这件事,往往要等几十条任务跑完、准备汇总时才发现。建议先挑一条验收条件写得最清楚的任务,单独跑通「执行 → 写记录 → 检查终态 → 判定」这条链路,再放开批量。

先把任务清单读完再跑分——LifeVal 的分数只认最终状态
# 占位示例,命令名与参数按你的环境替换
lif eval run `--task-id` T-001 `--record-out` ./records/T-001.yaml

跑完后不要只看退出码,要打开记录文件确认两件事:该任务的 final_state 字段非空,且记录里的 task_id 与这次执行的任务标识对应。可以用一段简短脚本检查,也可以先手工确认一遍:

# 通用检查示例,字段名按实际记录替换
python - <<'EOF'
import yaml
d = yaml.safe_load(open("./records/T-001.yaml"))
r = d["run_record"]
assert r["task_id"] == "T-001", "任务标识不匹配"
assert r["final_state"] and r["final_state"].get("conditions"), "final_state 为空"
print("OK", r["task_id"], len(r["actions"]))
EOF

如果检查不通过,先修记录结构再谈跑分。等这条任务的记录既能看清动作序列、又能逐条读到条件判定结果,批量执行才有汇总价值;否则批量结果只是一堆无法复查的分数。

按最终状态判断任务是否完成

判定动作建议固定成一张逐条对照的检查表,每次填同一套列,避免不同任务用不同标准:

先把任务清单读完再跑分——LifeVal 的分数只认最终状态
  • 条件名:与任务文件改写后的条件一一对应。
  • 期望值:改写阶段写死的值,执行过程中不改。
  • 实测值:检查时读到的真实值,原样记录。
  • 判定:满足 / 不满足 / 无法检查。
  • 证据位置:记录文件路径、日志行号或接口返回片段。

只有全部条件满足才记为完成;出现「无法检查」时按未完成处理,并把原因写清楚,例如接口不可达、字段在返回体里不存在。未达标时要记录缺失项,而不是只写一句失败:缺失条件名、期望值、实测值、以及能复现该问题的最小动作序列。这几项凑齐,后续才不用重新跑一遍去找原因。

把不达标的任务按缺失条件归类

把各条任务的 missing_conditions 汇总,按缺失条件的性质分组,比按任务编号罗列更有用。分组后每组对应一个明确的修改方向:

  • 目标描述歧义:同一句目标状态被写成了两种检查条件。修改方向是回到任务文件确认原意,统一条件定义后再重跑。
  • 动作缺失:动作序列里根本没有能产生该终态的步骤。修改方向是补动作,而不是在记录里改结果。
  • 状态未落地:动作执行了,但字段值或文件内容没变。修改方向是核对参数、路径和依赖条件,必要时单独重放这一步。
  • 记录缺失:条件满足与否无法判定,因为记录里没有对应条目。修改方向是先补记录字段,再重新执行该任务。

每个分组下建议保留任务标识列表和一条代表性证据,汇总时能直接看出哪一类问题占多数。这里的「占多数」只用于排序处理优先级,不要写成比例结论;评测环境、任务版本不同,分组分布通常会变,需要结合当前环境的实际记录确认。