• run 撞墙钟/调用次数/token 上限 blocked 时,之前界面上没有入口,
    只能开发者工具手搓 fetch 调 POST /:id/budget。加一个按钮 + 小弹窗,
    三维增量(留空不追加)+ 追加后立即启动,复用现有的 act() 提交入口
    与 confirmAuto 同款 modal 样式。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01U7xYyvv3pzuV9diMVUH5QL
    yibo authored
     
    Browse Dir »

  • run_b962ea87f58f 卡在 wallclock_ms 耗尽的锚点未结清问题上,需要人工追加预算
    才能继续。extendBudget 只增不减、只加到已配额的维度上,追加时顺带结清卡死的
    墙钟锚点(否则 startRunSync 一启动就把挂起时长记进新预算里)。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »

  • 35 号文档剩下的三个提案,彼此直接相关(C 产出 D 消费的证据,B 展示 D 算出的结果),
    一次做完。
    
    提案 D(goal-contract.js 引擎级证据闸门):
      `runBenchmark` 新增 evidence 检测——`evidence_hint` 命中"浏览器/视口/开发者工具/
      console/network/截图"类关键词的维度,必须在 evidence.<dim> 有真实字符串支撑,
      否则该维度判不过(哪怕分数达标)。证据来源两处都认:`--target` 文件自带的
      `evidence.<dim>`,或同目录姊妹判词文件 `attempt-<n>.json` 的 `dimensions[].evidence`
      ——后者是 benchmark-validator/agent.md 早就在教的既有写法,不用 agent 多写一份。
      新增 `dimensions[].evidence_required` 字段随判决落盘。6 条新单测。
    
    提案 C(可复用视觉验收工具):
      新增 scripts/visual-acceptance-check.mjs,四个子命令(overflow/style/console/
      contrast),封装最常见的几类真实浏览器检查(Playwright),agent 通过 bash 直接
      调用,不用每次自己临时想办法(真实撞见过两个极端:一次真写了 Playwright 认真测,
      一次只写了正则解析文本)。配一份不进 vitest 快速循环的独立冒烟脚本(起真
      Chromium,几秒量级)。benchmark-validator/agent.md Step 2 加了引用说明。
    
    提案 B(控制台证据可见性):
      GET /api/graph-runs/:id 新增 benchmarkVerdicts 字段(只读 goal-contract.js 已落盘
      的判决,不重新计算)。NodeDetailPanel 概览 tab 新增"验收证据"小节:逐维度显示
      分数 + 是否有证据支撑,evidence_required 且缺证据的标 ⚠️。纯展示,不改判定逻辑。
      2 条新单测。
    
    全量单测 1012/1012 通过;控制台功能用 Chrome 实测过(截图确认"验收证据"小节正确
    渲染)。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • 用户反馈:控制台原来只能逐个节点点「输入输出」tab 看产物,缺一个全局入口。
    新增 TaskFilesPanel.vue,挂在页头,跨节点/跨 run 一次性列出这个任务的全部产物。
    
    做的时候发现分两类、且第二类之前完全没覆盖:
      · 节点产出索引(graph_files,按 company+task 检索)——规划笔记/日志/契约快照
      · 项目根(W2 ensureProjectRoot,data/companies/{cid}/projects/{pid}/)——
        真实交付物代码写的地方,跨节点共享,indexNodeOutputs 从不扫它
    
    后端补 readProjectRootRecord 导出 + GET /api/graph-runs/:id 挂 projectRoot 字段;
    项目根的文件列表复用已有的 GET /:companyId/files(此前零调用方),不新开列目录端点。
    新增 graph-run-route-io.test.js 两例(分配前 null、分配后原样透传 + 幂等)。
    
    顺带订正 34 号文档:当时断言"index.html 从未被写出来"是错的——真实网站文件
    其实在项目根里,只是没查那个目录。34 号文档 §零 记录了订正过程,问题收窄成
    "validator 有没有真的做过浏览器级检查"(仍未解决,留待下次)。
    
    全量单测 1000/1000 通过。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »

  • 新增 join-status.js(+ .check.js 可运行检查,web/ 不在 vitest include 里,
    同款手法照抄 io-model.check.js):resolveJoinWait/joinWaitLabel,判据与引擎
    activateSuccessTargets/allIncomingSatisfied 同源——只看 forward 的 success
    入边,backward/fail 边不算「等待对象」。只有 2+ 条入边的真 fan-in 才出徽标,
    单一入边的普通顺序等待不加噪声。
    
    WorkGraphCanvas.vue:pending 节点在等哪几个上游时画一枚「⏳done/total」徽标,
    悬停看完整明细(谁 success / 谁还在 running / 谁 fail 了)。
    
    nextNodeId(单数)→ nextNodeIds(数组):advanceBatch(27-P4 T4)一次最多
    认领 max_concurrency 个 ready 节点,并行分支下真实会被同批拾取的可能是好几个,
    标一个会误导。这个 prop 之前在全仓库没有任何调用方真正传值(NEXT 徽标从未
    渲染过),顺手把它接上:GraphRunPane 按 run.max_concurrency 截取候选,
    手动模式仍显示单数提示,自动模式显示批量提示。
    
    并行运行中的多节点高亮不需要新代码——.dot.running/.node.running 已经是
    按每个节点各自状态渲染,多个节点同时 running 时天然一起亮,这条在 T4/T6
    落地时就已经生效。
    
    验证:join-status.check.js 6 条断言全过;`npm run web:build` 编译通过、
    零告警。没有做的:没有起真实浏览器点一遍——搭一张真的并行 fan-in 图需要
    起完整服务 + 建公司 + 跑真图,这次没做,逻辑侧的验证到 check.js + 编译为止。
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »

  • ## 批 4:解除「一家公司同时只有一个 active root run」
    - DROP idx_graph_runs_one_active_root(建表块删掉 + 迁移块显式 DROP,
      CREATE ... IF NOT EXISTS 对存量库不生效)
    - max_parallel_tasks 从 company.json 调用时读(不是模块加载时快照,
      否则改配置要重启才生效且不报错);缺省 1、非法回落 1 并留声、硬上限 20
    - 准入判据「从活跃集外进入活跃集」按额度计数
    
    **生死线用 8 个真进程并发抢坑实测**(不是纸面论证):max=1/2/3/5 四组,
    每组恰好抢到 max 个、库里活跃数 = max,落选进程各吃 40 次 RunSlotBusyError,
    零 other 错误。唯一索引没了之后,准入事务是真守卫。
    
    ## 批 3 对抗复核的四条遗留
    - N1 🔴 cancelQueuedRun 的前提被批 3 自己的 requeueBlockedRootRun 改没了:
      queued 的 run 现在可以是跑过一半的。探针实测取消后子 run 残留
      paused/stop_requested=0 —— 那条 running 的子 run 继续调 agent 烧 token。
      改为无条件走 engine.stopRun
    - L1 ⚠️ 恢复路径对 manual 只兑现一半:注释写着「T1 永远回不来这个后果因此
      消失」,但调度器故意不碰 manual → 退回队列后没人接。定案:「manual 不自动
      出队」约束的是首次起跑的授权,已被人亲手起过的不算新授权。
      判据用 attempt>0 而不是 started_at —— 后者会被 requeue 清成 NULL,
      恰好在需要它的那一刻是空的(实测踩过)
    - N2 🟠「退回队列」对用户完全不可见:200 + ok:true + 按钮全灰 + 图消失 +
      一句「节点状态一律 pending」的假提示。加 notice 明说
    - N3 🟠 isSlotRaceError 把 InvalidTransitionError 当竞态吞掉,而探针证伪了
      那条注释:被推走时条件更新返回 0 不抛,真正抛它的只有「调用方声明了非法
      转换」。删掉该分支,让它吵起来
    
    四条里三条是同一个模式:注释承诺的前提被本轮自己的改动改没了,注释还留着。
    文档 §十三.3 / §十四.4 已就这个模式立过两次案,这是第三、四、五次。
    
    ## 文档
    §十五 实施记录,含 §15.4 一次流程事故:87b776c 由第三方会话在对抗复核完成
    前误提,提交说明的「1201 用例全绿」压在一份尚未通过复核的代码上。
    
    全量:128 文件 / 1240 测试全绿,web:build 通过。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • 队列与调度(§五.1):
    - 下达任务不再因「公司已有 active root run」吃 409,改为建 queued run + queued task
      排队;出队走 updateRunStatus 的 CAS + BEGIN IMMEDIATE 准入事务,触发挂在
      transitionRun 这个唯一漏斗上,60s sweep 兜底。
    - 依赖已不可能满足的排队任务就地推导成 blocked,且每次 tick 重算不落死,上游重跑
      成功后能原路解开。
    
    恢复路径(批 3 复核 F1/F2):三条恢复转换的 from 全在活跃集之外,撞坑满时退回队列而不是
    永远躺在 blocked;退不回去的裸 run 干净拒绝,不留半截状态。
    
    控制台三处可见性修复 —— 症状全是纯视觉、不报错、git status 干净:
    1. 顶栏墙钟恒 `now - started_at`,没有终点。一条昨晚就 blocked 的 run 第二天还在涨到
       「16h 58min」,而那是页面上唯一的时间信号 —— 「已经停了等人处置」被显示成了
       「还在跑再等等」,这两件事需要的动作相反。终点改取 run.updated_at,并标「已停」。
    2. 越界日志只报「留下 N 处改动」,文件清单躺在 timeline.ndjson 里翻不到。判罚就是按
       这份清单下的,而人要判断「这真是 agent 写的吗」唯一的依据就是路径(并行的开发会话
       改宿主仓库会被算到当时在跑的节点头上,那是误判,看一眼就知道)。改为列出 entries。
    3. run 收敛成 blocked 时只把 task 写成 blocked、不写原因,任务列表那一行只剩一个橙色
       的「挂起」,必须逐层点进 org 图 → work 图 → 节点详情才知道发生了什么。改为把
       「卡在哪个节点 + 什么 fail_reason + 判词摘要」写进 tasks.blocked_reason。
       原因绝不带 UPSTREAM_BLOCK_PREFIX —— 带了会被调度器当成依赖推导出的 blocked 自动
       推回 queued,而这类 blocked 本来就等着人处置(守卫在 task-blocked-reason.test.js)。
    
    测试:126 文件 / 1201 用例全绿。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »

  • goal 从「人写一句话」变成「agent 拆成一张 task DAG、人确认后下达」,
    收敛时由 org-validator 在 goal 层再验一次。
    
    ## 交付
    - task-planning 本体(毕业判据实测通过:agent.md + soul.md 一次写完、
      不带 _base 哨兵、路径按 cwd 深度 3 实算核对)
    - 拆分链路:3 轮 errors 原样回喂 → 不过就降级成 1 条同描述 task,
      goal 绝不卡在 planning;token 记 goals.planning_tokens
    - goal 级 org-validator 验收:≥2 条 task 全 completed 才调,单 task 跳过,
      有 failed 直接 failed 不调(省一次真花钱的调用)
    - 控制台四栏 + GoalTaskPane 两级树 + 两步表单(拆分中给逃生口)
    - 中断恢复:启动时补跑验收与汇报
    
    ## 三条跨进程竞态,全部用真探针实跑复现后才判定修好
    1. runGoalSplit 无条件把 goal 写回 draft,抹掉逃生口刚下达的 active ——
       而触发它的正是表单自己推荐的那个逃生口。后果是一个正在烧钱的 goal
       显示成「草稿」,且从此永不收敛(OKR 不写、上级不唤醒、无日志)
    2. CAS 把最终态提前写进库,验收窗口内重启即丢,且 verdict=NULL 与
       「单 task 合法跳过」形态相同,查不出来 → 占位判词 + 启动重推
    3. 认领语句 SET verdict=RESUMING WHERE verdict IN (PENDING, RESUMING)
       —— 写进去的值就在 WHERE 里,changes 恒为 1。而函数注释白纸黑字
       写着「认领写的是另一个占位值」。注释是对的,代码没兑现。
       实测:org-validator 调 2 次 / OKR 写 2 条 / token 双记
       → claim 带唯一 token + 时间戳租约,回写条件更新决胜,主路径同闸门
    
    ## 与设计正文的偏离(已记进文档 §十四)
    拆分后 goal 落 draft 而非 active(active 的语义已被 markGoalDispatched
    钉死为「已下达」);mode 三级继承对显式 tasks[] 同样生效;占位判词不出
    API;新增 planning_error / reported_at 两列,后者迁移带回填(否则升级后
    第一次启动会把历史终态 goal 全部重报一遍)。
    
    ## 过程
    四轮 26 个 agent,复核报出 22 条缺陷,其中 6 条是修复自己引入的。
    第四轮修完挂了 3 条测试,全是测试在钉住缺陷本身 —— 其中一条的注释
    写着「模拟进程死后重启」,构造的却是新鲜占位值:注释描述 A 场景、
    代码构造 B 场景、断言按 A 场景写。
    
    全量:118 文件 / 1112 测试全绿,web:build 通过。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »

  • 控制台原先只能看引擎的事件轨(stream.log / timeline.ndjson),里面是结构化事件、
    自由文本还被截断到 600 字;引擎更是根本不消费流式 chunk(onAcpEvent 只取
    session/result 的 usage)。所以 LLM 的逐字输出从来不在它的轨道上。
    
    新端点 GET /api/graph-runs/:id/nodes/:nodeRunId/transcript **惰性读** Claude CLI
    自己的会话文件:不进 SSE、不进节点行、不落第二份库 —— 那正是引擎当初决定不存全文的
    三条理由要避免的(输出无上限而 getRunState 每次轮询 SELECT * 全量回传 /
    产物已有 output_ref 这个唯一真相源 / fail_reason 是选边匹配键不能掺自由文本)。
    这里没有推翻那个设计,只是多开一个读取入口。
    
    目录推导与条目规范化抽到 server/services/agent-transcript.js,
    scripts/tail-agent.js 改为复用它 —— 一份实现两个入口。今天已经修过三次
    「两份必须保持一致的实现漂了」,不想制造第四次。
    
    ## 界面上明说的三个前提(不藏)
    
    1. transcript 按 (公司, 角色) 分、**不按节点分**,只能用节点 started_at/completed_at
       截时间窗口 —— 近似而非精确对齐,窗口边界原样显示。
    2. <env_status>(harness 每轮注入的环境块,几 KB 机器噪音)服务端剥掉,
       但**剥了几处如实显示**。静默删内容比留噪音更坏。
    3. 默认只看 agent 说的话;喂进去的内容(提示词全文、工具返回)要勾选才出来 ——
       提示词里有写入边界与公司上下文,不默认摊开,但可以看。
    
    subgraph 节点不给这个 tab(它自己不调 agent,活在子图里)—— 给了就是个空 tab,
    而空 tab 会被读成「没记录」。正在跑的节点靠「刷新」取最新,**不轮询**
    (整份会话几百 KB,跟着 run 状态轮询太贵)。
    
    ## 三处「看着对、实际错」都有用例钉住
    
    ① listRoles 的目录前缀差一个 '-':path.join 丢掉空的最后一段,切出来的角色名
       全带前导 '-'(实测 '-sdd-planning')。我是靠肉眼看输出发现的,所以补回归测试。
    ② 路由取本体取错层:本体绑在定义层节点上,graph_run_nodes 只有 def_node_id,
       第一版直接读运行时行 → SqliteError: no such column。
    ③ 找不到文件时回 ok:false + 期望目录,不回空列表 ——
       空列表会被读成「这个 agent 没说过话」,而真相是「我们没找到文件」。
    
    另外测试当场抓到我自己那个诚实机制的漏洞:整条正文都是 env_status 的条目会被剥空,
    normalize 早返回 null 导致它剥掉的那一处**没计入总数** —— 号称如实回报却少报。
    改成 parts 空但剥过东西时仍返回,由 readEntries 先记账再决定入不入列表。
    
    ## 验证
    
    880 全绿(88 文件)。3 处变异精确变红后逐字还原。
    运行中的实例上走查过:org-planner-sdd 的原文逐条带时间戳显示,
    第一条就是它去读上游 prd.md / contract.json —— R-19 那条链路被 agent 真的用上了。
    subgraph 节点(org-planner)确认没有这个 tab。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • 用错了变量:写的是 `background: var(--bg-surface, #fff)`,而 `--bg-surface`
    不是「不透明表面」,它是 2% 的叠加色调(App.vue 里深色 rgba(255,255,255,0.02)、
    浅色 rgba(0,0,0,0.02))。于是弹框几乎全透,把身后 42% 的遮罩透了出来;
    文字色 var(--text-primary) 又跟着主题走成近白色,叠起来就是一片看不清。
    以为兜底的 #fff 永远轮不到 —— 变量确实存在,只是语义不是我以为的那个。
    
    该看的是周围的约定:**整个控制台是硬编码浅色的**
    (GraphConsole.vue:363 `.console { background:#fff; color:#1a1a1a }`,
    NodeDetailPanel.vue 里 CSS 变量用了 0 次)。我的弹框是唯一读主题变量的组件,
    所以只有它坏。改成与邻居一致的硬编码浅色,遮罩阴影 .18 → .28 让边界更清楚。
    
    在运行中的实例上用真实产物核过(mycompany 的 brd.md):白底、标题/表格/列表
    渲染正常。871 全绿(纯样式改动,无逻辑变更)。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • ## 为什么加
    
    「输入输出」tab 把产物的绝对路径摆出来了,但那是服务器本地路径 —— 浏览器里点不开,
    走查时只能靠肉眼确认「路径长得对」,而真正要确认的是「这份 brd.md 里写了什么、
    下游读到的是不是它」。
    
    ## 前端
    
    新增 web/src/components/graph-console/FilePreviewModal.vue,输入/输出两处路径
    改成可点按钮。渲染三档:.md 走 marked(已是既有依赖,没新增包)、.json 重新缩进、
    其它原文。两处刻意的选择:
    - .json 解析失败时**退回原文**并说明,不替它藏起来 —— 产物 json 写坏了本身就是要看的信息
    - 超过 512KB 时后端回 truncated,界面如实说「不是完整内容」,不装作读全了
    output_ref 那一行不做成可点:它是目录不是文件。
    
    后端没有新造端点:复用现成的 GET /api/company/:cid/files/content,它的根目录正是
    data/companies/<cid>,而 graph_files.rel_path 本来就是相对公司根的,正好对上。
    
    ## 修掉六处路径越界(真漏洞)
    
    company.js 里 3 个 GET + 3 个 PUT(templates / company / workspace)用的是同一个写法:
        if (!absPath.startsWith(safeBoundary)) → 403
    「一个目录名是另一个的前缀」时它会放行:
        cid = co-a,path = ../co-a-evil/company.json
        → abs = .../data/companies/co-a-evil/company.json
        → startsWith('.../data/companies/co-a') === true → 放行
    于是公司 co-a 能读 co-a-evil 的文件;PUT 那三处是同一缝隙上的跨公司**写**。
    抽 resolveInside() 用 path.relative 判断,六处共用一份(复制六份判据迟早会漂)。
    新增 7 条用例走真 HTTP 验,PUT 那条断言的是**文件没被改**而不只是响应码。
    
    ## 顺带修掉一个被你的实际使用触发的 bug
    
    跑全套时 graph-seed-service 的对账用例红了,报
    `org_graph_nodes WHERE company_id='mycompany' expected 10 / actual 9`。
    不是并发偶发 —— 单跑也红。原因:seedCompanyAgents 对 type='meta-bootstrap' 的角色
    是 continue(既不落 org_graph_nodes 也不落 system_agents),而 verifyCounts
    复算期望值时把 agents[] 全算进去。mycompany 的 10 个角色里 orggraph-planning
    正是 meta-bootstrap → 差 1。
    
    也就是说:**界面上点一遍新建公司就会踩到**。这条缺陷上一轮就被预告过
    (当时那个 agent 说「不在我的独占文件里」没修),今天被真实使用兑现了。
    修法是让 verifyCounts 复用同一个 isMetaBootstrap 判据,不复制那个 type 判断。
    新增独立测试文件(不并进 graph-seed-service.test.js —— 往它的 hermetic 夹具里
    加角色会连带改既有断言),用 GRAPH_SEED_ROOT 自建最小夹具。
    
    那个文件里第二条用例是刻意的:只断言「对账干净」时,seed 一个都没种也会“通过”,
    两种原因症状相同。第一版就是这么错的 —— 我误以为 runStartupSeed 会种公司角色
    (它只做 reconcile + 全局 agent + 模板),是第二条断言把「夹具没种」和
    「过滤没生效」分开的。
    
    ## 验证
    
    871 全绿(87 文件)。3 处变异精确变红后逐字还原
    (startsWith 回退 → 精确打红跨公司读/写两条;verifyCounts 去掉过滤 → 打红对账条)。
    拿运行中的实例 + 用户真实公司 mycompany 走查过:读到真实 brd.md 内容,
    `../idearun/company.json` 与 `/etc/hosts` 均 403。web:build 通过。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • R-19.A 把 declareEdgeContract 的调用方补上之后,inboundContracts 终于非空,
    「沿边传递」这类数据流在真跑里生效了(真实规划 agent 自己在边上写出了
    produces/needs 声明)。本次收掉它留下的三个缺口。
    
    1) role 落库(第 14 次「四环漏一环」)
       normalizeContracts 产出 role,declareEdgeContract 入参没有它、表也没这列 ——
       产生 → 传递(丢) → 落库 → 读回。后果不止是控制台不精确:规则 6(data-contract)
       靠「有人 needs 但没人 produces」判错,只存 kind 就没法从库里重算,而
       patchGraph 第 5 步的重新校验读的正是库 —— 增量 PATCH 又恰恰是
       「此前满足的 needs 失去产出方」的唯一发生地,校验偏偏在最该生效的通道上失效。
       - graph_edge_contracts 加 role 列(CHECK + 老库 ALTER 后回填 produces:
         NULL 在规则 6 里既不算产出也不算需求,会误拒一张合法的图;闸门宁可漏判不可错拦)
       - 两层调用点透传 role;readGraph 把 contracts 读回来并递进 validateGraph
    
    2) 控制台三字段(前端在、后端没喂)
       GET /api/graph-runs/:id 补 edges[].contracts / companyRoot / taskFiles,
       否则 R19-C 那三块界面整块降级:声明和索引都在库里,界面上看不见。
       contracts 只在非空时出现,与 failReason 同一个约定。
    
    3) 收拢 companyRootDir/taskDirRel 镜像
       goal-contract.js 里那份镜像靠注释约定「与 graph-engine 逐字同构」维持,
       控制台路由成为第三个调用方时这个约定就不成立了。抽到 company-paths.js,
       GRAPH_RUNS_DIR 改为调用时读(原先两个模块各自在加载时快照,
       加载顺序不同会算出不同的根)。goal-contract 那条「镜像漂了就报警」的用例
       按其自身预告改成比函数返回值。
    
    测试 826 全绿(+11:role 8 / 路由 3),既有断言未改。
    11 处变异逐一验证精确变红后逐字还原;其中一条断言初版在 fixture 上永远自洽
    (图里没有无声明的边),补了一条无声明的边才真正有判别力。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • 测试 786/786 全绿(76 文件,起点 760/72),未改任何既有断言。
    
    ## 本轮三件新东西,全部经真 CLI 验证
    
    W12 补完 · 失败原因四环打通
    - 引擎自判的失败(executor 抛异常、边界越界、子 run 无归因)现在也落
      graph_run_nodes.fail_reason,不再只有 agent 归因产出的才有值
    - 概览 tab 展示「[引擎判定] boundary_escape」+ 终端样式 excerpt,
      取不到 fail_reason 时回落 output_excerpt,并标明来源
    - 真跑实查:两行 fail_reason='boundary_escape' 都在库里,
      产生→传递→落库→读回四环在真 CLI 下走通
    
    W13 · 运行态文件根治(守卫误判的根因)
    - 17 个 todo.md / plan.md / scheduled_tasks.json git rm --cached + gitignore;
      源码(agent.md/config.json/soul.md/tools.md)一个未碰,模板本体仍跟踪
    - _registry.json 的 usedCount 挪进已忽略的 data/template-usage.json
    - 真跑验收:整轮(agent-creator、Master 各一次真 CLI、3 次 hire)结束时
      worktree git status 与基线逐字相同,_registry.json 零 diff
    
    单步进度感 · 真 CLI 一个节点 3-7 分钟
    - 画布卡片秒表 + 详情面板常驻条「运行中 2m40s · 最近事件 …(2m40s 前)」
    - 不做假进度条:引擎不知道 agent 还要多久
    - 顺手修 NodeDetailPanel 不跟 SSE 走(否则秒表也不会动)
    
    W9 失败上下文进提示词、W10 跨层地址两半、W11 Hot Swap 显式告警同批完成。
    
    ## 真跑结论:链路更长,但「work 节点 → success」仍未跑到
    
    走到:orggraph-planning 落图自雇 → agent-creator 补定义 → workgraph-planning
    真跑规划 + **先雇后提交**(W5/W6 再次成立)→ 子 run 起来 → work 节点 RUNNING
    → 7m19s 后 fail。两层原因叠加,都与 W1-W14 无关:
    
    1. **新缺陷**:agent-manager.js:324 把 idleTimeoutMs 硬编码 120s,
       readme-writer 通读源码静默超 2 分钟被掐死(动笔前就死了)。
       同进程 ClaudeCliProtocol 早把自己的 idle 上限放到 24h,
       stream-executor 的 JSDoc 默认值写的是 30 分钟 —— 这里把两者都压掉一个数量级;
       且 ...options 透传的 idleTimeoutMs 会被下一行覆盖,调用方无法覆写。
    2. **并行 agent 污染**:retrain-watchdog 每 5 分钟唤起的 Master 在同一工作树里
       改了两个源文件,被守卫 git status 差集算到该节点头上 → 额外署 boundary_escape。
       这是 W3「拦不住」第 5 条第一次真实发生。
    
    顺带记一笔:这一轮任务是 **LemonBoss 自己的 Master 自主下的单**,
    走的正是 POST /api/company/:id/tasks,它还自行诊断出了上面那个 idle timeout
    并动手改(引用了未定义的常量,是坏的)。
    
    ## 已知未修(下一轮)
    
    - idleTimeoutMs 硬编码 120s —— 「work 节点 → success」跑不通的唯一技术原因
    - W7 在**零边最小图**上失效:判据③要求存在 active org_graph_edges,
      零边图上三条判据全落空,work 层本体被写进 org_graph_nodes。
      服务层那 9 例测试造的都是有边的成型图,正好绕开这个形状
    - 前端 ACTIVE_RUN 含 blocked、后端 ACTIVE_ROOT_RUN_STATUS 不含:
      一家公司只要失败过一次,控制台上就再也下不了第二个任务(后端其实放行)
    - 真跑期间工作树里不能有第二个 agent 活动,否则守卫判罚不可信 —— 应写进真跑规程
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • ## W14 · POST /:cid/tasks 补上前端调用方
    
    该端点此前**全仓库没有任何前端调用方** —— 界面走查确认过:用户在控制台上
    没有任何办法给公司下达任务,只能 curl。这是「实现在、零调用方」在 P3 里的
    第 N 次出现(W8 刚给 replan 补上,tasks 还欠着)。
    
    新增 DispatchTaskButton.vue:
    - 手动/自动**在下达时就选**,不是跑起来再改 —— execution_mode 是 run 的属性,
      起 run 时定;后补一个下拉会让人以为能中途换
    - 自动模式在这一步就给成本预警(真 CLI 一次中等任务 $10-20 / 1-2 小时),
      GraphRunPane 的「启动」那道确认是针对已有 run 的,下达是更早的闸门
    - 409(v1 并发约束)连同服务端 hint 原样透出,比翻译成「出错了」有用
    - run 在跑时按钮直接不出现,而不是让人点了吃 409
    
    挂载:有图未跑 run 时给主操作位(这时候它是页面唯一该做的事),
    有 run 时收进标题栏。顺手修 .left-actions 缺 gap 导致两个按钮重叠。
    
    ## 第二次真 CLI 冒烟(worktree 隔离,主仓库 data/ 零写入)
    
    链路比上一轮走得远得多,两个硬缺陷的修复都在真跑中直接验证:
    
    1. **R-18.1 端到端成立**:POST /create 自动触发 orggraph-planning 真跑,
       它自己把图落库(3 节点 4 边,含两条 backward fail 边)**并自己雇了
       org-planner / org-coder / org-validator** —— Step 7 的招聘真执行了。
    2. **W5/W6 自雇再次验证,且规划质量明显更高**:workgraph-planning 规划出
       brd → prd → benchmark → validator 四节点主干,两条回退边一条带
       fail_reason=input_underspecified、一条无 reason 作兜底 —— 它自己用上了
       D.2.2 的细分路由并满足 fail-fallback-edge 规则。四个本体全部自雇。
    3. **守卫归属修复直接命中**:timeline 里
       「本次调用窗口内有 1 处 agent 运行态文件改动,无法归属到本节点,不计入越界
         unattributable = ['M system/agents/agent-creator/.claude/scheduled_tasks.json']」
       ——正是上一轮把成功节点判成 fail 的那个文件,这次被正确摘出,
       org-planner-brd → **success**(上一轮它跑起来了但被误判)。
    4. tokens 真的在计量(24,218),mock 下恒为 0。
    
    产出位置正确:brd.md 落在 runs/<rootRunId>/nodes/<nodeRunId>/,
    项目根 projects/p-4hjo36 按 root run 分配。worktree 源码跑完已复原到跑前状态。
    
    测试 760/760 全绿(72 文件)。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • 真 CLI 冒烟(worktree 隔离,PORT 3010)九轮来首次把 work 节点跑起来:
    orggraph-planning 真跑 3 分钟自主裁成单 org node 零边图 → workgraph-planning
    第 1 轮产出合法图 → **自己按 Step 6 把 brd-planning / planner-validator 雇进公司**
    (W5/W6 核心验收成立,且 W7 判据生效、两者都没写进 org_graph_nodes)→
    第一个 work 节点 brd-planning 真起 CLI 子进程,产出 brd.md / contract.json /
    attempt-0.json 全部落在 run 目录内。图内预算仅 2 次调用 / 13998 tokens(上限 15)。
    
    W5/W6 · workgraph-planning 自雇:撤掉「你不招人也不辞人」,Step 6 加招聘环节,
      写死「先雇、再提交图」的顺序,给出失败分级与幂等要求
    W7 · work 层招聘不写 org_graph_nodes:按 type 与 work graph 骨架点名两条判据区分层级,
      P2 「hire org 角色 → org graph 出现该节点」的语义保持不变
    W8 · 控制台「规划组织结构」按钮(抽成 ReplanOrgGraphButton.vue,带过渡态与秒表),
      接 POST /:companyId/org-graph/replan(该端点此前无任何前端调用方);
      新增 fixtures/devloop-mock/orggraph-planning.json
    W12 · 节点失败留痕:node.output 带 output_excerpt、新增 node.error 事件。
      真跑当场救场——守卫误判那条归因正是靠它才查得出来,
      换成之前看到的只有「节点 fail、无原因、无痕迹」
    
    测试 753/753 全绿(71 文件,起点 736/68)。
    
    已知未修(下一轮):子 run 转终态不回写父 node_run 导致任务永久卡死;
    applyBoundaryGuard 用整仓 git diff 判归属会把并行 agent 的写算到当前节点头上;
    W12 的 fail_reason 未落库(概览 tab 仍为空);POST /:cid/tasks 无前端调用方。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »

  • 界面走查(真 server + HTTP + 真 AgentManager,底层 mock 协议)已把
    manual 模式全流程点通:org 节点起子图 → 下钻 work graph → 单步 →
    第 3 步触发回退(徽标 0/3→1/3、run 级 1/5 双层计数同时可见)→
    归因记录与 remediation_note 完整送达 → 收敛后父节点结算、左栏前移。
    
    mock 侧补两处缺失接线(都是「四环漏一环」,非新功能)
    - ClaudeCliProtocol._sendMockPrompt 按 agent 类型查 fixture:图执行侧的
      agent 名带公司前缀(resolveAgentName 返回 {cid}:{id}),fixture 不该
      按公司复制一份。DevLoop 侧名字不含冒号,行为不变
    - graph-engine.defaultAgentExecutor 接住 mock/files 事件:此前只有
      DevLoop 的 loop-controller 接,图执行侧没接,于是 mock 下
      readNodeProduct 永远找不到 attempt-{n}.json,validator 系节点恒 blocked。
      写入限制在节点产物目录内,越界丢弃并留痕
    
    新增 5 份 P3 fixture(workgraph-planning / prd-planning / sdd-planning /
    coder-validator / validator-triager),coder-validator 用 sequence 演示
    一次回退。图必须放 chunks 不能只放 result——callAgent 的 output 来自
    流式 chunks,session/result 的文本不进 output。
    
    控制台入口:CompanyDashboard 加「🕸️ 执行控制台」按钮(路由早已注册,
    此前无任何入口,只能手敲 URL)。
    
    scripts/p3-demo-setup.js:手工测试准备脚本(雇人+写图+起 run),头部
    写明它是两个已知缺口的绕行,缺口修好后第 1 步即可删。
    
    _registry.json 补齐 6 条本体登记(brd/prd/sdd-planning、goal-benchmark、
    benchmark/testdata-validator)——同轮新增的 template-refs 防线测试正是
    因为缺这 6 条而变红,防线抓到了「交付与报告不符」。
    
    文档
    - 27-REQ R-18:招聘归 workgraph-planning(方案 a)、停用 mock 改真 CLI
    - 27-P3B 真实运行前置(新增):11 个工作项分三批,含现状核实 10 条证据
      (seedTemplates 无运行时调用方、10 条悬空 company_hired 行、
       FAILING_VERDICTS 不含 "fail" 导致验收假放行等)
    
    测试 719/719 全绿(66 文件)。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »
  • 按 27-p3-p4-work-graph-console.md v0.3 实现,三轮开发+校验后测试全绿
    (693/693,P2 26/26、DevLoop 230/230 未被打破,web:build 干净)。
    
    服务层
    - work-graph-db.js  定义层(work_graph_*) + 运行时层(graph_runs/graph_run_nodes/
      graph_run_loop_records) 五张表;状态转换表照 unit-registry 模式;
      复用 org-graph-service 四项校验 + 新增第五项 fail-fallback-edge
    - graph-engine.js   advanceOne 幂等原语;agent_call / subgraph 两种 executor;
      手动与自动共用同一原语;双层熔断(单边 loop_count + 按 root_run_id 共池的
      backward_count);任务级预算挂 root run;三层暂停/停止级联;
      重试按 contract_hash unchanged 判据
    - graph-run-sse.js  按 run_id 广播,状态转换+timeline+SSE 三者原子化
    - goal-contract.js  验收契约格式与执行器(R-15.6 验收先行)
    
    引擎泛化(R-15.4):org graph 与 work graph 走同一套 advanceOne,
    定义层两套、运行时层一套,三层下钻用 parent_run_id 链。
    
    R-16 失败归因:validator-reflection 专职归因节点;fail_reason 多边路由
    (精确匹配→兜底边→死路);子 run 收敛透传 success/fail + fail_reason +
    remediation_note 三值;infra_flake 不烧任何计数。
    
    路由 / 前端 / 模板
    - routes/graph-run.js 八个端点;company.js 任务入口
    - WorkGraphCanvas.vue 扩展 UnitsDAG(subgraph 角标、backward 虚线曲线、
      N/3 循环徽标、异常流程视觉降权);GraphConsole.vue 三栏 + 四 tab 详情
    - 五个新 agent 模板:validator-reflection / org-validator / planner-validator /
      coder-validator / workgraph-planning
    
    命名统一(R-15.3 + NAMING §三):org 节点改为 org-{职能},
    三个 org-graph 模板末节点收敛到 org-validator;org_graph_edges 加 fail_reason
    列并把唯一索引补上该列(避免精确边与兜底边互相吞掉)。
    
    三轮校验修掉的主要缺陷:subgraph 重跑不起新子 run 导致永久死锁;
    SSE/timeline 零调用方;org 侧 fail_reason 写入被丢弃;fail-fallback-edge
    只做了一层;backward_count 跨 run 树重置架空熔断外层;
    seedEntryNodes 误点亮只有 fail 入边的节点。
    
    已知缺口见后续提交:remediation_note 仅在 backward 边落库、
    total_tokens 预算维度无生产方。
    
    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    yibo authored
     
    Browse Dir »