/// engine/omega_strong.mbt — 可选「Omega 强验证」开关(默认关闭)。
///
/// 设计原则(三条):
///   1) 默认关闭即现状:未开启强验证的任务,publish / claim / plan / execute /
///      submit / verify / archive 的既有语义与行为**完全不变**。本文件所有逻辑
///      都以「任务 description 是否带 [omega:required] 标记」为唯一开关判据。
///   2) 开启后为「语料驱动」的两道关卡(递归拆解的每一轮):
///        · 执行前:语料创建者(spec_author)写语料 → 验证者(verifier)审核,
///          不通过则打回重做,通过后才放行执行(omega_execute_gate)。
///        · 验收前:执行者产出成果后,验证者对成果与语料复验,不达标则打回重做,
///          通过后才放行验收(omega_verify_gate)。
///   3) 打回有上限、超限必升级:每类打回最多 max_rounds(默认 3,硬上限 10)次,
///      超限不再循环,而是写 escalation 记录 + 暂停任务,转人工裁决(防死循环)。

///|
/// 强验证标记:出现在任务 description 中即表示该任务处于强验证模式。
pub fn omega_mark() -> String {
  "[omega:required]"
}

///|
/// 边界四问·叶级提示(R115 后置改进,对准 atgc-merge 归因报告机理 2「验收锚定 + 弱语料」)。
/// 语料只断言"做了没"时,执行体理性地停在判据边界上;这一行把"域外行为"变成每条叶子的显式义务。
pub fn boundary_probe_hint() -> String {
  " [边界四问:空输入/极值/非法输入/资源极限——须有用例或声明不适用]"
}

///|
/// 边界审视叶的切片文本(对准机理 1「递归拆解损失全局视角 ⇒ 全局不变量无 owner」)。
/// 拆完之后"spec 没写的域外行为"是无人负责地带;本切片给这类思考一个可领取、可验收的归属。
pub fn boundary_probe_slice() -> String {
  "[边界审视·全局输入域 owner] 根任务 spec 未写的域外行为归本叶:对输入域逐项给出空输入 / 极值 / 非法输入 / 资源极限 四类用例,或显式声明该项不适用并说明依据;不得因 spec 未提及而默认沉默(写下限语料时,强验证只会验证下限)。"
}

///|
/// 语料 author 前缀(纯文本行,避免为嵌入 author 而引入 JSON 转义)。
pub fn omega_author_prefix() -> String {
  "OMEGA-AUTHOR: "
}

///|
/// 任务是否处于强验证模式(未打标记 = 关闭 = 既有行为)。
/// BUG-389 方向②:门禁判据以 tasks 元数据列 omega_required 为准(description 被
/// supervisor_task_upsert 覆盖后仍成立);description 里的 [omega:required] 标记
/// 保留为旧数据的兜底兼容(两者取或)。
pub fn omega_enabled(t : @core.Task) -> Bool {
  t.get_omega_required() || t.description.contains(omega_mark())
}

///|
/// 去掉切片文本中已存在的强验证标记(避免递归下钻时标记逐层累积)。
pub fn omega_clean_slice(s : String) -> String {
  let mark = omega_mark()
  if !s.contains(mark) {
    return s
  }
  let mut out = ""
  for part in s.split(mark) {
    out = out + part.to_owned()
  }
  out.trim().to_owned()
}

///|
/// 「孤儿 Omega 任务」判据(BUG-417):本任务自己**没开** omega(元数据列 = false),
/// 描述里的 `[omega:required]` 是**从父层切片继承来的残留**,且**直接父任务已归档**。
///
/// 为什么需要这个判据:`omega_enabled` 的文本兜底(`description.contains(mark)`)
/// **不区分标记归属** —— 一个 `omega_required=0` 的任务,只因描述里引用了父层文本
/// (含标记)就被判为强验证任务。`task_plan_deep` 递归下钻 + `reinject_context`
/// 把父层切片拼进子层描述时,标记会逐层累积。
///
/// 实测(Lane T):孤儿 `T0r636.1.2` 描述长 4683 字节,`[父计划:` 出现 4 次,
/// 两个 omega 标记**都在嵌套段内** ⇒ `strip_plan_annotations` 的单层截断有盲区。
///
/// 与 BUG-389 正相反:那条是「标记被静默**覆盖**」,本条是「标记被静默**继承**」。
///
/// **语义依据**:`omega_strong_verify` 的语义是「**这棵任务树**的成果要被验证」。
/// 父已归档 ⇒ 那棵树的验收语境已终结 ⇒ 让一个没有父亲的叶子继续满足门禁是**判据错位**。
///
/// **只豁免「直接父已归档」这一种**:父未归档 / 取不到 / 祖父归档 / 根任务 一律 false(fail-closed)。
/// `parent_status` 由调用方查库传入 ⇒ 本函数保持纯、可单测、无 IO。
pub fn omega_orphan_of_archived_parent(
  t : @core.Task,
  parent_status : @core.TaskStatus?,
) -> Bool {
  // 元数据列真开了 ⇒ 是正经 Omega 任务,不许豁免
  if t.get_omega_required() {
    return false
  }
  // 描述里没有标记 ⇒ 文本兜底根本不会触发,无需豁免
  if !t.description.contains(omega_mark()) {
    return false
  }
  // **根任务无父 ⇒ 不豁免**(Lane P 原始设计里有这一条,我这里曾漏掉,
  // 被锁 omega_orphan_wb2 抓出来:只信 parent_status 参数会让「根任务 + 传已归档」
  // 也返回 true)。判据必须自己确认「确实有父」。
  match t.get_parent() {
    None => false
    Some(_) =>
      match parent_status {
        None => false // 父取不到 ⇒ fail-closed 不豁免
        Some(st) => st.is_archived()
      }
  }
}

///|
/// 切到某个标记首次出现处之前(沿用 omega_author_of 的「迭代首个元素即返回」写法,
/// 不对数组下标取,避免潜在越界)。无该标记则原样返回。
fn cut_before(s : String, mark : String) -> String {
  if !s.contains(mark) {
    return s
  }
  for part in s.split(mark) {
    return part.to_owned()
  }
  s
}

///|
/// decomposer 结构标记清单(单一真源)。`strip_plan_annotations` 与
/// `preserve_plan_markers` 共用同一份清单,消除两份清单漂移的风险。
/// 标记面必须与 decompose_rec 写入端一字不差(含前导空格)——本函数是唯一落点。
fn plan_markers() -> Array[String] {
  [
    " [难度梯度 ",
    " [父计划:",
    " | [父计划: ",
    " [边界四问",
    " [spec:",
    omega_mark(),
  ]
}

///|
/// 去掉「拆解引擎自己追加」的计划标注,只留任务本体描述(R113)。
/// `omega_clean_slice` 只洗强验证标记,而 gradient / reinject_context / boundary_probe /
/// spec 指纹四项同样会在递归下钻时被逐层重喂(child.description 当作下一层的
/// parent_desc,且又被嵌进「更简单变体」引用与「父计划」字段),实测 2 层拆分叶子
/// 1996 字节、根部仅 12 字节,并出现同一叶两个互相矛盾的梯度档。
/// 逐标记顺序截断 = 截在最靠前的那个标记之前,因此对已叠加多层的文本也能一次洗净。
/// 标记面来自 `plan_markers()`(单一真源)。
pub fn strip_plan_annotations(s : String) -> String {
  let markers = plan_markers()
  let mut out = s
  for m in markers {
    out = cut_before(out, m)
  }
  out.trim().to_owned()
}

///|
/// 合并 decomposer 注入的结构标记:新描述缺哪些,就把旧描述里的对应标记补回(BUG-389)。
///
/// `supervisor_task_upsert` 用 `with_description` **整体覆盖** description,而用户经超级管家
/// 更新任务描述时通常不会带上 `[omega:required]` / `[边界四问…]` / `[难度梯度 …]` /
/// `[父计划:…]` / `[spec:…]` 这些由 decomposer 注入的结构标记;覆盖后标记被静默丢失,
/// 之后 `omega_spec_create` 判门禁读到 description 不含 `[omega:required]` 就误报
/// 「未开启 Omega 强验证」,把「标记丢失」伪装成「用户没开 Omega」。
///
/// 语义:对 `plan_markers()` 列出的标记面做「缺失补回」——若旧描述含某标记而新描述不含,
/// 则把该标记(连同其前导空格,`omega_mark()` 无前导空格)追加到新描述末尾。
pub fn preserve_plan_markers(old_desc : String, new_desc : String) -> String {
  let markers = plan_markers()
  let mut out = new_desc
  for m in markers {
    if !out.contains(m) {
      if old_desc.contains(m) {
        out = out + m
      }
    }
  }
  out
}

///|
/// 默认最大打回轮次。
pub fn omega_max_rounds_default() -> Int32 {
  3
}

///|
/// 归一化轮次上限:非正数取默认,超过 10 硬截断(防死循环的最终边界)。
pub fn omega_norm_max_rounds(v : Int32) -> Int32 {
  if v <= 0 {
    omega_max_rounds_default()
  } else if v > 10 {
    10
  } else {
    v
  }
}

///|
/// 语料记录 id:spec::r
pub fn omega_spec_id(task_id : String, round : Int32) -> String {
  "spec:\{task_id}:r\{round}"
}

///|
/// 成果复验记录 id:result::r
pub fn omega_result_id(task_id : String, round : Int32) -> String {
  "result:\{task_id}:r\{round}"
}

///|
/// 升级记录 id:escalation:::r
pub fn omega_escalation_id(
  task_id : String,
  stage : String,
  round : Int32,
) -> String {
  "escalation:\{task_id}:\{stage}:r\{round}"
}

// —— 内部工具 ——

///|
/// Omega 环节角色授权:actor 必须具备指定 Action 权限(静态权限矩阵校验)。
fn omega_authorize_create(actor : String) -> Result[Unit, String] {
  @core.ensure_can_create_spec(actor)
}

///|
/// Omega 环节角色授权:审核/复验(角色:验证者,或人类指挥官)。
fn omega_authorize_review(actor : String) -> Result[Unit, String] {
  @core.ensure_can_review_spec(actor)
}

///|
/// 从语料内容中解析 author(读取 UTF8 前缀行;无前缀返回空串)。
fn omega_author_of(content : String) -> String {
  let p = omega_author_prefix()
  if !content.has_prefix(p) {
    return ""
  }
  let rest = content[p.length():content.length()]
  for line in rest.split("\n") {
    return line.to_owned()
  }
  rest.to_owned()
}

///|
/// r 是否比 cur 更新(created_at 优先,其次 id 字典序,保证跨后端确定性)。
fn omega_newer(r : @store.SpecRecord, cur : @store.SpecRecord) -> Bool {
  if r.created_at != cur.created_at {
    r.created_at > cur.created_at
  } else {
    r.id > cur.id
  }
}

// —— 引擎侧语料账本读写 ——

///|
/// 列出某任务的全部语料 / 复验 / 升级记录。
pub fn FistEngine::omega_records(
  self : FistEngine,
  task_id : String,
) -> Array[@store.SpecRecord] {
  self.store.list_specs_by_task(task_id)
}

///|
/// 统计某类型记录中处于指定状态的条数。
pub fn FistEngine::omega_count(
  self : FistEngine,
  task_id : String,
  spec_type : String,
  status : String,
) -> Int32 {
  let mut n = 0
  for r in self.store.list_specs_by_task(task_id) {
    if r.spec_type == spec_type && r.status == status {
      n = n + 1
    }
  }
  n
}

///|
/// 统计某类型的全部记录条数。
pub fn FistEngine::omega_count_type(
  self : FistEngine,
  task_id : String,
  spec_type : String,
) -> Int32 {
  let mut n = 0
  for r in self.store.list_specs_by_task(task_id) {
    if r.spec_type == spec_type {
      n = n + 1
    }
  }
  n
}

///|
/// 取最新一条指定类型记录。
pub fn FistEngine::omega_latest(
  self : FistEngine,
  task_id : String,
  spec_type : String,
) -> @store.SpecRecord? {
  let mut found : @store.SpecRecord? = None
  for r in self.store.list_specs_by_task(task_id) {
    if r.spec_type == spec_type {
      found = match found {
        None => Some(r)
        Some(cur) => if omega_newer(r, cur) { Some(r) } else { Some(cur) }
      }
    }
  }
  found
}

// —— 门禁 ——

///|
/// 占位符规整:把字符串拆成 Char 数组,剔除所有非字母数字的字符(空白/标点/全角标点),
/// 再转小写。MoonBit 用 `String::to_array()` 拿到 `Array[Char]`(同 evolve.mbt 的做法)。
fn placeholder_normalize(s : String) -> String {
  let out : Array[String] = []
  for c in s.to_lower().to_array() {
    let is_cjk = c.to_int() >= 0x4E00 && c.to_int() <= 0x9FFF
    let is_ascii_alnum = (c.to_int() >= 0x30 && c.to_int() <= 0x39) ||
      (c.to_int() >= 0x41 && c.to_int() <= 0x5A) ||
      (c.to_int() >= 0x61 && c.to_int() <= 0x7A)
    if is_cjk || is_ascii_alnum {
      out.push(c.to_string())
    }
  }
  out.join("")
}

///|
/// 预执行审计门禁(P2 BACKLOG「Pre-execution audit gate」):
/// 在 `can_execute` 通过之后、`execute()` 迁移之前插入,拦截「空交付物」与「占位符交付物」——
/// 「已完成但无交付物」的病灶形状:执行者写了空串/纯空白/「done」/「完成」/「ok」这类占位符
/// deliverable,账本记「完成」但没有任何产物可核。判据两条:
///   ① deliverable trim 后非空;② 非纯占位符(如 "done"/"完成"/"ok"/"yes"/"通过",大小写不敏感;不做全角归一化)。
/// 只拦确定性问题,不做过度拦截;零回归(正常交付物一定含具体改动/路径/验证信息)。
pub fn FistEngine::audit_execute_gate(
  _self : FistEngine,
  _task_id : String,
  deliverable : String,
) -> Result[Unit, String] {
  let trimmed = deliverable.trim().to_owned()
  if trimmed.is_empty() {
    return Err(
      "预执行审计门禁:deliverable 为空。请写清改动/路径/验证后再 execute",
    )
  }
  // 占位符检测:把常见 fake-GREEN 词规整后比对(大小写/空白/标点容忍)。
  // 只判「整串等于占位符」这种确定性问题,不做语义判定,避免过度拦截。
  // R10 修:旧实现只 to_lower,注释里承诺的「空白/标点容忍」落了空——`"Done ."` / `"完成!"`
  // 这类「占位符 + 杂散空白/标点」能绕过。现在把全串拆成字符后剔除所有非字母数字的字符,
  // 再做大小写归一,与规整后的占位符词表比对。
  let stripped = placeholder_normalize(trimmed)
  let placeholder_words : Array[String] = [
    "done", "完成", "ok", "yes", "通过", "finished",
  ]
  for w in placeholder_words {
    if stripped == w {
      return Err(
        "预执行审计门禁:deliverable 是占位符 [" +
        trimmed +
        "],没有可核产物。请写清改动/路径/验证后再 execute",
      )
    }
  }
  Ok(())
}

///|
/// 执行前门禁:强验证任务必须先有「已通过」语料;默认关闭的任务直接放行。
pub fn FistEngine::omega_execute_gate(
  self : FistEngine,
  task_id : String,
) -> Result[Unit, String] {
  match self.store.get_task(task_id) {
    None => Ok(())
    Some(t) =>
      if !omega_enabled(t) {
        Ok(())
      } else {
        match self.omega_latest(task_id, "spec") {
          None =>
            Err(
              "Omega 强验证门禁:任务 [\{task_id}] 尚未创建语料,请先由语料创建者执行 omega_spec_create",
            )
          Some(s) =>
            if s.status == "approved" {
              Ok(())
            } else {
              Err(
                "Omega 强验证门禁:语料 [\{s.id}] 状态为 [\{s.status}],未通过审核前禁止进入执行",
              )
            }
        }
      }
  }
}

///|
/// 验收前门禁:强验证任务必须先有「已通过」的成果复验记录。
pub fn FistEngine::omega_verify_gate(
  self : FistEngine,
  task_id : String,
) -> Result[Unit, String] {
  match self.store.get_task(task_id) {
    None => Ok(())
    Some(t) =>
      if !omega_enabled(t) {
        Ok(())
      } else {
        match self.omega_latest(task_id, "result") {
          None =>
            Err(
              "Omega 强验证门禁:任务 [\{task_id}] 尚未做成果复验,请先由验证者执行 omega_result_verify",
            )
          Some(s) =>
            if s.status == "approved" {
              Ok(())
            } else {
              Err(
                "Omega 强验证门禁:成果复验 [\{s.id}] 状态为 [\{s.status}],未通过前禁止验收",
              )
            }
        }
      }
  }
}

// —— 第一环:语料创建 ——

///|
/// 语料创建(角色:语料创建者 spec_author,或人类指挥官)。
/// 落库 specs 表:id = spec::r,status = pending。
pub fn FistEngine::omega_spec_create(
  self : FistEngine,
  task_id~ : String,
  author~ : String,
  content~ : String,
  now~ : String,
  max_rounds~ : Int32 = 0,
) -> Result[Json, String] {
  match omega_authorize_create(author) {
    Err(e) => return Err(e)
    Ok(_) => ()
  }
  let max_r = omega_norm_max_rounds(max_rounds)
  let t = match self.store.get_task(task_id) {
    None => return Err("task not found: \{task_id}")
    Some(x) => x
  }
  if !omega_enabled(t) {
    return Err(
      "任务 [\{task_id}] 未开启 Omega 强验证(description 缺少 [omega:required] 标记),无需创建语料",
    )
  }
  if content.trim() == "" {
    return Err("语料内容不可为空")
  }
  match self.omega_latest(task_id, "spec") {
    Some(cur) =>
      if cur.status == "pending" {
        return Err(
          "已存在待审核语料 [\{cur.id}],请先由验证者审核",
        )
      } else if cur.status == "approved" {
        return Err("语料 [\{cur.id}] 已通过审核,无需重复创建")
      }
    None => ()
  }
  let rejected = self.omega_count(task_id, "spec", "rejected")
  if rejected >= max_r {
    return Ok(
      self.omega_escalate(
        task_id, "spec", rejected, max_r, "语料连续打回达上限,转人工裁决",
        now,
      ),
    )
  }
  let round = self.omega_count_type(task_id, "spec") + 1
  let spec_id = omega_spec_id(task_id, round)
  let payload = omega_author_prefix() + author + "\n" + content
  let rec = @store.SpecRecord::new(
    id=spec_id,
    task_id~,
    spec_type="spec",
    content=payload,
    status="pending",
    created_at=now,
    updated_at=now,
  )
  match self.store.upsert_spec(rec) {
    Err(e) => Err(e)
    Ok(_) =>
      Ok(
        Json::object({
          "ok": Json::boolean(true),
          "stage": Json::string("spec"),
          "spec_id": Json::string(spec_id),
          "task_id": Json::string(task_id),
          "round": Json::number(round.to_double()),
          "status": Json::string("pending"),
          "author": Json::string(author),
          "max_rounds": Json::number(max_r.to_double()),
          "rounds_rejected": Json::number(rejected.to_double()),
          "next_action": Json::string("omega_spec_review"),
          "escalated": Json::boolean(false),
        }),
      )
  }
}

// —— 第二环:语料审核(可打回重做) ——

///|
/// 语料审核(角色:验证者 verifier,或人类指挥官)。
/// verdict = approve 通过;其余视为打回(打回累计超限则升级人工)。
pub fn FistEngine::omega_spec_review(
  self : FistEngine,
  task_id~ : String,
  reviewer~ : String,
  verdict~ : String,
  reason~ : String = "",
  now~ : String,
  max_rounds~ : Int32 = 0,
) -> Result[Json, String] {
  match omega_authorize_review(reviewer) {
    Err(e) => return Err(e)
    Ok(_) => ()
  }
  let max_r = omega_norm_max_rounds(max_rounds)
  let t = match self.store.get_task(task_id) {
    None => return Err("task not found: \{task_id}")
    Some(x) => x
  }
  if !omega_enabled(t) {
    return Err(
      "任务 [\{task_id}] 未开启 Omega 强验证,无语料可审",
    )
  }
  let cur = match self.omega_latest(task_id, "spec") {
    None =>
      return Err(
        "任务 [\{task_id}] 尚无语料,请先由语料创建者执行 omega_spec_create",
      )
    Some(c) => c
  }
  if cur.status != "pending" {
    return Err(
      "语料 [\{cur.id}] 当前状态为 [\{cur.status}],不是待审核状态",
    )
  }
  let author = omega_author_of(cur.content)
  if author != "" && author == reviewer {
    return Err(
      "验证者不可审核自己创建的语料(author = reviewer = \{reviewer})",
    )
  }
  let is_approve = verdict == "approve" ||
    verdict == "approved" ||
    verdict == "pass" ||
    verdict == "ok" ||
    verdict == "APPROVE" ||
    verdict == "PASS" ||
    verdict == "OK"
  if is_approve {
    match self.store.update_spec_status(cur.id, "approved", cur.content, now) {
      Err(e) => Err(e)
      Ok(_) =>
        Ok(
          Json::object({
            "ok": Json::boolean(true),
            "stage": Json::string("spec"),
            "verdict": Json::string("approved"),
            "spec_id": Json::string(cur.id),
            "task_id": Json::string(task_id),
            "reviewer": Json::string(reviewer),
            "reason": Json::string(reason),
            "next_action": Json::string("execute"),
            "escalated": Json::boolean(false),
          }),
        )
    }
  } else {
    let rejected = self.omega_count(task_id, "spec", "rejected") + 1
    // rejected = existing + 1, so > max_r means existing >= max_r (consistent with omega_spec_create)
    if rejected > max_r {
      return Ok(
        self.omega_escalate(task_id, "spec", rejected, max_r, reason, now),
      )
    }
    match self.store.update_spec_status(cur.id, "rejected", cur.content, now) {
      Err(e) => Err(e)
      Ok(_) => {
        // 失败回流:语料被打回即自动落 [lesson] 教训,供 plan/claim inject 检索
        let learned = self.omega_auto_lesson(
          rejected,
          "omega.spec_rejected",
          if reason == "" {
            "语料被打回(未附原因)"
          } else {
            reason
          },
          "语料未达要求,按审核意见重写后重新 omega_spec_create",
          now,
        )
        Ok(
          Json::object({
            "ok": Json::boolean(true),
            "stage": Json::string("spec"),
            "verdict": Json::string("rejected"),
            "spec_id": Json::string(cur.id),
            "task_id": Json::string(task_id),
            "reviewer": Json::string(reviewer),
            "reason": Json::string(reason),
            "rounds_rejected": Json::number(rejected.to_double()),
            "max_rounds": Json::number(max_r.to_double()),
            "learned_lesson": Json::boolean(learned),
            "next_action": Json::string("omega_spec_create"),
            "escalated": Json::boolean(false),
          }),
        )
      }
    }
  }
}

// —— 第三环:成果复验(可打回重做) ——

///|
/// 成果复验(角色:验证者 verifier,或人类指挥官)。
/// verdict = pass 达标;其余视为打回重做(超限升级人工)。
pub fn FistEngine::omega_result_verify(
  self : FistEngine,
  task_id~ : String,
  reviewer~ : String,
  verdict~ : String,
  reason~ : String = "",
  now~ : String,
  max_rounds~ : Int32 = 0,
) -> Result[Json, String] {
  match omega_authorize_review(reviewer) {
    Err(e) => return Err(e)
    Ok(_) => ()
  }
  let max_r = omega_norm_max_rounds(max_rounds)
  let t = match self.store.get_task(task_id) {
    None => return Err("task not found: \{task_id}")
    Some(x) => x
  }
  if !omega_enabled(t) {
    return Err(
      "任务 [\{task_id}] 未开启 Omega 强验证,无需成果复验",
    )
  }
  let spec = match self.omega_latest(task_id, "spec") {
    None =>
      return Err(
        "强验证任务 [\{task_id}] 尚无执行前语料,不可复验成果",
      )
    Some(s) => s
  }
  if spec.status != "approved" {
    return Err(
      "执行前语料 [\{spec.id}] 未通过审核([\{spec.status}]),不可进入成果复验",
    )
  }
  if t.deliverable.trim() == "" {
    return Err(
      "任务 [\{task_id}] 尚无交付物(deliverable 为空),无可复验成果",
    )
  }
  let round = self.omega_count_type(task_id, "result") + 1
  let result_id = omega_result_id(task_id, round)
  let is_pass = verdict == "pass" ||
    verdict == "approved" ||
    verdict == "approve" ||
    verdict == "ok" ||
    verdict == "PASS" ||
    verdict == "OK"
  let payload = "resv-reviewer: " +
    reviewer +
    "\nverdict: " +
    verdict +
    "\nreason: " +
    reason
  let rec = @store.SpecRecord::new(
    id=result_id,
    task_id~,
    spec_type="result",
    content=payload,
    status=if is_pass { "approved" } else { "rejected" },
    created_at=now,
    updated_at=now,
  )
  if is_pass {
    match self.store.upsert_spec(rec) {
      Err(e) => Err(e)
      Ok(_) =>
        Ok(
          Json::object({
            "ok": Json::boolean(true),
            "stage": Json::string("result"),
            "result_id": Json::string(result_id),
            "task_id": Json::string(task_id),
            "round": Json::number(round.to_double()),
            "status": Json::string("approved"),
            "reviewer": Json::string(reviewer),
            "reason": Json::string(reason),
            "next_action": Json::string("verify"),
            "escalated": Json::boolean(false),
          }),
        )
    }
  } else {
    let rejected = self.omega_count(task_id, "result", "rejected") + 1
    // rejected = existing + 1, so > max_r means existing >= max_r (consistent with omega_spec_create)
    if rejected > max_r {
      return Ok(
        self.omega_escalate(task_id, "result", rejected, max_r, reason, now),
      )
    }
    match self.store.upsert_spec(rec) {
      Err(e) => Err(e)
      Ok(_) => {
        // 失败回流:成果复验未达标即自动落 [lesson] 教训
        let learned = self.omega_auto_lesson(
          rejected,
          "omega.result_rejected",
          if reason == "" {
            "成果复验未达标(未附原因)"
          } else {
            reason
          },
          "交付物未达语料要求,按复验意见重做后重新 execute/submit",
          now,
        )
        // 打回重做:若已提交待验收,则用既有 reject 语义退回执行
        let mut demoted = ""
        if t.get_status().is_reviewing() {
          demoted = match
            self.reject_task(task_id~, reason~, by=reviewer, now~) {
            Ok(_) => "待验收 -> 已打回"
            Err(e) => "打回失败: " + e
          }
        } else {
          demoted = "任务当前状态 [" +
            t.status_to_string() +
            "],保持不动,等待执行者重做"
        }
        Ok(
          Json::object({
            "ok": Json::boolean(true),
            "stage": Json::string("result"),
            "verdict": Json::string("rejected"),
            "result_id": Json::string(result_id),
            "task_id": Json::string(task_id),
            "reviewer": Json::string(reviewer),
            "reason": Json::string(reason),
            "rounds_rejected": Json::number(rejected.to_double()),
            "max_rounds": Json::number(max_r.to_double()),
            "learned_lesson": Json::boolean(learned),
            "task_transition": Json::string(demoted),
            "next_action": Json::string("execute"),
            "escalated": Json::boolean(false),
          }),
        )
      }
    }
  }
}

// —— 超限升级(防死循环的终点) ——

///|
/// 打回超限升级:写 escalation 记录 + 暂停任务,转人工裁决。
fn FistEngine::omega_escalate(
  self : FistEngine,
  task_id : String,
  stage : String,
  rounds : Int32,
  max_r : Int32,
  reason : String,
  now : String,
) -> Json {
  // 失败回流:打回超限升级本身是最典型的「此路不通」教训,自动沉淀进 DGM
  let learned = self.omega_auto_lesson(
    rounds,
    "omega.escalated",
    if reason == "" {
      "打回超限升级人工(未附原因)"
    } else {
      reason
    },
    "该打回原因已反复出现,需换策略而非继续同样的做法",
    now,
  )
  let esc_id = omega_escalation_id(task_id, stage, rounds)
  let payload = "stage: " +
    stage +
    "\nrounds_rejected: " +
    rounds.to_string() +
    "\nmax_rounds: " +
    max_r.to_string() +
    "\nneeds_human_review: true" +
    "\nreason: " +
    reason
  let rec = @store.SpecRecord::new(
    id=esc_id,
    task_id~,
    spec_type="escalation",
    content=payload,
    status="escalated",
    created_at=now,
    updated_at=now,
  )
  let mut spec_err = ""
  match self.store.upsert_spec(rec) {
    Ok(_) => ()
    Err(e) => spec_err = e
  }
  let paused = match self.pause_task(task_id~, now~) {
    Ok(_) => true
    Err(_) => false
  }
  Json::object({
    "ok": Json::boolean(true),
    "stage": Json::string(stage),
    "verdict": Json::string("escalated"),
    "escalation_id": Json::string(esc_id),
    "task_id": Json::string(task_id),
    "rounds_rejected": Json::number(rounds.to_double()),
    "max_rounds": Json::number(max_r.to_double()),
    "reason": Json::string(reason),
    "needs_human_review": Json::boolean(true),
    "task_paused": Json::boolean(paused),
    "spec_persist_error": Json::string(spec_err),
    "learned_lesson": Json::boolean(learned),
    "next_action": Json::string("human_review"),
    "escalated": Json::boolean(true),
  })
}

// —— 状态查询 ——

///|
/// 查询某任务的强验证状态(开关、语料轮次、打回次数、复验状态、是否已升级)。
pub fn FistEngine::omega_status(
  self : FistEngine,
  task_id : String,
) -> Result[Json, String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) => {
      let records = self.store.list_specs_by_task(task_id)
      Ok(
        Json::object({
          "ok": Json::boolean(true),
          "task_id": Json::string(task_id),
          "task_status": Json::string(t.status_to_string()),
          "omega_enabled": Json::boolean(omega_enabled(t)),
          "spec_rounds": Json::number(
            self.omega_count_type(task_id, "spec").to_double(),
          ),
          "spec_rejected": Json::number(
            self.omega_count(task_id, "spec", "rejected").to_double(),
          ),
          "result_rejected": Json::number(
            self.omega_count(task_id, "result", "rejected").to_double(),
          ),
          "spec_status": Json::string(
            match self.omega_latest(task_id, "spec") {
              Some(s) => s.status
              None => "none"
            },
          ),
          "result_status": Json::string(
            match self.omega_latest(task_id, "result") {
              Some(s) => s.status
              None => "none"
            },
          ),
          "escalated": Json::boolean(
            self.omega_count(task_id, "escalation", "escalated") > 0,
          ),
          "records": Json::array(records.map(fn(r) { r.to_json() })),
        }),
      )
    }
  }
}