-
27-P4 §一.3 的目标逐字写着「解除『一家公司同时只有一个 active root run』约束 —— P3 v1 用一个唯一索引强制它,并行能力具备后应 放开」。本文档的批 4 在做同一件事。 划清边界:放开约束的设计归 27-P4,本文档只负责在它之上定义 「谁来排队、按什么序出队」。两边各写一版会产生两套并发守卫 —— 而这次要删的正是最后一道 DB 兜底,守卫分裂的代价特别高。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
并行的 agent 重构那条线同步来的,已核实三个函数都在: - agent-locator.js missingBodyDefinition() 判什么算没填完 - graph-service.js promoteDraftIfComplete() 转正动作 - graph-service.js isUngraduatedStatus() hire() 挡人的判据 关键是最后一个只挡 draft / training 两个状态,不是「≠ active 就挡」。 库里有 36 个本体的 status 是 enabled/idle/ready/trained,按「不等于 active」判会被全部误判成没填完 —— 这个坑已经被踩过一次。 取值域的唯一持有者是 graph-service,不要在别处复述 —— 与本文档 §六.3 记的 canDispatch 教训(前端复述了一份取值域还多写一个 blocked,导致公司失败一次后再也下不了任务)是同一个病。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
另一条工作线正在做 agent 目录结构重构(system/templates 并入 system/agents),约 900 个变更尚未提交。逐条核实交集: 好消息 —— 本文档引用的全部函数/常量(settleRun / markRunReady / stopRun / defaultPlanWorkGraph / PLAN_MAX_ROUNDS / writeTaskGoalArtifact / reportRunOutcome / ACTIVE_ROOT_RUN_STATUS / saveTaskMeta / getAggregatedTasks)在 650 行改动后全部存活,五条 行为性结论逐条复验仍成立,work-graph-db.js 完全没被碰(第二轮 复核最关键的那批发现不受影响)。27-P3/P4 那条「只写函数名不写 行号」的体例在这里直接兑现了价值。 坏消息 —— §四.9 有一条写反了,已纠正并留档: - system/templates/ 彻底取消,本体落 system/agents/task-planning/ - _registry.json 不再是数据源头(seedAgents 直接 readdirSync 扫 目录当真相,registry 只按 id 补 benchmark_score),所以「不登记 会把 CI 跑红」不成立 —— 建目录才是关键动作,登记是可选的 - 真正的闸门是新增的「毕业」判据:agent.md + soul.md 非空且不带 _base 骨架哨兵,否则 status 停在 draft、hire() 返回 body_not_ready。「先建骨架后填」的中间态雇不进公司 - 本体正文路径三条硬规矩(cwd 深度 3):自身文件 ../../、仓库根 ../../../../../、交付物必须用 $W 绝对路径。写错全都不报错、 只静默降级 —— 静默故障家族的最新成员 排期影响:批 1 照常(work-graph-db.js 无人触碰);批 2 的 task-planning 本体等重构落地后再建,否则要按旧形态做一遍再改; 批 5 开工前重新核 agent-chat.js(+455 行)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
companyService.get 已经在读这个文件,零新增读路径;建表要多一张表、 一套读写、一次迁移,而目前公司级配置项只有这一个。涨到 3 个以上时 再考虑建表。 这是 P3C 最后一个开放问题,§十一 至此全部关闭。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
R-20.6: 1. 退役 /api/goals 与 /api/company/:cid/goals 两个 OKR 别名,确认执行 2. goal 级验收仍用 org-validator,在 goal 层再调一次同一个本体。 不复用 task 级结论 —— 两次验的是基数不同的东西:task 级问 「这一个 task 的 task-goal 达成没有」,goal 级问「N 个 task 合起来人要的东西做出来没有」。单 task 的 goal 跳过这次调用。 goal 状态机加 failed,判词落 goals.verdict 3. 预算先不考虑,不做 goal 级闸门;但 planning_tokens / validation_tokens 两个记账字段保留 —— 它们不是闸门,是让 goal 层那两次 agent 调用的花费可见 4. queued 开放改 depends_on。当初担心的「改完位次怎么算」不成立: queuePosition 只按 priority→seq→created_at 排,depends_on 决定 的是够不够格出队,两者正交 5. 两套任务体系统一到 tasks 表,新增 §十二(批 5) 定案 5 核实出一个反直觉的前提:两套不是并列的,新体系的回调链路 长在旧体系身上 —— reportRunOutcome 收敛后调的正是 /api/agent/task/report。所以「删掉另一套」= 删存储与会话反推 (system/tasklog + TaskService.getAggregatedTasks),不能删入口 与回调:/task/dispatch 的 URL 与请求体写在 tools-base.md 里, 改它等于同时改所有 agent 的提示词。 tasks 表为此吸收三个字段(executor / assignee_agent_id / parent_task_id):agent 派单与 graph 执行的载体确实不同, 硬说成一回事是骗自己;调度器只管 executor='graph'。 顺带修好:派单去重从扫目录变一条 SQL,两套 T- id 合一。 开放问题 2/4/6/7 全部关闭,只剩 5(max_parallel 放哪)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
上游失败时下游自动转 blocked 已定案,开放问题里还留着同一个问题 的疑问句 —— 这正是「代码改了、文档停在上一轮」那类漂移。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
R-20.5 四条: 1. task-planning agent 提进 v1(原计划 v2 人手拆)。产出一律 draft 清单,人确认编辑后才下达 —— 那一步是唯一一道成本闸门, 拆出 5 条 task 就是 5 份 DEFAULT_TASK_BUDGET 2. 并行仍留批 4,v1 只排队(max_parallel_tasks=1,唯一索引不动) 3. manual 任务不参与自动出队:startRun(manual) 只点亮入口就停下等 /next,而 run 已经是 running 占着坑,自动拉起会堵死队头 4. 上游失败 → 下游自动推导为 blocked 并标红,给「重跑上游」和 「强制放行」两个出路。blocked 每次 tick 重算而不落死, 上游重跑成功后下游自己回 queued 定案 1 牵出一处新缺陷:task-planning 跑在 goal 层、任何 run 存在 之前,它烧的 token 没有预算池可扣 —— 正是 defaultPlanWorkGraph 注释里点名的「隐形的一半花费」在 goal 层的新实例。上一轮刚以 「零消费方」为由砍掉的 goal 级预算字段,以记账字段 planning_tokens 的形式回来(闸门仍不做)。 链路照抄 defaultPlanWorkGraph 不另造:调 agent → 校验 → errors 原样回喂,最多 3 轮;3 轮不过降级成 1 条同描述的 task,绝不能把 goal 卡在 planning。新本体必须与 _registry.json 登记同 commit, 否则 template-refs.test.js 当场把 CI 跑红(§八.21 有前科)。 验收 19-24 新增:拆分正常 / 失败降级 / 记账 / 不该花钱的路径不花钱 / 上游失败下游标红且可恢复。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
逐条对着代码核初稿,最要命的一条是基础事实搞错了: - createRun 在建行的事务里就按 readDefGraph 把 graph_run_nodes 全插好了。 初稿三处基于「queued run 没有节点行、进去就是空指针」的论证全部作废。 真实情况是 queued run 与 ready run 在数据上只差 run_status 一个字段, 所以「靠没有节点行自然报错」那道想象中的防线根本不存在, 唯一的闸门是 advanceOne 里 run_status !== 'running' 那一句,必须加断言钉死。 由此派生出一个既存、但被排队从毫秒窗口放大成必然事件的缺陷: 节点行在 createRun 时快照,而 getRunState 每次读都取当前定义。 排队期间点「重新规划组织」→ 新节点没有 run 行 → 出队即卡死。 补 syncRunNodesToDef,出队前对齐。 其余六处: - 出队原语写错:markRunReady 把 from 写死成 planning,复用不了; 正解是 updateRunStatus(runId,'queued','ready') 这一条条件更新 - 唯一索引冲突是 throw 不是 changes=0,初稿的错误处理只覆盖一半 - 触发点枚举本身是漏的:stopRun 与预算耗尽→blocked 两条最常见的 释放路径都不走 settleRun。改为挂在唯一漏斗 transitionRun 上, 一个钩子覆盖全部路径(枚举法在这里靠不住,而漏的症状是静默的) - report_to 只活在请求闭包里,排队后回调链路静默断掉 → 必须落库 - okr_node_id 逐 task 下发会反复覆写同一个 OKR 节点, done 会被后来的 failed 翻掉 → task 的 run 一律不带 okr_node_id - manual 任务占着 running 等人点「下一步」,会永久堵住队头 → 不参与自动出队 补漏:存量回填脚本(不做的话批 1 反而让历史任务更看不见)、 任务级 rerun 与节点级 retry 的命名撞车、queuePosition 排序口径 必须与调度器同源、砍掉没有消费方的 goals.budget_json。 错误结论留档不删(§三 ⚠️ 块 / §五.1 / §九.1 开头)—— 它们是最容易再犯一次的那类。验收从 12 条涨到 19 条。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-
控制台走查暴露的「一个 company 只能有一个任务」,根因不是并发约束, 是「人类提的需求」和「机器执行的单元」被压在同一条 root graph_run 上。 三个实地核实的前提,让这次不是发明新概念: - 27-NAMING §四 早就定义了 goal 1 : task N 的基数 - graph_runs.goal_id / task_id 两列早就在,company.js 注释也写着 「三者基数不同不可混用」—— 但全仓库没有任何写入方,goal_id 是悬空外键 - G- 前缀已被 OKR 正名释放;/api/goals 与 /api/company/:cid/goals 这两个 OKR 向后兼容别名全仓库零调用方,可以退役后把路径要回来 设计要点: - goals / tasks 两张新表 + graph_runs 新增 run_status='queued' - queued 的唯一理由是把出队的并发临界区交给既有唯一索引兜底: idx_graph_runs_one_active_root 覆盖 ready/running/paused 而不覆盖 queued, 超发会被索引直接拒绝,不需要应用层的「先查后插」 - 排队推翻了 P3「拒绝而不排队」的定案,但那条定案的理由(没有出队 worker = 静默丢任务)今天仍成立,所以调度器的四个触发点是功能主体而非收尾 - 已下达的描述冻结:入队即写 task-goal.json 并被 describeTask 消费, 改库不改 artifact 会让两份对不上,两份都改等于篡改审计输入 - 现有 T-${Date.now().toString(36)} 在「一个 goal 批量建 N 个 task」下 同毫秒必撞,且 tasks.id 是主键 —— 改用仓库既有约定的 4hex 后缀 R-20 四条定案回记至 27-requirement.md。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>