dsh-loopx-plugin
huangruiteng/loopxLoopX——面向长周期 Agent 的提供商中立、本地优先状态内核与控制平面:在 DeepSeek Harness 执行层之上持久化 Goal、Todo、门禁、证据、配额、恢复与交接状态;插件负责引导安装 CLI 与技能、准入有界的同会话续跑,并为精确绑定的工作循环提供本地 GoalBar。
DeepSeek Harness 会话任务看板:主窗口把任务派发给一次性 Worker/Verifier 子代理执行与验收,支持依赖调度、文件级排他锁、裁决挂起冻结、里程碑进展上报与任务级 Token 消耗统计。
智能看板插件 — agent 团队的持久台账与治理层:把「派发 → 执行 → 验收 → 度量 → 复盘」跑成全链路闭环,每一张卡都是可审计、可度量的长期资产。
dsh-agent-board 是 agent 团队的持久台账与治理层——看板只是界面,内核是「派发 → 执行 → 验收 → 度量 → 复盘」的全链路闭环。 它与「一次性组队、跑完即散」的冲锋型编排器、「人建卡、agent 认领、人逐张验收」的手工看板不是一个代际:
acceptance 硬性脚本命令由 Worker 实跑、Verifier 独立复跑;结论分通过 / 驳回并逐条给证据。人只看该看的——风险队列「待你过目」把该亲自确认的卡推到眼前,其余交给机器闭环。流水线归机器,审计台归人。 我们不造「跑完就散」的冲锋队,也不做「人逐张盯着验收」的手工看板;我们的信念只有三条:验收独立复跑、人只看该看的、数据沉淀成资产。别人负责冲锋,agent-board 负责记账与验收——互补,不对抗。
dsh --profile web宿主 DSH 版本 · 应装插件版本 · 原因 ≥ 0.2.0(含 rc) · ≥ 1.3.0(必须) · 0.2.0 起宿主在启动/安装时强制校验 peerDependencies,区间不含 0.2.0 的包直接拒绝激活(路由不挂载、面板不出现)。1.3.0 声明 ^0.1.7 \ · \ · 0.2.0-rc.2 \ · \ · ^0.2.0——注意 semver 预发布不命中宽区间,0.2.0-rc.2 必须显式枚举。运行时 API(subagents/systemPrompt/agents/uiWorkspace.openSession/sessions/v4 日志格式)在 0.2.0 全部兼容,已过 0.2.0-rc.2 实测(E2E 23+8 断言全绿) 0.1.7 ~ 0.1.7-x(含 rc) · ≥ 1.2.2(必须) · 0.1.7 会话日志升级为 format v4:插件消息 source.kind 必须是生产者自有 kind。1.2.1 及更早会在任务完成/阻塞回执落盘时抛 SessionFormatError: format v4 message requires a producer-owned source kind,并连带使主窗口当前轮次失败(表现为「本轮运行失败」);同时「跳转会话」因宿主移除 sessions.open 而失效(控制台 sessionsSvc.open is not a function),卡片活动心跳读不到 v4 日志(session.v4.jsonl.zstd) 0.1.5-rc.1 ~ 0.1.6 · ≤ 1.2.1 · 1.2.2 起按 0.1.7 协议编写(v4 source kind、uiWorkspace.openSession 跳转),旧宿主未做回归验证,建议停留 1.2.1
dsh plugin --profile web add dsh-agent-board@latest # 0.1.7+/0.2.x 宿主(推荐)
dsh plugin --profile web add dsh-agent-board@1.2.1 # 0.1.5/0.1.6 宿主从 ≤1.2.1 升到 ≥1.2.2 必须重启 DSH(host 端代码在启动时加载;1.2.2 之前的老版本还有一个路由残留 bug:禁用/启用热重载会撞 duplicate exact route,只能重启恢复,1.2.2 已修复)。已发布至 npm 官方 registry(dsh-agent-board):
dsh plugin --profile web add dsh-agent-board
# 重启 dsh 生效
dsh --profile webgit clone https://github.com/PPawnsir/task-board-plugin.git
dsh plugin --profile web add <本仓库绝对路径>/packages/dsh-agent-board
# 重启 dshplugin tree failed to loadcurl -X POST http://127.0.0.1:3080/dsh-agent-board \
-H "Content-Type: application/json" \
-d '{"method":"get-tasks","args":{"sessionId":"<sessionId>"}}'返回 JSON 即正常;405 空 body 说明路由未挂载。
# 市场版
dsh plugin --profile web add dsh-agent-board@latest
# 源码版
git pull
# 两者都需重启 dshdsh plugin --profile web remove dsh-agent-board
# 重启 dsh看板数据存在 ~/.dsh/tasks-.json,卸载不删数据。- 归属:看板文件按会话分文件,同时在文件里记ownerCwd(创建该看板的会话工作区路径,取不到则省略该字段)——~/.dsh/tasks-*.json每个文件是一块看板,list-boards全局视图可看到本机所有板。
- 重启继承:DSH 重启后同一会话的根 id 可能漂移,此时新 id 没有对应文件——若同工作区(ownerCwd严格相等)存在唯一「原主已不在agents.roots()」的看板,则自动继承:文件重命名为新 id、文件内ownerSession改写为新 id、console.error留一行[task-board] 继承看板 →;多个候选一律不自动接管(记一行日志后按空板处理,防误合并,旧板仍可在list-boards全局视图里看到)。
- 写盘保护:落盘走 临时文件+rename 原子写(EPERM/EBUSY 退避重试);瞬时读失败/坏文件隔离后返回的空板禁止回写(防一个"读不到"的瞬间把看板覆成空板),坏文件隔离为 .corrupt- 留档不丢数据。看板数据(~/.dsh/tasks-.json)是本插件唯一的持久化状态,按三层防线保证数据不丢、事故可见:
fsync → rename 覆盖目标」——rename 在同分区是原子的,进程在写盘中途被强杀时磁盘上最多残留一个 .tmp 残件,看板本体永远不会是截断的半个 JSON。Windows 上 rename 覆盖已存在目标原生支持(实测直接覆盖成功),仅当目标被并发读句柄/Defender/索引器瞬时占用(EPERM/EBUSY/EACCES/ENOTEMPTY)时做有限退避重试;重试耗尽仍失败则降级「先 unlink 目标再 rename」并留日志——绝不丢整板。.corrupt- 留档隔离(防反复 poison),同时在「架构健康」区亮一条 err 级红条(healthHints)提示「看板数据文件腐坏已隔离,历史在 .corrupt-,可联系恢复」,并向 owner 会话推送通知——数据不丢,也不再静默从空板重启。JSON.parse 报错 position 截断法,与人工恢复同款手法),成功则以抢救出的完整板为底自动写回继续(healthHints 红条记「已抢救保留 N 张卡,丢弃撕裂残片」),失败才回退空板。两种情况下原始文件都留档 .corrupt-,可随时人工恢复。核心能力一页速览(★ 为 v1.7.5–1.8.4 新栈):
subagents.start/startContinuable 统一重构为 startActivation(spec)——能力探测自动选路:新契约按 delivery 语义分发(continuable=parent 结算留言 / 一次性=caller 只回 result),Activation 适配旧 run 形状下游零改动;老宿主逐字走旧双路径)+ continuable 结算兜底臂(activation.result 在子会话被宿主拆除时落定即接失败结算——rate-limit/模型崩溃的死子不再挂到硬超时)★:硬性验收脚本独立复跑、驳回全量带回重派、Verifier 自测指南(userTest)、风险队列「待你过目」、验收时序防护(Verifier 在场时主窗口抢批需显式 force:true;有活跃 run 的卡禁止归档;Verifier 迟到结论落 lateVerdict 留痕+直投告警)、迟到 verdict 三保险(①入参校验:verdict 非 approved/rejected 拒收并返回重调指引——漏带字段不再被当驳回落账;②通知分态:approved 迟到=「✅ 迟到复核·全过追认」notice 级,🚨「迟到驳回」只留给真 rejected;③指纹去重:同 taskId+by+verdict 只投一次,重复落账零重复通知)★:Token 消耗(总量 / 有效 / 缓存读,按模型·按任务·按日)+ 记分卡(模型表现 / 质量趋势 / 驳回聚类)★:运行时健康自检(派发冻结 / 结算停滞告警)、异常驱动审视(风险队列 / 质量异动告警 / 批次摘要)、起草 lint、数据安全(原子写盘 / 腐坏隔离 / 自动 salvage)、僵尸 run 留档清扫(host 重启后「落定卡上的 running 无 endedAt 留档」在派发周期自动关账 stale-closed + 清认领位,归档门禁不再被幻影 run 永久拦截)、子会话生命周期收口(一次性 run 落定/迟到 verdict 落账后主动 interrupt 子会话——「结算≠停止」空转根治;continuable 收紧为「续跑位真在本 child 手上」才豁免,残影 Worker 无处藏身)、terminate 三保险(no-rec 也按认领位盲杀补刀 + interrupt 失败 err 级可见化 + hold:true 原子「终止+转手动」)、配置审计(set-board-config 成功写入落板级 configLog {key,from,to,actor,at} 截尾 50 条;模型下拉两段式选中≠保存)以下各节是完整规格。
delegationDepth(fork/seed 会话 depth=0 认根;真子代理 depth≥1 才隐藏看板入口),不再误把带 parentSession 的 fork 当子代理currentColor 跟随主题,浅深色自适应)zoom 等比缩放(字体/图标/间距一并放大,只影响本面板、不碰宿主页面),选中即时生效并 localStorage 本地记忆(键 dsh-agent-board-ui-zoom)⛁ 数字);区底固定口径 caption:累计 / Top 8 仅看板派发的 run 消耗,主窗口行并列不混入e=null)的「今日显 — / 矮灰柱」防护顺势退役(总量恒有值,正常画柱,悬浮注明有效不可知)。不动的:「模型表现」「质量趋势」区保持有效口径(效率指标语义),报告导出分列口径不动。实证背景:本板累计 10.3M 里缓存读占 9.7M(94%)——总量与有效的差额一眼可在累计三分量与悬浮里对照task-muxnqunk 翻转版,替代 task-muwq9u04):按模型分布行与任务消耗 Top 8 行的主数字一律为总量(含缓存读;模型取 host 的 byModel,任务取 topTasks[].total),有效消耗(byModelEff 模型有效分摊 / topTasks[].effective)进悬浮 title——与「今日」「近 7 天」同口径;老 host 缺 byModelEff 或老卡无五分量留账时 title 标「有效不可知」(口径不伪造)task-muwc7hjd):仪表盘顶部的「统计范围」(快捷:今天 / 近 7 天 / 近 30 天 / 全部 + 自定义起止)现在同时作用于 Token 区的按模型分布 / 任务消耗 Top 8 / 累计三分量——范围变化即用新范围重拉 get-tasks,由 host 按每个 run 的本地日落点(t.runs[i].at → YYYY-MM-DD,两端闭区间)过滤:范围外 run 不计入 total/byModel/top,byDay 同步裁到范围内;范围激活时 Token 区标题带「范围内: …」标记。今日大数字与「近 7 天」柱子是自身固定口径,不随范围变化(区底第二行 caption 与范围筛选浮层均写明)。无范围(两端皆空)时聚合结果与旧版逐字一致(parity);无 run 级留账(老卡 / runs 条目未落 usage)退化为按 updatedAt 本地日判定,无 at 的老 run 只在无范围时计入(宁可漏不错),run 未记模型名时按入选 run 占比摊任务级模型小计(合计与有效同法摊派,ΣbyModel 与入选总量、ΣbyModelEff 与入选有效各自对齐)。数据源口径修正(`task-muwq9u04`):run 记录数组在任务级 `t.runs[]`(t.usage.runs 只是结算次数计数)——此前误把计数当数组读,范围过滤静默退化成 updatedAt 单日近似、Top 8 与无范围逐字相同;现已逐 run 精确裁切,且范围切换后客户端按 usageSummary 的 JSON 串比对补一次 notify(选范围即渲染,不等下一次任意刷新)。Token 口径三连修(`task-muwsnyqv`):① 范围内 byDay 按入选 run 的本地日落点逐日重建(to 端闭区间,from=to=今天 时今天不丢——修「范围含今天时 total 含今天、byDay 却吞今天」);② usageSummary 同时返回未过滤全量 `byDayFull` 与范围内 byDay,「今日」「近 7 天」改读 byDayFull 兑现固定口径承诺(老 host 缺字段退化读 byDay);③ ~~旧口径日灰柱防护~~ 已随口径翻转退役(task-muxnqunk):总量主显后 e=null 的旧口径日就是正常柱(t 恒有值,柱高按总量归一),不再画矮灰柱 / 今日显「—」,有效不可知只在悬浮 title 注明~/.dsh/sessions/*//session.v4.jsonl.zstd),把 assistant/message 事件的 usage(inputTokens / outputTokens / cacheReadTokens / cacheWriteTokens / totalTokens,字段形状以真实日志为准)按 zstd 帧逐帧累加到任务 usage(含按模型小计、runs 计数与 byDay 日账——本地日 YYYY-MM-DD,一次 run 整笔记在结算日;多轮重跑/驳回重做自动累加);run 级留账:本次用量同时原样写回 t.runs 对应条目的 usage(五分量俱全),因此按天 / 按模型 / 按阶段任何维度都能从 runs 精确重建,口径若要再调整不必回头猜byDay 为双指标形态 { t, e }(t = 总量含缓存读,e = 有效消耗不含缓存读;一次 run 不跨日拆分)。聚合端兼容老数据:值是裸 number 的历史日账按 { t: n, e: null } 处理——总量照常保留(「近 7 天」不会整段消失),有效值不可知就置 null;口径翻转后(`task-muxnqunk`)旧口径日按总量正常展示(今日大数字显总量、近 7 天按总量画柱),有效不可知只在悬浮 title 注明——task-muwsnyqv 的「显 — / 矮灰柱」防护已随总量主显退役get-tasks 再现算 board 级 usageSummary(总量 / 有效合计 / 按模型(合计 byModel + 有效分摊 byModelEff,两者同源累加)/ Top8(带有效与缓存读拆分)/ 日账双份(范围内 byDay + 未过滤全量 byDayFull,后者供「今日」「近 7 天」固定口径读取),不落盘额外表;老任务无 byDay 时整笔近似归到 updatedAt 的本地日,无 updatedAt 则不计入任何日)——只做展示、不做计费断言,日志读不到或没有 usage 时一律显示「暂无数据」;第二参 range(可选 { from, to } 本地日)给定即只聚合该范围内的 run(口径见上条)task-muwsol23):累计行下方新增一行「主窗口(本会话):今日 X · 累计 Y」(总量口径含缓存读——task-muxnqunk 翻转后缓存读不再单列、已含在 total 里,有效值见悬浮 title),按模型分布尾部追加一条「主窗口(对话)」(琥珀色与 run 模型区分,总量为 0 不渲染,固定尾部不参与排序);数据源是该看板所属主会话自己的 v4 日志,host 侧增量尾读聚合(缓存键=会话 id:文件不变零读、变大只读新增字节段、变小/轮换全量重读一次,尾部半帧不结算下轮补读——3s 轮询稳态零全量重读),五分量与有效口径(e=输入+输出+缓存写)同 Worker 完全一致;隔离红线:不进 Top 8、不进「本看板累计」、不进架构健康/学习飞轮基数,只并列展示;随统计范围裁剪(按 assistant/message 事件的本地日落点);日志不存在/读取失败/无 usage 一律静默降级(不渲染该行,不炸轮询)task-muxhtgi2):Token 区下方新增模型 × 场景八指标对比表——每行一个 模型 × 角色(worker/verifier)× 规模段(小 10M,按任务有效 token 分桶)桶;八列口径一句话版:有效均值 = 桶内 run 有效消耗(输入+输出+缓存写,不含缓存读)的均值、耗时中位 = run 耗时(endedAt−at)中位数(P90 在行 title)、驳回率 = 归因到本桶的验收驳回 / 桶内 runs、一次通过率 = 桶内 resolved 任务中零驳回占比、超时率 = 超时落定 run / 桶内 runs、失败率 = 跑崩落定(incomplete/error/failed)run / 桶内 runs(terminated 人工终止不计入,task-mv73ym6i)、续跑率 = resume 续跑记录 / 桶内 runs、缓存命中率 = cacheRead/(input+cacheRead)(⚠️ 跨 provider 对比先核 input 是否含缓存读);表头列名均带 title 口径说明;表头下两个本地筛选器(角色 全部/worker/verifier + 规模段 全部/小/中/大)只在已返回的 scoreboard 上过滤、不重拉;桶内 runs<5 整行灰显 + title「样本 <5,仅供参考」(不参与任何「最优」强调);无数据显「暂无足够 run 数据」;Token 区 caption 新增「→ 模型表现」锚链接一键滚动到位。数据源 = get-tasks 响应里的 usageSummary.scoreboard(卡2 host 聚合底座 buildScoreboard,与 Token 区同一统计范围口径裁剪)task-muxhtgil):模型表现区下方新增全局趋势四块(P1 质量 KPI 并入)——一次通过率(近 14 天柱形:当日落定 resolved 任务中零驳回占比,今日柱高亮 + 块头标今日值,无落定日画灰基线不假装 0%)、卡时长分布(四桶横条 60m,创建→落定墙钟含排队/验收全程)、超时率走势(近 14 天迷你柱行:当日超时落定 run / 当日 runs)、续跑成功率(resume 续跑记录中 completed 占比,范围总量口径、host 出参无逐日故不伪造 byDay);全部读 usageSummary.scoreboard.trends(卡2 已按统计范围裁剪,client 只渲染不重拉),范围激活时区头带「范围内: …」徽章;近 14 天为固定窗口(范围落在窗口外时对应日柱为空,caption 写明);整区/单块空态均灰显不炸task-muxhu1zv):质量趋势区下方新增驳回原因 Top3——host 对验收驳回文本做规则法关键词聚类(不上 embedding:驳回文本结构模板化;首命中归类,占比分母=驳回总数,未匹配进「其他」兜底桶;按驳回消息自身本地日落点随统计范围裁剪),每行 TopN 类目 + 占比 + 代表原文(行 title 悬浮,各截 80 字)+ 「建议沉淀为约定」结构化文本(形如「驳回 Top1『验收脚本未实跑』占 42%——建议在派发约定/Worker prompt 补一条:…」,一键复制按钮,沉淀动作人工);挂 usageSummary.scoreboard.rejectionClusters,老 host 缺字段整块不渲染,无驳回显空态。同一通道的「按表现荐模型」hint(卡5③):某模型在中小卡 worker 桶合并后 runs≥10 且一次通过率≥90% 且有效均值较其他每个合格模型严格低 >30% → 「架构健康」区亮黄条「模型 X 在中小卡表现最优(通过率 92% · 有效均值 0.8M,较其他合格模型低 35%),建议设为默认 workerModel」;无足够数据/无对比对象不亮get-tasks 顺带对近 50 张卡现算四信号(纯函数零存储:touches 声明热度 ≥8 次且占比 ≥40% / 带 touches 任务滞留中位数 >2 倍 / 任务执行时长 p90 >45min(claimedAt→resolvedAt 纯干活口径,不含排队)/ 同路径驳回 ≥2 次),命中才在仪表盘渲染提示条(⚠️/ℹ️ 两级,最多 3 条)——让运行数据主动提示"该优化架构了"(如某文件反复成为锁热点=该拆),信号只建议不裁判;运行时健康自检(task-muxhrkbg)复用同一 hint 通道——host 侧在 poolCycle 成功轮 / settle 结算 / 幽灵回收三处记内存心跳(state.poolHealth,不落盘):有可派卡+有空位却 >5min 无成功派发轮 → 亮「🔴 派发循环疑似冻结」,有在跑卡却 >30min 无任何结算 → 黄级「结算通道长时间无活动」,幽灵表项回收 >0 时留一条一次性 info 记录(90s 保鲜、读到即灭)——运行事故不再只靠 e2e 翻车与肉眼发现;质量异动告警(异常驱动审视②):usageSummary.scoreboard.trends 环比——近 7 天一次通过率较再前 7 天跌 >10 个百分点(两侧样本各 ≥5 防小样本误报)→ 黄条「质量异动:一次通过率本周 X%(上周 Y%),建议抽查近期验收」,超时率 / 驳回率突变各加一条同构规则(阈值常量置顶,恰好 10pp 不亮、10.1pp 亮)buildReport 顶部一页纸——完成 N 张 / 驳回 M 次 / Token 总量(约 X,附有效 Y)/ 异常事件计数(超时 + 幽灵回收,读现有字段与 healthHints)/ 一句话质量趋势;纯聚合现有字段、不新建状态,无数据时优雅空态(一句话「近 24 小时无活动记录」)task-muzikj1y):get-tasks 对每张卡现算 reviewHint={score,reasons[]}(纯函数 core.computeReviewHints,现算零落库)——四条硬信号恒计入:被驳回过(rejectCount>0 或 verification.verdict=rejected 或 messages 有 rejection 包)/ 上报过歧义(messages 有 arbitration 裁决包)/ touches 碰核心文件(dispatch.mjs|rpc.mjs|core.mjs)/ full 无 acceptance;两条软信号仅质量异动告警激活期间计入(联动加严):diff>300 行(deliverable.diff 的 git diff --stat 解析)/ 续跑≥2 次(runs 中 resume:true 计数)。已完成/归档的命中卡带「👁 建议过目」徽章(悬浮全部理由行),FilterBar 加 chip「待你过目」一键只看未阅命中卡;打开详情页即幂等落 reviewedAt(唯一新落库字段,mark-reviewed RPC 只写一次),已阅卡徽章消失、chip 不计;详情顶部新增「审视摘要区」(仅命中时显示)四问动线——①为什么在这(理由行)/ ②改了什么(deliverable.summary+diffStat,标「Worker 汇报」来源徽标)/ ③机器怎么验的(verification 结论+验收脚本+驳回/仲裁史,标「Verifier 实证」/「系统记录」徽标)/ ④怎么亲自确认(复用 verification.userTest 自测指南,缺省显示 tier=internal 提示);报告「批次摘要」段加一行「未过目 N 张」task-mv2131cz,用户指令「这个清理可以做到看板上」):DSH 宿主无会话删除 API(归档=执行门禁不删数据),看板是唯一知道「哪些会话账已结清」的组件——清理只能长在看板上。仪表盘新增「存储清理」区:「预览可清理会话」按钮 → 展示可删会话数 + 预估释放空间 + 按卡分组明细 + 跳过项与理由(只读不删;体积估算优先读宿主 SessionPersistenceSnapshot.sizeBytes,快照缺省时回退目录遍历);「清理」按钮二次确认后真删(删除不可恢复,token 账早已记入卡片、删除不影响任何统计),完成后报告「已释放 N / 跳过 M 及理由」lib/cleanup.mjs 纯函数):只删本板 runs[] 关联的会话 id,且 主闸 = 卡龄——所属卡 status=archived 且 archivedAt 距今 ≥ cleanupRetentionDays(板级设置项,默认 7 天、可配 1-90,回收与归档生命周期对齐);三底闸永留——① outcome 已落定(非 running)② 会话当前不活跃(不在 ctx.agents 活跃树 / 非本会话血统)③ 路径安全(id 白名单 + rm 前 isWithin 再验)——任一解析不确定即跳过并计入理由(宁漏勿错删)。continuable/usageRecorded 两道旧闸已撤:归档满保留天数即视为账本封存、续跑意愿过期(恢复待办时旧会话已被删走,既有「冷复活失败→回落新 spawn」路径承接,零新逻辑)~/.dsh/sessions///(fs.rm recursive)+ projcache 缓存 ~/.dsh/storages/session_projcache/sessions/.json;路径逃逸双闸防护:① 会话 id 白名单 [A-Za-z0-9_-](含 ../、/、` 一律拒)② rm 前再验目标绝对路径仍在 sessions/projcache 桶内(path.relative 判定)。**注册表索引残留**:~/.dsh/storages/session_projcache.json(宿主托管的 version/seq 结构)**不清理**——只是元数据索引,残留条目不占会话日志体积,宿主自会 GC;每次清理写 board.cleanupLog` 留痕(时间/操作者/删除数/释放字节/会话 id 清单,上限 50 条)note_search / note_manage)完全由主窗口 agent 自己决定lesson-candidate 消息(场景 / 错误做法 / 来源);② 主窗口裁决 Worker 歧义 → 一条 lesson-candidate 消息(场景 / 疑问 / 裁决结论)。同一事件按「同时间戳 / 同内容前缀」轻量判重只落一条,且不写 history 流转记录(不刷屏)push-lesson RPC followup 给主窗口 agent(提示语写明「请用你可用的笔记/记忆工具沉淀,或评估后忽略」),推送成功后按钮变「✅ 已推送」置灰contextNotes)true(与升级前行为一致)dsh-agent-board 与笔记类插件(如 dsh-notes-plugin)之间没有任何依赖、服务调用或文件直写——看板只发一条 followup 文本,怎么用由主窗口 agent 决定draft → pending → in-progress → verifying → resolved → archived
↓ ↑
blocked ←────── rejectdependsOn 声明依赖(DFS 环检测),依赖全部完成后才会被派发,串行链路自动编排full(执行+验证)/ work(只做不验)/ direct(不进池,主窗口直接处理),创建时按规则自动分类、可手动覆盖acceptance 字段写验收脚本命令,Worker 必须实际运行、Verifier 必须独立复跑git checkout / git restore / git reset --hard / git clean 等——会冲掉并行 Worker 与你自己的未提交在途编辑);只改自己写的文件、别人改了别的文件与你无关,确实需要干净基线时走歧义上报(board_report kind=escalate)由主窗口裁决;提交只允许精确路径 `git add`(本卡 touches 声明的文件,或逐一列出明确改过的文件路径),禁止 git add -A / git add . / git add 目录——并行 Worker 共享暂存区,宽泛 add 会把别卡在途编辑卷进 commit(实证 n-mv6xntg1p6i5:三起暂存吞并)write 写入全量(单次超长输出会撞模型输出上限、上下文耗尽零产出),先 write 落主体骨架、再用 edit 追加续块(每块 ≤4KB)逐块落地git status 看工作区有无未提交半成品,能续作就续作,别盲目从零」——重发/重派场景的旧产物先盘点再决定touches 声明本任务要改的文件/glob(如 ["src/**", "README.md"]);持有文件锁的任务(in-progress/verifying)与候选 touches 重叠就跳过本轮(卡片显示 🔒 等文件释放,详情页列出在等谁),锁随工作态:状态流转到已完成(resolved)即放锁,cancelled/归档同样不再持锁(归档回归纯收纳动作、不再是释放点)——锁只护「正在写」的阶段,「验收后-提交前」的窗口期由主窗口「回执到即提交」纪律 + 史诗 post-hook 承接,不用长持锁把整批串行化。避免并行 Worker 改同一批文件互踩;手动「派发」遇到冲突会列出冲突任务,确认后才以 force 越权派发board_report(kind: "progress",question 写一行进展摘要 ≤200 字符)上报——进行中的卡片显示「📈 最近进展 · 相对时间」(覆盖式只留最新一条),详情页消息流保留全部 progress 条目history 流转记录,避免刷屏archive-task 对「无活跃 run 的 in-progress」——典型如被 parentKick 推进后子任务已全部归档的史诗——直接放行,有活跃 run 的仍拒);归档子任务仍计入史诗进度并在详情留档可见——进度分子口径 settled = resolved | cancelled | archived、分母也含归档,归档一张子卡不会再让史诗进度从 0/10 退化成 0/9(进度只增不减),全归档的父卡也照常显示徽章;详情子任务清单不排归档行(灰化 + 行尾「已归档」徽章 + 沉底排序,点击仍可进子卡看留档)create-task 拒绝不完整 sessionId(防裸短 id 建出幻影板)get-tasks 响应附 tasksHash;客户端轮询带上轮 hash 作 ifHash,host 比对一致时返回 {unchanged:true} 轻量响应(不含 tasks 全量——轮询载荷从 1.34MB 级降到 KB 级,usage/healthHints/池状态等轻量聚合照常返回),前端保留 state.tasks 不动并跳过重渲染;hash 不一致 / 不带 ifHash / includeArchived 一律全量返回(老客户端零回归)isRoot 判定改读持久 parentSession(根会话=无父)——休眠根会话(有板有卡但无活 agent)也算 root,入口不再分钟级消失;子代理会话(parentSession 指向父)恒不显示入口。客户端防抖仍保留兜底:已确认 root 的会话需连续 3 次(≈9s)false 才收起抽屉(会话生命周期内「曾确认 true」粘滞),看板不再在生成状态切换时突然消失;从未确认 root 的子代理会话仍即时隐藏入口,保护语义不变settled = resolved | cancelled | archived,total 同口径含归档;有在跑子任务时附「▸ 在跑:标题」行);子卡标题下显示「↳ 父任务标题」;依赖未满足的待办卡底部灰字「⛓ 等待「依赖标题」」(childStats 由 host 现算,缺字段一律不渲染)epic.hooks = { pre: { enabled, prompt, state, runId }, post: 同构 }——前置让子任务具备开跑条件(串行闸门:未完成前该史诗的子任务一张都不派),后置把这批活收口(全部子任务了结后跑一遍,完成后史诗才转验证中);prompt 只给薄框架契约,具体动作由 hook agent 自行决策,吃不准就走歧义上报(失败即转阻塞等人裁决:重试/跳过/放弃,不自动重跑)。hook run 记在 epic.runs[](role hook-pre/hook-post),卡片带相位徽章(⏳ 前置准备中 / 🧪 收尾中 / ⚠️ hook 失败待裁决,无 hooks 的老卡零渲染),详情页 hooks 区可编辑 enabled+prompt、查看 state/耗时并跳转 run 会话、失败一键跳裁决区;hooks 仅主窗口可设(工具与 RPC 双通道门禁),commit/push 不入任何默认形态delete-task RPC(卡片 hover 垃圾桶按钮 / 详情页「删除」按钮,均先 confirm('删除不可恢复,确认删除「标题」?'))+ batch-op op='delete'(多选模式底部「批量删除」,同样 confirm)。状态门禁:草稿/待办/阻塞可删;进行中/验证中拒绝并提示先用 terminate-agent 终止(避免在跑的 run 变孤儿);已完成/取消引导改用归档(archive-task,留档可检索);有未归档子任务时拒删(防 parentId 悬空破坏父任务自动流转);已归档任务幂等返回 ok。是真删(从 tasks 数组移除),因此不产生 `batch-undo` 撤销快照(批量条对 delete 不显示「↩️ 撤销」),删除操作在 host 端 console.error 留一行日志便于溯源pipeline: direct,不进池派发),再挂若干 10~30 分钟的子任务(task_create 传 parentId=父卡 id,有先后顺序用 dependsOn 串联),子任务全部完成后父卡自动流转(checkParentAuto)——task_create 工具描述与 Team 模式提示词都写了这条契约;容器卡结构性不派发:凡有子任务的卡(epic)永不进派发候选(与 pipeline 字段无关,不再只靠 direct 口头约定——手滑建 full 档 epic 也不会被派出占 worker 槽),子任务全了结转 verifying 后派 Verifier 验收不受影响task_create / create-task 发现描述超 500 字符、或标题/描述命中「全量 / 整体 / 系统级 / 全面 / 重构 / 所有模块 / 整个」等史诗特征词时,返回体附带一行 suggestSplit 建议文案(只提示,不阻断创建与派发;未命中则不出现该字段,老调用方无感)create-task/task_create 响应不再附 suggestSplit 软提示;机制不禁(显式传 parentId 建子卡、史诗自动收口与 hooks 状态机照常工作,明确要拆时不受阻);老看板文件没有该字段 → 读路径自动补 true(与升级前行为一致)。工具描述里的粒度契约是静态工具定义(随 request header 快照),不在开关范围set-board-config 对 workerModel/verifierModel 的非空值校验当前网关可用清单(list-models 同款枚举)——手写非法 id(如把熔断通知里的显示名抄成 id)直接拒写并返回合法清单前 8 个,验收 spawn 不再 UNKNOWN_MODEL 秒死;空串=清除放行;宿主无 llm 服务时降级跳过校验不炸。配套熔断通知分态:UNKNOWN_MODEL 类失败报「配置非法(不在可用清单)」,与「验收连续失败」区分——mistake 归 mistake,quality 归 quality路径:L起-L止 — 一句用途」);文件内容本体不进 prompt,由子代理用 read 工具按行号范围按需自取(执行时盘面更新鲜;旧形态「host 读盘取正文注入」既受单文件 8KB/总包 40KB 截断,又随 runtime 快照每轮刷新重发——自治 run 实测 6×48.8K 字符≈白烧 75–100K token);UI 侧调研门禁——full/work 且声明了 touches 却未附调研的卡片亮「⚠️ 无调研」徽章,详情页「调研注入」区列 files 清单 + notes 字数(无则明示)contextFiles 条目写法「path:L2350-L2420 / path:L2350」+ 可选「 — 一句用途」(em dash 两侧空格分隔;缺省只给路径行号)——锚点只认尾部 :L(兼容 Windows 盘符),清单里原样带上行号供子代理直接按行段 read;锚点写错(:L0 / :L5-L2)自动剥掉,不误导子代理去读空段read(path, offset, limit) 取需要的那段,清单里给出的行号就是起点;task_preview_context / preview-context 返回的也是这份瘦身清单(不是文件正文)task_create/create-task 响应附 warning 字段——①描述为空「Worker 只能凭标题猜需求」②full/work + touches 非空而未附调研上下文 ③touches 含整树 glob 建议精确到文件级(可多条合并);GUI 表单内黄色展示不关窗。epic 发布(publish)时自动轻量预检全部子任务注入情况,缺材料则 pushSysNote 汇总提醒主窗口(全有不打扰);派发时清单组装失败落任务「最近失败」行,不再静默。另存 lintWarnings[] 起草 lint(四规则:touches 整树 glob「粒度过粗,几乎锁整仓」/ 相对路径双仓库歧义「建议加仓库前缀」/ full 无验收「建议带验收命令」/ 标题缺动词或描述空),落卡透出、详情页 ⚠️ 行展示,不阻断创建