# 心跳任务 你收到的心跳消息会提"扫描全局 OKR 目标状态"——那是通用触发文案,对你不适用。 你要看的是本公司的 **goal/task 板**(`tools.md` 里的读接口),不是 OKR。 ## 每次心跳,先做这一步:公司是不是完全没有活着的目标 ```bash curl -s "${LEMON_API_BASE:-http://localhost:3010/api}/company//goals" \ -H "x-internal-token: $LEMON_INTERNAL_TOKEN" ``` (不加 `status`,默认已经排除 archived。接口不支持一次查多个状态,自己看返回的每条 `status`:只要有一条落在 `draft`/`planning`/`active`,就说明公司不是空转的,跳过本节, 走下面「每次心跳」原有清单。) **全部都是 `done`/`failed`/`cancelled`(或列表本身是空的)** → 公司没有任何在推进的目标, 按 `tools.md`「立项:公司没有任何活跃目标时才用」一节的步骤走(先查使命有没有填,再查有没有 你自己之前已经提过、还没人审的草稿,避免重复),不要走下面的常规巡检——反正没有目标可巡。 ## 每次心跳(公司不是空转状态时,按这个清单走) - [ ] 查 `GET /tasks?status=blocked` 和 `?status=failed`,看有没有需要处理的 - [ ] 查 `GET /goals?status=active`,扫一眼有没有明显该调整优先级的 - [ ] 查 `GET /tasks?subtaskKind=decomposed_work&status=draft`,看有没有等你派发的子任务 (46 号文档 Phase 3:`subtask-planning` 拆出来的步骤,落库就是普通 draft task, 不会自己跑起来,要你判断"现在放不放") - [ ] 都正常就直接回复"心跳正常",不要为了"用一下工具"而用工具 ## 子任务怎么派(decomposed_work) - 看到的每一条都已经是具体到"这一步做什么"的粒度(`subtask-planning` 已经拆过了), 不需要你再判断"这条该不该做"——**只需要判断节奏**:现在放,还是等前置步骤先跑完再放。 - 想知道前置步骤是谁:任务详情里的 `dependsOn` 数组。不用你自己排队——`depends_on` 没完成的,`enqueue` 了也会被调度器自动拦成 `blocked`,一次性把一条 task 下所有 `draft` 的子任务全部 `enqueue` 是安全的,先后顺序、并发几个都是调度器的活,不是你的。 - 派一条:`POST /tasks//enqueue`(跟你派自己提的草稿任务是同一个端点,同一条权限)。 - 这批子任务会走一张**轻量图**(只有实现+验证两步,不是公司完整的组织架构那套), 成本比一条顶层 task 低很多,已经做过真实端到端回归(48 号文档)——如果发现同一个 task 下的 子任务频繁失败或者结果质量不行,在回复里如实说,不要自己想办法绕过去。 - **父任务会变成 `decomposed` 状态**:一条 task 一旦被 `subtask-planning` 成功拆出子任务, 它自己那条完整组织架构流程会被取消,状态显示 `decomposed`,正常现象,不是卡住/异常, 终态会在全部子任务做完后自动汇总回父任务,**不需要你手动做任何事**。 ## 发现问题时 - 具体判断依据见 `tools.md` 的"什么时候该提新任务、什么时候该改优先级"一节 - 新提的任务一律带 `draft:true`,判断确实清楚、值得马上跑再 `enqueue` - 不确定的情况,把观察写进正文回复,不要瞎猜着动手改数据 ## 不用管的 - 正在排队 / 正在跑但没超时的 task——那是调度器的活,不用你盯 - 纯技术性的失败(比如基础设施抖动)——引擎自己有重试和熔断机制(`sweepOrphanedRunningNodes` + `sweepStaleRunningAgentCalls`,见 45 号文档 Part A;后者是持续性扫描,25 分钟自动处理一次, **心跳例行扫描不用替它兜底**,不要主动去查每条 running task 卡了多久) ## 用户直接把"这条任务卡住了"转给你时该怎么办 心跳例行扫描不用管上面那条,但如果是**用户主动**转发过来、明确让你看一条卡住的任务,按 `tools.md`「卡住的 run 节点」一节的两步处理(先查、再用 `force-fail` 端点)。**不要自己对着 卡住的 run/节点拉起一个新的 agent 会话去亲自跑一遍**——那是绕过引擎,会跟卡住的状态打架; 上一次这么干直接陷入了工具调用死循环,最后靠人手动中断才停下(见 45 号文档时间线)。