dsh-plugin-teamflow 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,57 @@
2
2
 
3
3
  > 本插件首次公开发布版本为 **v0.1.0**;发布前的内部迭代(v0.3~v0.13)记录于 `AGENTS.md` §5,对外统一归到 v0.1.0。
4
4
 
5
+ ## [0.1.8] - 未发布
6
+
7
+ ### 新增
8
+ - **全局团队工作台(`sidebar.panellist` + `main`)**:工作台从「某个会话里的一个 tab」升级为应用级主面板——左侧边栏多一个图标(inline SVG,跟随选中态),点开中央主区即整块换成 TeamFlow:左栏是**产品线**列表(`$DSH_HOME/teamflow/<key>` 扫描,含 run 计数/活跃数/最近需求与验收结论/磁盘路径),右栏是该产品线的 **run 列表 + backlog 分组**(需求/任务/缺陷,含按角色 token)。**不依附会话**:面板在 root scope(无 `useSession`/`useProjection`),所以数据面新增按**产品线 key** 寻址的 remote 方法(`products` / `productView` / `productRunDetail` / `productStageDetail` / `productItemDetail`),与会话内工作台同源装配(同一批 journal 与 state.json,非新数据模型)
9
+ - **run 详情进右侧栏 tab**:注册 `teamflow-run` tab 类型(认领 `dsh-resource://teamflow/run/**`),在会话内点 run 即在该会话右侧栏打开完整详情(阶段表 + 官方口径 token + 阶段详情/尝试聚合/验证证据/产出/日志)。地址由 host 生成(client 不拼地址)——与产物预览同一条原则。**右侧栏的会话内容只在对话视图存在**(宿主 `RightbarRoot` 门控),所以全局面板里点 run 默认在**面板内联**显示;要并排看就点「对话右栏」——它会切回对话再打开右栏(seat 在切换后才 bind,故带小步重试);任何一步不可用都降级面板内联并给出**可见提示**(不静默失败)
10
+ - **状态徽章可点筛选(多选)**:分组行上的每个状态计数徽章升级为可点 `filterChip`(选中态实心 + 状态色边框),**多选 toggle**——真实问法是「还没结束的有哪些」(进行中 / 待验收 / 需人工的并集),单选会逼人来回点。**筛选优先于折叠**:选中含终态时自动展开(否则点了「已验收 19」却看不到卡片),清掉筛选回到默认折叠;行尾显示「筛选中 N 项 · 显示 x/y × 清除」,无筛选时不出现(不加噪音)。作用域:backlog **每组独立**,run 标签加同款一行(7 个状态),run 的折叠(最近 8 条 + 进行中置顶)**只作用于筛选结果**;切产品线清空筛选与展开态(面板不重挂载,显式 reset)。**纯客户端过滤**,host 数据面与 slice 上限一律不动(数据不丢,清除即见全部)
11
+ - **右栏入口改为「去发起会话」**:右侧栏是**会话级**的(`RightbarRoot` 只渲染当前会话),旧「切回对话」跳回的仍是用户来时的会话、与 run 无关。改为 `goOwnerSessionAndOpen(target)`:host 侧 `runBrief`/`snapshotOf`/`itemDetail.runInfo` **新增 `ownerSession` 透出**(journal 早有该字段)+ 产物地址的会话段改用 run 的发起会话,client 先 `sessions.open(ownerSession)`、等 `sessions.list.getSnapshot().current` 真的切过去**且**对话 seat 挂载 bind 后再 `openResource`(带就绪判据的小步重试);会话已清理时只提示不跳转,老数据无该字段退回旧行为
12
+
13
+ ### 修复
14
+ - **交付判定信号分级(`judgeDeliverable`)**:dev/qa 产出判定由「全文拒绝词命中即否决」改为三级——① 客观形态(非空 + 阶段长度下限)→ ② **真交付信号**(`DELIVERY_EVIDENCE_PATTERN`:prompt 强制的 `[Verification evidence]` 块 = 命令 + 退出码 + 断言计数)→ ③ 措辞兜底(`REFUSAL_PATTERN` 仅在**无证据块**时才否决)。**修「如实汇报环境限制被判未交付」**:子代理自述「7 个用例与 26 项校验无法执行,属环境性失败」因命中「无法执行」被判 `insubstantial` → 提测门禁停线 → 人工 resume + 重复补跑(已完成任务被重做)。修后命中拒绝词**但有证据块** → 判交付 + 记 warn 留痕(措辞只作诊断,不再是门禁)。删 `hasSubstance`
15
+ - **熔断改用「新增」口径(`freshTokensOf`)**:熔断预算 = `input + cacheWrite + output`(**排除 `cacheRead`**),阈值 `FRESH_TOKEN_BUDGET`(默认 200k)。旧口径把缓存重放计入——实测某 dev 任务 `totalTokens` 1,885,583 ≥ 60k 触发熔断,**真实新增仅 55,439** ⇒ **任何任务失败一次都立刻熔断、`RETRY_LIMIT` 连一次重试都走不到**。修后重试优先于熔断恢复。**汇报/展示口径 `totalTokensOf`(官方 billed)不变**,两套口径不得合并(已在 AGENTS §4/§5 锚定)
16
+ - **收口提交面排除自有日志**:`sanity.tfAddArgs()` = `git add -A -- . ':(exclude)logs/teamflow'`(magic pathspec 强制排除,**不依赖目标仓库有没有配 `.gitignore`**;`-- .` 同时把提交面收敛到工作区),两处提交点(收口提交 + `preAction=commit`)统一走它,**禁止再出现裸 `add -A`**;新增 `util.mergeGitignore()` + `pipeline.ensureLogGitignore()` **提交前幂等补写**工作区 `.gitignore`(覆盖判定含更宽规则 `logs/`、`logs/**`;`changed=false` 时不落盘,不留无谓 diff;写失败只 warn——pathspec 仍兜底)。**修一次收口提交 227 文件里 208 个(92%)是自有日志**(真交付仅 19)——子代理 git 纪律无问题(交付报告写「logs/ remain untracked」当时属实),是 host 在最后一刻扫进去的
17
+ - **prompt 日志布局收口**:`TOKEN_HYGIENE` 新增 `[Log layout · policy]`——**每用途一个文件**:套件输出 → `regression-<phase>.log` 且**重跑时追加**带 `--- <timestamp> <task> ---` 表头(禁止 `-run2`/`-nopipe`/`-shim` 同名变体)、一次性校验脚本 → `scripts/`、命令载荷 → 合并进 `captures.json`、探针/草稿 → `probe/`;dev/qa/qaFix 三处 `[Log discipline]` 指向该布局。**实测消灭 51 份重复套件输出(占 `.log` 78%,267.5 KB)**,同一沙箱绕行被各 agent 重新发明 6+ 次的问题一并收敛
18
+ - **日志布局路径作用域**:上条的四条路径写成**未限定相对昵称**(`scripts/`、`probe/`)→ 模型按「最像项目约定」解析成**项目根** → 在仓库根建了 `scripts/`(5) 与 `probe/`(1) 且被收口提交扫进去(32 文件里占 6 个)。修复:四条路径全部改写为**完整限定** `logs/teamflow/<runId>/...`,段首加粗「never create scripts/ or probe/ at the project root」,三处 `[Log discipline]` 各自重申;L1 契约新增 `LOG-LAYOUT-SCOPED`(断言完整路径 + 项目根禁令,`exclude` 未限定旧写法防回退)。**教训:给模型指路径必须给完整限定路径,不能给通用昵称**
19
+ - **右栏 run tab 卡在「读取中」**:正文读地址必须用宿主绑定的 **`useTabInfo`**(slot 声明 `hooks: { tabInfo }` 会被渲染器改名为 `use<Name>`),prop 名写成 `tabInfo` 取不到 `tab.navigation.address || tab.contentId`
20
+ - **二次 unwrap / 空信封静默失败**:去掉阶段详情 / 条目详情 / 面板内联 run 详情的**二次 unwrap**(首层已解包,二次解包取到 `undefined` → 表现为「读取中」或空白);`unwrap` 对 `ok=true` 但无 `value` 的**空信封显式报错**,不再静默返回 `undefined`
21
+ - **React #310(hook 归属错位)**:`FoldableText` 被当普通函数调用(`FoldableText(...)`)而非作为组件渲染 → hook 挂到父组件,叠加条件渲染导致**每次渲染 hook 数变化**。改为组件用法
22
+ - **工作台顶出外层页面滚动条**:面板改用宿主 `.viewArea` **高度契约**布局(不再用 `100vh` 一类硬高度),消除「页面级滚动条 + 面板内滚动条」双层滚动;并恢复看板**列内滚动**(限高 340)+ 列头/分组标题 sticky
23
+ - **同值点击产品线卡在「读取产品线数据中…」**:重复点击同一产品线不再无响应——`viewTick` 重载 + 选中态提示
24
+ - **窄列卡片内容溢出**:等宽数字行(token/耗时)在窄列顶破面板 → 收敛为可换行/截断
25
+ - **详情浮层单一事实源**:修「run 详情与 backlog 详情同时存在、要关两次」——详情状态收敛为单一来源
26
+ - **分栏改用 `grid auto-fit`**:修 `flex-wrap` 多行 flex 行高随内容 → 列被撑高、`overflow` 永不触发导致「展开后无法滚动」
27
+
28
+ ### 改进
29
+ - **客户端展示层收拢**:主题 token / 状态词表 / 格式化(token 官方口径、时间、耗时、折叠文本)从 1286 行的 `client/index.tsx` 抽到 `client/shared.tsx`,会话内工作台与全局面板共用一份——两处展示语言不会再各自漂移
30
+ - **宿主 slot 契约对齐**:`dsh.client.inject` 补 3 个 slot owner 包(`ui-layout` / `ui-sidebar` / `ui-sidebar-right`,注册进谁的 slot 就列谁)+ 对应 optional peer 声明,避免加载顺序不确定导致的「slot 不存在」
31
+ - **全局面板第三版布局 —— 主区标签页 + 详情覆盖式浮层**:第二版把 **rail + run 栏 + backlog 栏 + 详情栏**四栏并排并叠了 `grid auto-fit` 自适应,在 1100–1400px 窗口**必然超载**(卡片被压到 ~200px、run 行折成多行、详情栏还和列表抢宽度),并触发连环故障(`flex-wrap` 行高随内容 → 列被撑高、`overflow` 永不触发 → 展开后无法滚动)。第三版**做减法**:① 主区改为**标签页**(🚀 流水线 run N | 📋 Backlog M),一次只显示一个列表——宽度全给它、只剩一个滚动区;② 详情改为**覆盖式浮层**(绝对定位 + 独立滚动,与会话内两个抽屉同款),不再参与横向宽度分配;③ 删掉 panel 级 grid/flex 两栏自适应(backlog 卡片自身的 `auto-fill` 网格保留)。折叠 / 进行中置顶 / 终态收起 / 需人工不折等已确认行为全部保留。**教训:并排面板数量必须由可用宽度决定,不是由信息架构决定**
32
+
33
+ ### 已知待办
34
+ - 全局面板目前**只读**(未提供 backlog 流转写路径);run tab 未注册 `sidebar.right.pane.tab.title` seat(chip 标题取自类型定义);两处渲染组件仍分叉(`shared.tsx` 只统一了词表/格式化)。见 `docs/TODO.md`
35
+ - 熔断阈值(`FRESH_TOKEN_BUDGET`,默认 200k)仍是常量,未做成 service Config;护栏**复读检测**仍读已弃用的事件读取器(提醒通道与挂死判据已迁官方投影)。见 `docs/TODO.md`
36
+
37
+ ## [0.1.7] - 2026-09-11
38
+
39
+ ### 新增
40
+ - **工作台产物一键预览**:任务卡详情里的「任务夹」现在按真实存在的产物列按钮(PRD / DESIGN / TECHNICAL / QA-REPORT / ACCEPTANCE / meta),点一下即在 DSH **右侧栏**打开预览(Markdown 由官方文档预览器接管)。地址由 host 用官方 `fileAddressFor` 生成(`dsh-resource://file/session/<id>/<相对路径>`)——客户端不拼地址、也不引宿主包进 client bundle;只列真实存在的文件(不出死按钮);右侧栏服务缺失时静默降级
41
+ - **产物交付(`present`)**:prd/tech/qa/acceptance 四个阶段被要求把任务夹产物交给官方 `present` 工具 → 用户在该会话得到「交付文件卡」(预览 / 默认程序打开 / 文件管理器定位)。诚实标注为 `[policy]` 增强项:文件仍是唯一事实源,缺文件依旧是硬失败;卡片渲染在**该子代理会话**的轮次尾部(主会话不显示)
42
+ - **机械阶段推理强度降档(省 token)**:DeepSeek 路由默认 `reasoningEffort: high`,而推理 token **计入 output** 且**推理内容每个带推理回合原样回传**(同时抬高后续 input)。现对两处机械阶段下发 `low`——patch 档的「单点确认」与 `scaffold`(脚手架落地);判据类阶段(PRD/设计/技术方案/QA/验收)保持宿主默认 `high`,**重试自动回升 `high`**(质量优先)。安全前提:先经 `llm.resolveModelInfo()` 探测该路由的 `reasoning.efforts`,只有声明支持才下发——宿主对不支持的值会 `UNSUPPORTED_REASONING_EFFORT` 硬失败且不降级;探测结果按 provider/model 缓存。阶段日志记录实际下发的档位
43
+
44
+ ### 修复
45
+ - **token 计量改走官方 Session 投影(宿主弃用同步事件读取器)**:dsh 0.1.5-rc.2 起 `Session.eventAt()` / `snapshotEvents()` / `ownEvents()` 标记为 deprecated(存量可留、新调用禁止,宿主方向是不再把完整事件序列常驻内存)。计量来源改为**官方投影优先**——`ctx.sessionProjections.stateOf(session,'tokenUsage')` 取四桶(与宿主 token-meter 同一份 fold,重试替换语义更准)+ `'sessionStats'.steps` 取调用数,**零历史扫描**;投影缺失/无数据/读取异常时静默回退原事件扫描(最小 profile 与存量宿主不受影响,不虚报 0,不中断流水线)。`sessionProjections` 走可选 `ctx.inject`,不进 `static inject`——服务缺失时插件照常加载
46
+ - **护栏适配官方通道(提醒 + 挂死检测)**:轻提醒从手写 `session.append('user/message')` + step/end flush 时序状态机,改为官方 `run.localAgent.inject()`(宿主在协议安全边界整批认领,旧注释声称的「会插进 tool_calls→tool_result 触发 400」不成立);挂死检测从「多源取最长事件视图」长度启发式改为官方 **`subagentTiming` 投影**的 `active.through`(已提交事件时间,不受视图失明影响——上次 QA 误判 stalled 的根因)。长工具静默执行仍由 agent 活动守卫豁免;投影不可用时回退旧启发式。中止语义未变
47
+
48
+ ### 改进
49
+ - **声明宿主兼容窗口**:`package.json` 新增 `engines.dsh: ">=0.1.5-rc.2 <0.2.0"` 与 `dsh.manifestVersion: 1`(dsh 0.1.5 起支持的公共 manifest 字段;当前宿主不校验,属作者声明);README「版本锚定」段同步到 v0.1.5-rc.2,并记录本次兼容核对结论与两个待跟进项
50
+ - **清理死注入**:`static inject` 长期硬注入 `tokenMeter` 却全仓从未使用 → 从 static inject / setRuntime / runtime 三处移除(假依赖会拖累插件的加载条件)
51
+ - **工作区 key 文档纠偏**:`workspaceScopeOf` 的「优先用 DSH workspace UUID」分支**当前不可达**(宿主 `resolveByPath` 是异步、我们同步调用),实际生效的是路径派生 `slugPath(cwd)`;注释与 AGENTS.md 改为事实描述,真修(改异步 + 存储 key 迁移)列入 `docs/TODO.md` 待 v0.1.8
52
+
53
+ ### 已知待办
54
+ - **护栏复读检测仍读已弃用的事件读取器**(提醒通道与挂死检测已改官方;复读需要流式文本内容):官方替代是订阅 `'session/event'` post-commit 投递,需先定等价判据,见 `docs/TODO.md`(当前行为不变,存量调用被宿主明确允许)
55
+
5
56
  ## [0.1.6] - 2026-09-07
6
57
 
7
58
  ### 新增
package/README.en.md CHANGED
@@ -42,19 +42,20 @@ requirement → PRD (based on existing patterns / product memory, archived to pr
42
42
 
43
43
  ## Core Features
44
44
 
45
- - **Anti-fake-delivery**: ① Substantive validation — outputs containing rejection phrases ("I cannot complete", etc.) or below the per-stage length floor are treated as undelivered and routed to retry / human intervention; ② Token circuit breaker — a single stage accumulating 60k budget stops retries; ③ Context-exhaustion failures are not retried (retrying the same prompt likely reproduces); ④ Product-level concurrency lock — only one active pipeline per product at a time, preventing requirement state from stepping on itself; ⑤ Full stage outputs are retained (memory + disk) for the detail drawer and checkpoint resume.
45
+ - **Anti-fake-delivery**: ① Delivery is judged by **tiered signals** — objective shape (non-empty + per-stage length floor) → real-delivery signal (a `[Verification evidence]` block) → **wording only as a fallback** (rejection phrases like "I cannot complete" count as undelivered **only when there is no evidence block**; a matched phrase with an evidence block is logged as a diagnostic and never vetoes — honestly reporting environment limits is no longer a false failure); ② Token circuit breaker — new tokens accumulated per call (`input+cacheWrite+output`, cache hits excluded) beyond 200k stop retries and require human intervention; ③ Context-exhaustion failures are not retried (retrying the same prompt likely reproduces); ④ Product-level concurrency lock — only one active pipeline per product at a time, preventing requirement state from stepping on itself; ⑤ Full stage outputs are retained (memory + disk) for the detail drawer and checkpoint resume.
46
46
  - **Auto completion report to main thread**: when a pipeline ends (success / failure / cancel / interrupt), it automatically delivers a summary (status / stage stats / total token / backlog / next-step guidance) to the initiating session's Agent — wakes on idle (followup), injects next-step context when busy (inject), using the same mechanism as DSH's background-task notifications (tool-jobs mode, but independently implemented and not dependent on the web-disabled tool-jobs). The user need not watch the panel; the model relays the result or continues per guidance (claim defects / transition / resume from checkpoint).
47
47
  - **Resume from checkpoint**: every stage checkpoint persists to `$DSH_HOME/teamflow/runs/<runId>.json` (LangGraph checkpointer semantics); after a process crash / restart it is auto-marked `interrupted`, and `teamflow_resume` / the panel's "↻ resume from checkpoint" continues from the first unfinished stage (skipping completed stages, reusing full stage outputs).
48
48
  - **Backlog persistence (workspace-isolated since v0.1.0)** under `$DSH_HOME/teamflow/<workspace>/backlog/` as `requirements.json` / `tasks.json` / `bugs.json`, surviving restarts; backlog is isolated per "workspace (project)" — one workspace is one product line, and different workspaces each see their own Team Workspace.
49
49
  - **Single-task model **: one requirement = one rotating task card (no longer split by role); the task card records `devAssign` / `qaAssign` / acceptor, with state rotation: todo → developing → to-test → testing → to-accept → accepted | bounced | needs-human; the delivered frontend page also shows each role's **real token usage** spent on that task.
50
50
  - **Artifact consolidation **: pipeline docs (PRD / design / architecture / tech spec / QA / memory / history) all consolidate into `docs/teamflow/`, command run logs into `logs/teamflow/<runId>/`, so the host `docs/<role>/` and project root are no longer polluted by TeamFlow; the host-side run log likewise lands in `<workspace>/logs/teamflow/<runId>.log`.
51
+ - **Delivery surface vs. noise**: only **code + the `docs/teamflow/` task folder** go into the closing commit (one commit per run); `logs/teamflow/` is the plugin's own run log (including sub-agent scratch verification scripts) and is **not a deliverable** — the host appends it to the workspace `.gitignore` (idempotent, visible in that same commit) and force-excludes it via a git pathspec, so **your project needs no pre-configured .gitignore**. If a repo already committed that noise, run `git rm -r --cached logs/teamflow` there to untrack it (local files are kept).
51
52
  - **State machine + event log**: requirement (initiated → in-progress → to-accept → accepted), task (todo → developing → to-test → testing → to-accept → done | bounced | needs-human), defect (to-claim → in-progress → fixed-to-verify → closed).
52
53
  - **Bounce-back threshold**: 2 consecutive Agent failures in a single stage auto-retry; still failing → `needs-human`, requiring human intervention.
53
54
  - **Concurrency pool**: dev tasks run in parallel by `maxConcurrency` (default 3, max 8).
54
55
  - **QA defect registration**: the QA report outputs in a fixed table → auto-parsed into bugs entering the backlog.
55
56
  - **Token metering (official semantics)**: each stage records `usage` = **cache-miss input / cache-hit input / write-cache / output + call count** (accumulated per event by the sub-agent session) + **cache hit rate** (cacheRead / (input + cacheRead)). Workspace cards / task cards / completion reports all display in this basis — model-agnostic and consistent with the official bill.
56
- - **lite mode **: lightweight micro-features — `teamflow_start(lite:true)` skips the standalone tech-spec doc stage (PRD is the contract) and goes straight **PRD → dev → QA → acceptance**; with `needDesign:true` it **keeps the UI/UX design stage**. Measured ~64% time / ~88% token savings vs the full 7-stage run.
57
- - **Token circuit breaker**: when a stage's official total consumption (input + cacheRead + cacheWrite + output accumulated) exceeds `STAGE_TOKEN_BUDGET` (default 60k), retries stop and human intervention is required.
57
+ - **lite mode**: lightweight micro-features — `teamflow_start(lite:true)` skips the standalone tech-spec doc stage (PRD is the contract) and goes straight **PRD → dev → QA → acceptance**; with `needDesign:true` it **keeps the UI/UX design stage**. The point is trimming the stage set to match requirement size instead of running a full waterfall on a micro-feature (the `patch` tier is smaller still: single-point confirmation + dev).
58
+ - **Token circuit breaker**: when the **new tokens** accumulated per call (`input + cacheWrite + output`, **cache hits excluded**) exceed `FRESH_TOKEN_BUDGET` (default 200k), retries stop and human intervention is required; reporting/display still uses the official billed basis (`totalTokensOf`). Cache hits are cheap replays — counting them here would mean "any single failure trips the breaker, making auto-retry dead code" (see `docs/devlog.md` entry 15).
58
59
  - **🏭 Team Workspace (Web tab)**: a session-header tab alongside chat / trace, containing:
59
60
  - Pipeline graph (stage swimlanes + node cards: status / duration / token / sub-agent session, 2s live refresh)
60
61
  - **Backlog drag-drop kanban** (requirement / task / defect three status swimlanes, cards dragged to transition, native HTML5 DnD zero-dep)
@@ -78,7 +79,7 @@ web profile host composition
78
79
  ├── teamflow-host (dsh-plugin-teamflow/host) Cordis service `teamflow`
79
80
  │ └── TeamflowService extends TypertRemoteService
80
81
  │ ├── ctx.typert.register(strict descriptors) ← 17 Remote methods
81
- │ ├── ctx.tools.register(teamflow_*) ← 11 model tools
82
+ │ ├── ctx.tools.register(teamflow_*) ← 12 model tools
82
83
  │ └── node:fs → $DSH_HOME/teamflow/...
83
84
  └── teamflow-client (dsh-plugin-teamflow/client, auto-scanned) ← package.json declares dsh.client,
84
85
  └── ctx.remote.$mount(TEAMFLOW_REMOTE_CONTRIBUTION) no patch line needed, clientModules auto-registers
@@ -124,7 +125,7 @@ dsh plugin --profile web add file:./plugins/dsh-plugin-teamflow
124
125
  ```
125
126
 
126
127
  After install, **restart** `dsh --profile web` for the host `teamflow-host` to take effect:
127
- - The model side gains 11 `teamflow_*` tools: `start / triage / status / backlog / claim / update / assign / cancel / resume / pause / resume_session`;
128
+ - The model side gains 12 `teamflow_*` tools: `start / triage / status / backlog / claim / update / assign / cancel / resume / pause / resume_session / merge`;
128
129
  - The browser session header shows the "🏭 Team Workspace" tab;
129
130
  - Backlog is written to `$DSH_HOME/teamflow/<product>/backlog/*.json`.
130
131
 
package/README.md CHANGED
@@ -42,26 +42,29 @@ TeamFlow 团队研发流水线 —— DeepSeek Harness 可分发插件(`dsh pl
42
42
 
43
43
  ## 核心特性
44
44
 
45
- - **防假交付**:① 实质校验——拒绝措辞("我无法完成"等)或低于阶段长度下限的输出视为未交付,走重试/需人工;② token 熔断——单阶段累计 60k 预算,超限停止重试;③ 上下文耗尽类失败不重试(重试同一 prompt 大概率复现);④ 产品级并发锁——同一产品同时只允许一条活跃流水线,防需求状态互踩;⑤ 阶段产物全文保留(内存 + 磁盘,供详情抽屉与断点续跑读取)。
45
+ - **防假交付**:① 交付判定按**信号分级**——客观形态(非空 + 阶段长度下限)→ 真交付信号(`[Verification evidence]` 证据块)→ **措辞兜底**(仅在**无证据块**时才把"我无法完成"等拒绝措辞视为未交付;命中措辞但已带证据块只记诊断、不否决——如实汇报环境限制不再被误杀);② token 熔断——单次调用累计**新增**消耗(`input+cacheWrite+output`,不含缓存命中)超 200k 停止重试转人工;③ 上下文耗尽类失败不重试(重试同一 prompt 大概率复现);④ 产品级并发锁——同一产品同时只允许一条活跃流水线,防需求状态互踩;⑤ 阶段产物全文保留(内存 + 磁盘,供详情抽屉与断点续跑读取)。
46
46
  - **完成汇总自动汇报主线程**:流水线结束(成功/失败/取消/中断)后自动把汇总(状态/阶段统计/token 总计/backlog/后续操作指引)投递给发起会话的 Agent——空闲时唤醒(followup),忙碌时注入下一步上下文(inject),与 DSH 后台任务通知同款机制(tool-jobs 模式,但独立实现,不依赖 web 面被禁用的 tool-jobs)。用户无需盯面板,模型会转述结果或按指引继续(认领缺陷/流转/断点重跑)。
47
47
  - **断点续跑**:每阶段 checkpoint 落盘 `$DSH_HOME/teamflow/runs/<runId>.json`(LangGraph checkpointer 语义);进程崩溃/重启后自动标记 `interrupted`,可用 `teamflow_resume` / 面板「↻ 从断点重跑」从第一个未完成阶段继续(跳过已完成阶段,复用阶段产物全文)。
48
48
  - **backlog 持久化(v0.1.0 起按工作区隔离)到 `$DSH_HOME/teamflow/<workspace>/backlog/`**
49
49
  `requirements.json` / `tasks.json` / `bugs.json`,跨重启不丢;backlog 按「工作区(项目)」隔离——一个工作区就是一条项目线,不同工作区各看各的团队工作台。
50
50
  - **单任务模型**:一个需求 = 一张轮转任务卡(不再按角色拆任务),任务卡记录 `devAssign` / `qaAssign` / 验收人,状态轮转:待办→开发中→待测试→测试中→待验收→已验收|打回|需人工;交付前端页面同时展示每个角色花在该任务上的**真实 token usage**。
51
51
  - **产物收口**:流水线文档(PRD/设计/架构/技术方案/QA/记忆/历史)全部收口到 `docs/teamflow/`,命令运行日志收口到 `logs/teamflow/<runId>/`,宿主 `docs/<职责>/` 与项目根不再被 TeamFlow 污染;host 端 run 日志同样落 `<工作区>/logs/teamflow/<runId>.log`。
52
+ - **交付面与噪音隔离**:只有**代码 + `docs/teamflow/` 任务夹**进收口提交(一个 run 一个 commit);`logs/teamflow/` 是插件自己的运行日志(含子代理的临时验证脚本),**不属于交付物**——host 提交时会把它写进工作区 `.gitignore`(幂等追加,随本次提交可见),并用 git pathspec 强制排除,因此**目标项目不需要预先配置 .gitignore**。若你的仓库已经提交过这批日志,可在目标仓库执行 `git rm -r --cached logs/teamflow` 移出(本地文件保留)。
52
53
  - **状态机 + 事件日志**:需求(立项→进行中→待验收→已验收)、任务(待办→开发中→待测试→测试中→待验收→完成|打回|需人工)、缺陷(待认领→处理中→已修复待验→已关闭)。
53
54
  - **打回阈值**:单阶段连续 2 次 Agent 失败自动重试,仍失败 → `needs-human`,需人工介入。
54
55
  - **并发池**:开发任务按 `maxConcurrency`(默认 3,最大 8)并行执行。
55
56
  - **QA 缺陷登记**:QA 报告按固定表格输出 → 自动解析成 Bug 进入 backlog。
56
57
  - **token 计量(官方口径)**:每阶段记录 `usage` = **输入(缓存未命中)/输入(缓存命中)/写缓存/输出 + 调用数**(由子代理会话逐事件累计)+ **缓存命中率**(cacheRead/(input+cacheRead))。工作台卡片/任务卡/完成汇报均按此口径展示,模型无关、与官方账单一致。
57
- - **lite 模式**:微功能轻量——`teamflow_start(lite:true)` 跳过独立技术方案文档阶段(PRD 即契约),直接 **PRD → 开发 → QA → 验收**;配套 `needDesign:true` 时**保留 UI/UX 设计阶段**。实测较完整 7 段省 ~64% 时间、~88% token。
58
- - **token 熔断**:单阶段官方总消耗(input+cacheRead+cacheWrite+output 累计)超 `STAGE_TOKEN_BUDGET`(默认 60k)时停止重试、需人工介入。
59
- - **🏭 团队工作台(Web tab)**:与 chat / 轨迹并列的会话头部 tab,含:
60
- - 流水线图形工作流(阶段泳道 + 节点卡片:状态/耗时/token/子代理会话,2s 实时刷新)
61
- - **Backlog 拖拽看板**(需求/任务/缺陷三组状态泳道,卡片拖拽流转,原生 HTML5 DnD 零依赖)
62
- - 成本中心(每阶段 token + 总计 + 运行时长)
63
- - 人工介入中心(needs-human 项聚合 + 一键终态)
64
- - 历史 run 切换 + 产品切换
58
+ - **lite 模式**:微功能轻量——`teamflow_start(lite:true)` 跳过独立技术方案文档阶段(PRD 即契约),直接 **PRD → 开发 → QA → 验收**;配套 `needDesign:true` 时**保留 UI/UX 设计阶段**。用「按需求规模裁剪阶段集」换流程重量,避免一个微功能套完整瀑布(`patch` 档更小:单点确认 + 开发)。
59
+ - **token 熔断**:单次调用累计**新增**消耗(`input+cacheWrite+output`,**不含缓存命中**)超 `FRESH_TOKEN_BUDGET`(默认 200k)时停止重试、需人工介入;汇报/展示仍按官方 billed 口径(`totalTokensOf`)。缓存命中是廉价重放,把它计入熔断会让「任何任务失败一次就熔断、自动重试形同虚设」——见 `docs/devlog.md` 补 15。
60
+ - **🏭 团队工作台(双入口)**:
61
+ - **会话内 tab**:与 chat / 轨迹并列的会话头部 tab,含:
62
+ - 流水线图形工作流(阶段泳道 + 节点卡片:状态/耗时/token/子代理会话,2s 实时刷新)
63
+ - **Backlog 拖拽看板**(需求/任务/缺陷三组状态泳道,卡片拖拽流转,原生 HTML5 DnD 零依赖)
64
+ - 成本中心(每阶段 token + 总计 + 运行时长)
65
+ - 人工介入中心(needs-human 项聚合 + 一键终态)
66
+ - 历史 run 切换 + 产品切换 + 「⇥ 右栏打开 run 详情」
67
+ - **全局面板**(v0.1.8):侧边栏图标 → 中央主区整块切换为**产品线视角**——左栏产品线列表(`$DSH_HOME/teamflow/<key>`,含 run 计数/活跃数/最近需求与结论),右栏该产品线的 run 列表 + backlog 分组(不依附会话,跨会话可用)。点 run 在**面板内联**看详情(阶段/尝试/验证证据/产出/日志);要并排看产物就点 run 行的「对话右栏」= 切回对话并在右侧栏打开(**右侧栏的会话内容宿主只在对话视图渲染**,这是宿主设计,不是面板缺陷;任何一步不可用都会降级为面板内联并给出可见提示)
65
68
 
66
69
  ## AGENTS.md 最小侵入原则(重要)
67
70
 
@@ -78,12 +81,14 @@ AGENTS.md 会被 harness 无条件注入每个会话,是**团队资产**。Tea
78
81
  web profile 宿主组合
79
82
  ├── teamflow-host (dsh-plugin-teamflow/host) Cordis service `teamflow`
80
83
  │ └── TeamflowService extends TypertRemoteService
81
- │ ├── ctx.typert.register(strict descriptors) ← 17 个 Remote 方法
82
- │ ├── ctx.tools.register(teamflow_*) ← 11 个模型工具
84
+ │ ├── ctx.typert.register(strict descriptors) ← 22 个 Remote 方法
85
+ │ ├── ctx.tools.register(teamflow_*) ← 12 个模型工具
83
86
  │ └── node:fs → $DSH_HOME/teamflow/...
84
87
  └── teamflow-client (dsh-plugin-teamflow/client,自动扫描) ← package.json 声明 dsh.client,
85
88
  └── ctx.remote.$mount(TEAMFLOW_REMOTE_CONTRIBUTION) 无需 patch 行,clientModules 自动注册
86
- └── conversation.view tab「🏭 团队工作台」
89
+ ├── conversation.view tab「🏭 团队工作台」(会话内)
90
+ ├── sidebar.panellist + main/teamflow(全局产品线面板)
91
+ └── sidebarRightTabs「teamflow-run」(右栏 run 详情 tab)
87
92
  ```
88
93
 
89
94
  **为什么不用 @Remote 装饰器**:宿主插件以纯 JS 分发,避免装饰器语法/TS 编译要求;
@@ -106,8 +111,12 @@ dsh-plugin-teamflow/
106
111
  descriptors.ts # Remote 描述符(纯数据,host/client 共用)
107
112
  store.ts # 持久化层:原子写/备份/损坏自愈 + journal 序列化/加载(可独立测试)
108
113
  host/index.ts # TeamflowService(TS;构建为 lib/host.mjs 供宿主加载)
109
- client/index.tsx # 团队工作台(TSX;构建为 lib/client.js)
114
+ host/core/products.ts # 产品线装配(全局面板数据面:清单/摘要/地址)
115
+ client/index.tsx # 会话内团队工作台 + 全部 slot 注册(TSX;构建为 lib/client.js)
116
+ client/panel.tsx # 全局面板(sidebar.panellist + main)+ 右栏 run 详情 tab
117
+ client/shared.tsx # 共享展示层(主题 token / 状态词表 / 格式化)
110
118
  test/smoke.js # 无依赖 smoke 测试(描述符/模块结构/安全加固)
119
+ test/product-scope.test.js # 产品线装配测试(地址/白名单/过滤/摘要/空态)
111
120
  test/journal.test.js # journal 行为测试(直跑 store.ts 源码)
112
121
  ```
113
122
 
@@ -119,15 +128,20 @@ dsh-plugin-teamflow/
119
128
  - Node.js ≥ 22.18;
120
129
  - 依赖宿主提供的 `@deepseek-ai/dsh-*` 与 `react`(peerDependencies,宿主注入,无需单独安装)。
121
130
 
122
- opencode### 版本锚定(dsh 宿主兼容性)
131
+ ### 版本锚定(dsh 宿主兼容性)
123
132
 
124
- 本插件开发与验证基于 **dsh git master(2026-09-04,≈ 0.1.3-alpha.1 发布线)**;npm 侧最新发布线 `0.1.2-rc.1`(next tag;`latest` 标签滞后为 0.0.1-rc.1,勿以 latest 判断)。`peerDependencies` 保持 `*`(宿主注入,宽松兼容)。
133
+ 本插件开发与验证基于 **dsh v0.1.5-rc.2(2026-09-10,tag `dsh-v0.1.5-rc.2`)**;npm 侧 `next`=0.1.5-rc.2、`latest`=0.1.5-rc.1(`latest` 常滞后于 `next`,勿以 latest 判断发布线)。`peerDependencies` 保持 `*`(宿主注入,宽松兼容),并在 `package.json` 声明兼容窗口 **`engines.dsh: ">=0.1.5-rc.2 <0.2.0"`** 与 **`dsh.manifestVersion: 1`**——当前 dsh 不读取/校验这两个字段(源码内仅有类型声明),属作者声明性元数据。
125
134
 
126
- 2026-09-04 兼容性核对(dsh 0.1.3-alpha.1):session 持久化 v2(write-lease/JSONL 快照/版本化导出)、attachment/file-upload 收口、Windows 子进程隐藏、workspace 全限定路径硬化——**全部兼容,插件无需调整**。
135
+ 2026-09-10 兼容性核对(dsh 0.1.5-rc.2):插件面板 Slot(原 `conversation` 根 slot → `main` 下的 `conversation` key)、会话格式 V3 + Session 生命周期(`SessionHandle`、异步 `agentLoop.create()`、会话锁)、`ctx.agent` 移除与 Inbox 类型化、SDK/Headless/ACP 默认工具调整、subprocess handle 去除 pid——**插件全部兼容**(未使用被改动的接口;`conversation.view` / `conversation.input.right` 声明未变,slot 树无删除)。其中一项需要跟进:
136
+
137
+ - **Session 同步事件读取器已弃用**(`session.eventAt()` / `snapshotEvents()` / `ownEvents()`,宿主 2026-09-09 起「存量可留、新调用禁止」,方向是不再把完整事件序列常驻内存):**token 计量已改为官方 Session 投影优先**(`ctx.sessionProjections.stateOf(session,'tokenUsage')` 取四桶 + `'sessionStats'.steps` 取调用数),事件扫描降级为无投影宿主的回退;**护栏的提醒通道已改官方 `Agent.inject()`、挂死判据已改用官方 `subagentTiming` 投影的 `active.through`**(长工具静默仍由 agent 活动守卫豁免),只剩**复读检测**仍在读事件(需要流式文本内容,官方替代=订阅 `'session/event'` post-commit 投递,需先定等价判据,见 `docs/TODO.md`)。
138
+
139
+ 2026-09-04 核对(dsh 0.1.3-alpha.1):session 持久化 v2(write-lease/JSONL 快照/版本化导出)、attachment/file-upload 收口、Windows 子进程隐藏、workspace 全限定路径硬化——全部兼容,插件无需调整。
127
140
 
128
141
  插件侧契约约束(dsh 升级后若行为异常先核对本段;锚定版本变更会在此更新):
129
- - 插件注入的 session 事件(`tool-workflow/agent-start`、`user/message` 带 `source.kind='plugin'`)均在 released 词表内;**未来新增自定义事件类型须带 `ignorable: true`**,已知类型载荷不加 released 词表外键;
130
- - `@deepseek-ai/dsh-client-modules` 自 0.1.2-rc.1 起替代 `@deepseek-ai/dsh-client-runtime`(后者已从 monorepo 移除)。
142
+ - 插件注入的 session 事件(`tool-workflow/agent-start`、`user/message` 带 `source.kind='plugin'`)均在宿主 `known-event-types` 词表内;**未来新增自定义事件类型须带 `ignorable: true`**,已知类型载荷不加词表外键;
143
+ - `@deepseek-ai/dsh-client-modules` 自 0.1.2-rc.1 起替代 `@deepseek-ai/dsh-client-runtime`(后者已从 monorepo 移除);
144
+ - 计量读的是**宿主投影 key**(`tokenUsage` / `sessionStats`)而非插件自有格式:宿主若改 key 或 state 版本,此段与 `host/core/metering.ts` 同步更新。
131
145
 
132
146
  ## 安装(对使用者)
133
147
 
@@ -140,8 +154,8 @@ dsh plugin --profile web add file:./plugins/dsh-plugin-teamflow
140
154
  ```
141
155
 
142
156
  安装后**重启** `dsh --profile web`,宿主行 `teamflow-host` 生效:
143
- - 模型侧出现 11 个 `teamflow_*` 工具:`start / triage / status / backlog / claim / update / assign / cancel / resume / pause / resume_session`;
144
- - 浏览器侧会话头部出现「🏭 团队工作台」tab;
157
+ - 模型侧出现 12 个 `teamflow_*` 工具:`start / triage / status / backlog / claim / update / assign / cancel / resume / pause / resume_session / merge`;
158
+ - 浏览器侧:会话头部「🏭 团队工作台」tab(会话内)+ **左侧边栏「团队工作台」图标**(全局面板,产品线视角);
145
159
  - backlog 写入 `$DSH_HOME/teamflow/<product>/backlog/*.json`。
146
160
 
147
161
  > 注意:`@deepseek-ai/*` 为宿主私有包,运行需 DeepSeek Harness(dsh)宿主环境;本包不发布也无法独立运行。
@@ -150,7 +164,7 @@ dsh plugin --profile web add file:./plugins/dsh-plugin-teamflow
150
164
 
151
165
  1. **选团队**:会话输入框旁点「🏭」按钮,选择团队(或选「无团队」= 不走流水线,直接对话);
152
166
  2. **发需求**:直接说需求,模型会自动调用 `teamflow_start`(自动分诊模式:patch / lite / tech / medium / full)——也可以用「直接跑 medium 模式做这个」等指定档位;
153
- 3. **看进展**:会话头部切到「🏭 团队工作台」tab——流水线图实时刷新(每阶段 token / 耗时 / 子代理会话),Backlog 看板可拖拽流转、点卡片看详情;
167
+ 3. **看进展**:会话头部切到「🏭 团队工作台」tab——流水线图实时刷新(每阶段 token / 耗时 / 子代理会话),Backlog 看板可拖拽流转、点卡片看详情;点「⇥ 右栏打开」把该 run 详情放到右侧栏(与任务夹产物并排)。想看**跨会话/全局**的情况,点左侧边栏「团队工作台」图标(产品线视角:产品线 → run 列表 + backlog);
154
168
  4. **收结果**:流水线完成后自动向当前会话汇报(状态 / 阶段统计 / token / 后续指引);中断/失败的运行可「↻ 从断点重跑」。
155
169
 
156
170
  > 使用规则提醒:`teamflow_start` 调用后**主线程不要自行改代码或跑验证**——实现、QA、汇报由流水线各阶段子代理完成(避免与流水线抢活)。