dsh-plugin-teamflow 0.1.8 → 0.2.0
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 +252 -159
- package/README.en.md +63 -57
- package/README.md +51 -74
- package/lib/client.js +1123 -291
- package/lib/descriptors.mjs +14 -1
- package/lib/host.mjs +4893 -696
- package/lib/store.mjs +77 -6
- package/package.json +134 -134
package/README.en.md
CHANGED
|
@@ -20,48 +20,41 @@ requirement → PRD (based on existing patterns / product memory, archived to pr
|
|
|
20
20
|
|
|
21
21
|
## Screenshots
|
|
22
22
|
|
|
23
|
-
1.
|
|
23
|
+
1. Global panel — the 🏭 Team Workspace icon in the left sidebar (cross-session, product-line view: product list + run list + Backlog tab + overlay detail pane)
|
|
24
24
|
|
|
25
|
-

|
|
26
26
|
|
|
27
|
-
2.
|
|
27
|
+
2. Pipeline view — stage serpentine lanes + node cards (status / duration / tokens / subagent session)
|
|
28
28
|
|
|
29
|
-

|
|
30
30
|
|
|
31
31
|
3. Stage detail drawer — full stage artifacts + token breakdown + "🎬 jump to subagent session"
|
|
32
32
|
|
|
33
|
-

|
|
33
|
+

|
|
34
34
|
|
|
35
|
-
4.
|
|
35
|
+
4. Backlog board — draggable lanes for requirements / tasks / defects
|
|
36
36
|
|
|
37
|
-

|
|
38
38
|
|
|
39
|
-
5.
|
|
39
|
+
5. Board task detail — task-card drawer (requirement text / assignments / event timeline / subtasks / defects / tokens)
|
|
40
40
|
|
|
41
|
-

|
|
42
|
+
|
|
43
|
+
6. Team selector — 🏭 button + team dropdown
|
|
44
|
+
|
|
45
|
+

|
|
42
46
|
|
|
43
47
|
## Core Features
|
|
44
48
|
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
-
|
|
52
|
-
- **
|
|
53
|
-
|
|
54
|
-
- **Concurrency pool**: dev tasks run in parallel by `maxConcurrency` (default 3, max 8).
|
|
55
|
-
- **QA defect registration**: the QA report outputs in a fixed table → auto-parsed into bugs entering the backlog.
|
|
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.
|
|
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).
|
|
59
|
-
- **🏭 Team Workspace (Web tab)**: a session-header tab alongside chat / trace, containing:
|
|
60
|
-
- Pipeline graph (stage swimlanes + node cards: status / duration / token / sub-agent session, 2s live refresh)
|
|
61
|
-
- **Backlog drag-drop kanban** (requirement / task / defect three status swimlanes, cards dragged to transition, native HTML5 DnD zero-dep)
|
|
62
|
-
- Cost center (per-stage token + total + runtime)
|
|
63
|
-
- Human-intervention center (needs-human items aggregated + one-click terminal state)
|
|
64
|
-
- History run switching + product switching
|
|
49
|
+
- **One-line requirement → accepted delivery**: requirement → PRD → technical design → parallel development → QA → acceptance is orchestrated end to end; every stage gets a task card, artifacts and a verdict. Small mechanical changes can use the `patch` / `lite` tiers to trim the stage set instead of running a full waterfall.
|
|
50
|
+
- **Multi-agent team + parallel development**: the requirement is split into parallelizable tasks from the architecture blueprint (3 concurrent by default, 8 max), with product / architecture / dev / QA each working in their own isolated context.
|
|
51
|
+
- **Anti-fake-delivery**: delivery is judged by evidence, not wording — a stage must provide a `[Verification evidence]` block (command + exit code + assertion count), QA runs its own adversarial probes, and acceptance only trusts an explicit verdict line (missing ⇒ the pipeline stops for a human).
|
|
52
|
+
- **QA bounce-back loop**: P0–P2 defects are sent back for a fix and re-verified (≤2 rounds), each defect carrying its own check command and pass criterion; exceeding the limit hands over to a human instead of pretending the run is "done".
|
|
53
|
+
- **Resume + completion report**: after a crash or restart the pipeline continues from the first unfinished stage (completed stages reuse their artifacts); when a run ends, a summary (status / stages / tokens / next steps) is delivered back to the originating session.
|
|
54
|
+
- **Your repository stays clean**: pipeline docs live in the `docs/teamflow/` task folder and the plugin's own run logs are archived out of your project when the run ends — the closing commit carries **code + the task folder only** (one commit per run, **no pre-configured `.gitignore` required**). If an older commit already swept in `logs/teamflow/`, untrack it in that repository with `git rm -r --cached logs/teamflow` (your local files stay).
|
|
55
|
+
- **🏭 Team workbench (two entry points)**: an in-session tab (pipeline graph, drag-and-drop kanban, cost centre, human-intervention centre) and an app-level panel (product-line view, usable across sessions); open any run to see its stages, tokens, verification evidence and artifacts. The UI is **bilingual (Chinese / English)** and follows the host language live; host replies, pipeline logs and pipeline artifacts follow it too (resolved once per run).
|
|
56
|
+
- **Token accounting you can audit**: every stage records its input (cache miss / hit), cache write, output and call count, plus the cache-hit rate, shown on the same basis in reports and in the workbench; mechanical stages automatically drop their reasoning effort and raise it again on retry.
|
|
57
|
+
|
|
65
58
|
|
|
66
59
|
## AGENTS.md minimal-invasion principle (important)
|
|
67
60
|
|
|
@@ -76,37 +69,37 @@ AGENTS.md is unconditionally injected into every session by the harness; it is *
|
|
|
76
69
|
|
|
77
70
|
```
|
|
78
71
|
web profile host composition
|
|
79
|
-
├── teamflow-host (
|
|
80
|
-
│
|
|
81
|
-
│
|
|
82
|
-
│
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
72
|
+
├── teamflow-host (host/) Cordis service `teamflow`
|
|
73
|
+
│ ├── ctx.typert.register(strict descriptors) ← Remote methods (`descriptors.ts` pure data, shared by host / client)
|
|
74
|
+
│ ├── ctx.tools.register(teamflow_*) ← model tools
|
|
75
|
+
│ └── node:fs → $DSH_HOME/teamflow/… ← backlog / journal / archived logs
|
|
76
|
+
└── teamflow-client (client/) ← `package.json` declares `dsh.client`; the host composition scans and registers it
|
|
77
|
+
├── conversation.view "🏭 Team Workspace" (in-session tab)
|
|
78
|
+
├── sidebar.panellist + main/teamflow (global product-line panel)
|
|
79
|
+
└── sidebarRightTabs "teamflow-run" (right-sidebar run detail)
|
|
87
80
|
```
|
|
88
81
|
|
|
89
|
-
|
|
82
|
+
Two hard constraints shaped this (details in `AGENTS.md` §3): **no `@Remote` decorator** (plugins ship as plain JS, so Remote uses `ctx.typert.register`'s strict descriptors); **it must be a host-level plugin** (a dynamic plugin's `fs` is sandboxed to the runtime root and cannot write `$DSH_HOME`).
|
|
83
|
+
|
|
90
84
|
|
|
91
|
-
**Why a host-level plugin (not a dynamic plugin)**: dynamic (in-session) plugins run in a restricted sandbox whose `fs` is hard-limited to the runtime root and cannot write to `$DSH_HOME` or the session workspace (observed `file access denied under workspace-write mode`). Only a formal plugin inside the host composition has real Node `fs`, able to land backlog in `$DSH_HOME`, and the client can register an independent tab.
|
|
92
85
|
|
|
93
86
|
## Directory structure
|
|
94
87
|
|
|
95
88
|
```
|
|
96
89
|
dsh-plugin-teamflow/
|
|
97
|
-
package.json
|
|
98
|
-
cordis.patch.yml
|
|
99
|
-
tsdown
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
store.ts
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
test/journal.test.js # journal behavior test (runs store.ts source directly)
|
|
90
|
+
package.json # dsh.bundle.patch + dsh.client declarations; exports point to lib/
|
|
91
|
+
cordis.patch.yml # plugin mount patch (insert block, entry uses the package root)
|
|
92
|
+
tsdown*.config.ts # builds: client → lib/client.js; host/store/descriptors → lib/*.mjs
|
|
93
|
+
host/ # TeamflowService + core/* (pipeline / backlog / runner / guard / triage / state…)
|
|
94
|
+
client/ # Web workbench (in-session tab + global panel + right-sidebar run detail)
|
|
95
|
+
store.ts # persistence layer (atomic write / backup / corruption self-heal + journal serialize)
|
|
96
|
+
descriptors.ts # Remote descriptors (pure data, shared by host / client)
|
|
97
|
+
test/ # dependency-free tests (node test/*.js, 14 suites)
|
|
98
|
+
docs/ # ADRs / dev log / benchmark corpus / release notes
|
|
107
99
|
```
|
|
108
100
|
|
|
109
|
-
|
|
101
|
+
The whole repo is TS/TSX: **the host must be built** (Node's type stripping does not apply to files under `node_modules`, and the host loads plugins from the profile's `node_modules`), so run `pnpm bundle` after changing source and sync the profile copy's `lib/`. Per-file details and the dev environment are in `CONTRIBUTING.md`.
|
|
102
|
+
|
|
110
103
|
|
|
111
104
|
## Requirements
|
|
112
105
|
|
|
@@ -114,6 +107,19 @@ dsh-plugin-teamflow/
|
|
|
114
107
|
- Node.js ≥ 22.18;
|
|
115
108
|
- Relies on host-provided `@deepseek-ai/dsh-*` and `react` (peerDependencies, injected by the host — no separate install needed).
|
|
116
109
|
|
|
110
|
+
### Version anchor (dsh host compatibility)
|
|
111
|
+
|
|
112
|
+
This plugin is developed and verified against **dsh v0.1.7-alpha.1** (session format v4). **That is also the floor for running a pipeline**: every message the plugin injects must carry a producer-owned `source.kind` (`plugin:dsh-plugin-teamflow`), while a v3 host validates `source.kind` against a **closed vocabulary** (`SOURCE_KINDS` contains no `plugin:*`) — the old form `{kind:'plugin', plugin:…}` is rejected outright by a v4 host, and the new form is equally illegal on a v3 host, so the two shapes are **mutually incompatible**; the plugin therefore no longer claims it can run back to v0.1.5-rc.2. The Remote descriptors still expose both `schema` and `create()` for hosts of either generation, see "typert descriptor contract" below. `package.json`'s `engines.dsh: ">=0.1.7-alpha.1 <0.2.0"` (**narrowed to this floor** — see the measurement below) and `dsh.manifestVersion: 1` are declarative author metadata (the host neither reads nor validates them).
|
|
113
|
+
|
|
114
|
+
⚠️ **How the prerelease-tuple rule interacts with this range** (verified 2026-09-23 with semver 7.7.4's `satisfies`): a prerelease only matches a range carrying a prerelease on the **same `[major,minor,patch]` tuple** — `>=0.1.7-alpha.1 <0.2.0` evaluates to **PASS for `0.1.7-alpha.1` / `0.1.7-alpha.2` / `0.1.7` / `0.1.8` / `0.1.9`** and **fail for `0.1.6-alpha.2` / `0.1.6` / `0.2.0-rc.1` / `0.2.0`** (exactly the v4 floor above). Note the old range `>=0.1.5-rc.2 <0.2.0` judged even the then-current `0.1.6-alpha.2` false under the same rule, so a field like this only states compatibility **against stable releases**; the host does not validate it anyway, and day to day you should go by **`next`**: `latest` lags behind it, so don't use `latest` to judge the release line.
|
|
115
|
+
|
|
116
|
+
**Breaking surface of v0.1.7-alpha.1 (this audit)**: the session event format moved to **v4** — before adopting an event the host validates every message's `source.kind` and **refuses the retired v3 plugin wrapper** (`{kind:'plugin', plugin:…}` → `format v4 message requires a producer-owned source kind`), requiring `kind:'plugin:<name>'` instead. All four injection sites (team context ×2 / completion report / guard reminder) still wrote the old wrapper, so a fresh run failed at the write step (the journal never even landed). They now emit `plugin:dsh-plugin-teamflow`. Every other surface re-checked (typert strict descriptors still require `create()`, `subagents.start`/`SubagentRun`, the `tokenUsage` four buckets + `sessionStats.steps`, `agent.inject/followup/steer`, the `settings.locale` read-only port, `remote.$mount`, `sessions.openSubagent`, `sidebarRight.openResource`) showed **no breakage**.
|
|
117
|
+
|
|
118
|
+
**Breaking surface of v0.1.6-alpha.2 (previous audit)**: the typert strict codec changed from `{ mode, typeSymbol, schema }` to `{ mode, typeSymbol, create: () => Schema }` (lazy materialisation — `materializeSchema` does `record.value ??= record.create()`); `validateCodec` **throws at registration** for a strict codec missing `create()` — `"strict codec has no create() factory"`. Combined with dsh-app-boot's policy (a required plugin failing to activate fails the whole profile with `startup failed`), the symptom is **"dsh won't start"** (`web boot: N entries did not activate`). A full diff of the other surfaces (client-modules / subagent / agent runtime / manifest / the tools llm projection) found no further breakage for this plugin, and the three UI slot packages have zero changes in `src/index.ts` → slot names are safe.
|
|
119
|
+
|
|
120
|
+
If behaviour looks wrong after a dsh upgrade, check two things first: ① the session events this plugin injects (`tool-workflow/agent-start`, `user/message` with `source.kind='plugin:dsh-plugin-teamflow'`) must sit inside the host's event vocabulary — **a v4 host only accepts producer-owned source kinds (the v3 `plugin` wrapper is retired)**, and a v3 host's closed vocabulary does not accept `plugin:*` either (hence the v4 floor); `tool-workflow/agent-start` carries no message/source slot and is outside that check. **New custom event types must carry `ignorable: true`**, and known types must not add keys outside it; ② metering reads the host **projection keys** (`tokenUsage` / `sessionStats`), so if the host renames them or bumps their state version, `host/core/metering.ts` has to be updated in step. Compatibility checks and open follow-ups are recorded in `CHANGELOG.md` (0.1.6–0.1.9) and `docs/TODO.md` (for example, repeat detection still reads the deprecated event readers).
|
|
121
|
+
|
|
122
|
+
|
|
117
123
|
## Install (for users)
|
|
118
124
|
|
|
119
125
|
```bash
|
|
@@ -126,7 +132,7 @@ dsh plugin --profile web add file:./plugins/dsh-plugin-teamflow
|
|
|
126
132
|
|
|
127
133
|
After install, **restart** `dsh --profile web` for the host `teamflow-host` to take effect:
|
|
128
134
|
- The model side gains 12 `teamflow_*` tools: `start / triage / status / backlog / claim / update / assign / cancel / resume / pause / resume_session / merge`;
|
|
129
|
-
- The browser session header shows the "🏭 Team Workspace" tab;
|
|
135
|
+
- The browser session header shows the "🏭 Team Workspace" tab (in-session) **and the "Team Workspace" icon in the left sidebar** (the global panel: product-line view, cross-session);
|
|
130
136
|
- Backlog is written to `$DSH_HOME/teamflow/<product>/backlog/*.json`.
|
|
131
137
|
|
|
132
138
|
> Note: `@deepseek-ai/*` are host-private packages; running requires the DeepSeek Harness (dsh) host environment; this package is neither published standalone nor runnable alone.
|
|
@@ -135,7 +141,7 @@ After install, **restart** `dsh --profile web` for the host `teamflow-host` to t
|
|
|
135
141
|
|
|
136
142
|
1. **Pick a team**: click the 🏭 button next to the input box and choose a team (or "no team" = chat directly, no pipeline);
|
|
137
143
|
2. **Say the requirement**: just describe it — the model calls `teamflow_start` automatically (auto-triage: patch / lite / tech / medium / full); or force a mode, e.g. "run this in medium mode";
|
|
138
|
-
3. **Watch progress**: switch to the 🏭 Team Workspace tab in the session header — the pipeline graph live-refreshes (per-stage token / duration / sub-agent session), and the backlog kanban supports drag transitions and card detail drawers;
|
|
144
|
+
3. **Watch progress**: switch to the 🏭 Team Workspace tab in the session header — the pipeline graph live-refreshes (per-stage token / duration / sub-agent session), and the backlog kanban supports drag transitions and card detail drawers; for a **cross-session / global** view, click the "Team Workspace" icon in the left sidebar (product-line perspective: product lines → runs + backlog), and hit "⏹ Stop" to cancel a live run (two-step confirm);
|
|
139
145
|
4. **Get the result**: the pipeline reports back to the session automatically when done (status / stage stats / token / next steps); interrupted/failed runs can "↻ resume from checkpoint".
|
|
140
146
|
|
|
141
147
|
> Note: after `teamflow_start`, the **main thread should not modify code or run verifications itself** — implementation, QA, and reporting are done by pipeline sub-agents (avoid fighting the pipeline over the workspace).
|
|
@@ -155,13 +161,13 @@ Optional cleanup (NOT done automatically; run as needed):
|
|
|
155
161
|
## Development & verification
|
|
156
162
|
|
|
157
163
|
```bash
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
pnpm test # smoke (descriptors / structure / security) + journal (resume behavior)
|
|
165
|
+
pnpm run typecheck # tsc --noEmit type check (needs the local dsh profile for @deepseek-ai/* types)
|
|
160
166
|
node --check lib/host.mjs lib/client.js lib/store.mjs lib/descriptors.mjs
|
|
161
|
-
|
|
167
|
+
pnpm run bundle # build client (tsdown → lib/client.js, registered via __ModuleLoader__.load)
|
|
162
168
|
```
|
|
163
169
|
|
|
164
|
-
**For plugin developers** (the local dev loop of THIS plugin): see [`AGENTS.md`](./AGENTS.md) and [`docs/adr/`](./docs/adr) in the repo — deployment sync (`node deploy.mjs` → restart `dsh --profile web`), the "running web loads the host from the profile deployment copy, building source alone does not take effect" caveat, design decision records (ADR-0001~
|
|
170
|
+
**For plugin developers** (the local dev loop of THIS plugin): see [`AGENTS.md`](./AGENTS.md) and [`docs/adr/`](./docs/adr) in the repo — deployment sync (`node deploy.mjs` → restart `dsh --profile web`), the "running web loads the host from the profile deployment copy, building source alone does not take effect" caveat, design decision records (ADR-0001~0009) and benchmarks (`docs/benchmarks/`). All repo source is TS/TSX and must be built first (`pnpm bundle`) to run (`strip-types` does not apply under `node_modules`).
|
|
165
171
|
|
|
166
172
|
Note: `lib/` is excluded by `.gitignore` but must ship with the package (`files` whitelist includes `lib/`; `exports["./client"]` points to `./lib/client.js`).
|
|
167
173
|
|
|
@@ -174,7 +180,7 @@ Note: `lib/` is excluded by `.gitignore` but must ship with the package (`files`
|
|
|
174
180
|
| `teamflow_backlog` / `teamflow.backlog(product)` | View backlog (+ persistence path) |
|
|
175
181
|
| `teamflow_claim` | Claim a task or defect |
|
|
176
182
|
| `teamflow_update` / `teamflow.backlogUpdate(kind, id, to, product, reason)` | Manually transition state (handle needs-human) |
|
|
177
|
-
| `teamflow_cancel` / `teamflow.cancel(runId)` | Cancel a run |
|
|
183
|
+
| `teamflow_cancel` / `teamflow.cancel(runId)` | Cancel a run (buttons in the workbench, the global panel's run row and run detail; two-step confirm; only effective while the run is live) |
|
|
178
184
|
| `teamflow_resume` / `teamflow.resume(runId, sessionId)` | Resume from checkpoint (rerun from first unfinished stage) |
|
|
179
185
|
| `teamflow_triage` | Requirement triage preview (start auto-triages by default; use only to pre-assess / force a mode) |
|
|
180
186
|
| `teamflow_assign` | Assign owner of a task / defect (separate from claim: claim only changes state) |
|
package/README.md
CHANGED
|
@@ -20,51 +20,41 @@ TeamFlow 团队研发流水线 —— DeepSeek Harness 可分发插件(`dsh pl
|
|
|
20
20
|
|
|
21
21
|
## 界面预览
|
|
22
22
|
|
|
23
|
-
1.
|
|
23
|
+
1. 全局面板——左侧边栏「🏭 团队工作台」图标(跨会话 / 产品线视角:产品线列表 + run 列表 + Backlog 标签页 + 覆盖式详情浮层)
|
|
24
24
|
|
|
25
|
-

|
|
26
26
|
|
|
27
|
-
2.
|
|
27
|
+
2. 流水线视图——阶段蛇形泳道 + 节点卡片(状态/耗时/token/子代理会话)
|
|
28
28
|
|
|
29
|
-

|
|
30
30
|
|
|
31
31
|
3. 阶段详情抽屉——阶段性产物全文 + token 明细 +「🎬 跳转子代理会话」
|
|
32
32
|
|
|
33
33
|

|
|
34
34
|
|
|
35
|
-
4.
|
|
35
|
+
4. Backlog 看板——需求/任务/缺陷拖拽泳道
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
5. 看板任务详情——任务卡抽屉(需求原文/分配/事件时间线/子卡/缺陷/token)
|
|
36
40
|
|
|
37
41
|

|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
6. 团队选择——🏭 按钮 + 团队下拉
|
|
40
44
|
|
|
41
45
|

|
|
42
46
|
|
|
43
47
|
## 核心特性
|
|
44
48
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
- **
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
- **打回阈值**:单阶段连续 2 次 Agent 失败自动重试,仍失败 → `needs-human`,需人工介入。
|
|
55
|
-
- **并发池**:开发任务按 `maxConcurrency`(默认 3,最大 8)并行执行。
|
|
56
|
-
- **QA 缺陷登记**:QA 报告按固定表格输出 → 自动解析成 Bug 进入 backlog。
|
|
57
|
-
- **token 计量(官方口径)**:每阶段记录 `usage` = **输入(缓存未命中)/输入(缓存命中)/写缓存/输出 + 调用数**(由子代理会话逐事件累计)+ **缓存命中率**(cacheRead/(input+cacheRead))。工作台卡片/任务卡/完成汇报均按此口径展示,模型无关、与官方账单一致。
|
|
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 行的「对话右栏」= 切回对话并在右侧栏打开(**右侧栏的会话内容宿主只在对话视图渲染**,这是宿主设计,不是面板缺陷;任何一步不可用都会降级为面板内联并给出可见提示)
|
|
49
|
+
- **一句话需求 → 可验收的交付**:从需求到 PRD / 技术方案 / 并行开发 / QA / 验收全链路自动编排,每个阶段有任务卡、有产物、有结论;机械小改动可用 `patch` / `lite` 档裁剪阶段集,不必为一行改动跑完整瀑布。
|
|
50
|
+
- **多 Agent 团队 + 并行开发**:按架构蓝图把需求拆成可并行任务(默认 3 路并发,上限 8),产品 / 架构 / 开发 / QA 各自独立上下文,互不污染。
|
|
51
|
+
- **防假交付**:交付看证据不看措辞——阶段必须给出「命令 + 退出码 + 断言数」的验证证据,QA 有独立对抗探针,验收只认显式结论行(缺失即停线转人工)。
|
|
52
|
+
- **QA 打回闭环**:P0–P2 缺陷自动打回修复 → 复验(≤2 轮),每条缺陷都带「检测命令 + 通过判据」;超限转人工,不会伪装成「已完成」。
|
|
53
|
+
- **断点续跑 + 完成汇报**:进程崩溃 / 重启后从第一个未完成阶段继续(已完成阶段复用产物);流水线结束时自动把汇总(状态 / 阶段 / token / 后续指引)投递回发起会话。
|
|
54
|
+
- **你的仓库保持干净**:流水线文档收口在 `docs/teamflow/` 任务夹,插件自己的运行日志在 run 结束时归档出项目,收口提交只带**代码 + 任务夹**(一个 run 一个 commit,**不需要你预先配置 `.gitignore`**)。若历史提交里已经混进过 `logs/teamflow/`,在目标仓库执行 `git rm -r --cached logs/teamflow` 移出即可(本地文件保留)。
|
|
55
|
+
- **🏭 团队工作台(Web 双入口)**:会话内 tab(流水线图 + 拖拽看板 + 成本中心 + 人工介入中心)与应用级主面板(产品线视角,跨会话可用);点开 run 看阶段、token、验证证据与产物。**界面中英双语**,跟随宿主语言实时切换;host 侧的回复、流水线日志与产物文档同样跟随语言(run 起跑时定一次,同一条 run 内一致)。
|
|
56
|
+
- **token 有账可查**:按官方口径记录每个阶段的输入(未命中 / 命中)/ 写缓存 / 输出与调用数,并给出缓存命中率,汇报与看板同口径;机械阶段自动降档推理强度,重试时回升。
|
|
57
|
+
|
|
68
58
|
|
|
69
59
|
## AGENTS.md 最小侵入原则(重要)
|
|
70
60
|
|
|
@@ -79,48 +69,37 @@ AGENTS.md 会被 harness 无条件注入每个会话,是**团队资产**。Tea
|
|
|
79
69
|
|
|
80
70
|
```
|
|
81
71
|
web profile 宿主组合
|
|
82
|
-
├── teamflow-host (
|
|
83
|
-
│
|
|
84
|
-
│
|
|
85
|
-
│
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
├── sidebar.panellist + main/teamflow(全局产品线面板)
|
|
91
|
-
└── sidebarRightTabs「teamflow-run」(右栏 run 详情 tab)
|
|
72
|
+
├── teamflow-host (host/) Cordis service `teamflow`
|
|
73
|
+
│ ├── ctx.typert.register(strict descriptors) ← Remote 方法(descriptors.ts 纯数据,host / client 共用)
|
|
74
|
+
│ ├── ctx.tools.register(teamflow_*) ← 模型工具
|
|
75
|
+
│ └── node:fs → $DSH_HOME/teamflow/… ← backlog / journal / 归档日志
|
|
76
|
+
└── teamflow-client (client/) ← package.json 声明 dsh.client,宿主组合自动扫描注册
|
|
77
|
+
├── conversation.view「🏭 团队工作台」(会话内 tab)
|
|
78
|
+
├── sidebar.panellist + main/teamflow(全局产品线面板)
|
|
79
|
+
└── sidebarRightTabs「teamflow-run」(右栏 run 详情)
|
|
92
80
|
```
|
|
93
81
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
保证 endpoint 与 wire 参数一致)。
|
|
82
|
+
两条硬约束决定了这个形态(详见 `AGENTS.md` §3):**不用 `@Remote` 装饰器**(插件以纯 JS 分发,Remote 走 `ctx.typert.register` 的严格描述符);**必须是宿主级插件**(动态插件的 `fs` 被沙箱限制在运行时根,写不了 `$DSH_HOME`)。
|
|
83
|
+
|
|
97
84
|
|
|
98
|
-
**为什么是宿主级插件(而不是动态插件)**:动态(会话内)插件宿主运行在受限沙箱,
|
|
99
|
-
其 `fs` 被硬限制在运行时根,无法写入 `$DSH_HOME` 或会话工作区(实测
|
|
100
|
-
`file access denied under workspace-write mode`)。只有宿主组合里的正式插件拥有真实
|
|
101
|
-
Node `fs`,能把 backlog 落到 `$DSH_HOME`,且 client 能注册独立 tab。
|
|
102
85
|
|
|
103
86
|
## 目录结构
|
|
104
87
|
|
|
105
88
|
```
|
|
106
89
|
dsh-plugin-teamflow/
|
|
107
|
-
package.json
|
|
108
|
-
cordis.patch.yml
|
|
109
|
-
tsdown
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
store.ts
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
client/panel.tsx # 全局面板(sidebar.panellist + main)+ 右栏 run 详情 tab
|
|
117
|
-
client/shared.tsx # 共享展示层(主题 token / 状态词表 / 格式化)
|
|
118
|
-
test/smoke.js # 无依赖 smoke 测试(描述符/模块结构/安全加固)
|
|
119
|
-
test/product-scope.test.js # 产品线装配测试(地址/白名单/过滤/摘要/空态)
|
|
120
|
-
test/journal.test.js # journal 行为测试(直跑 store.ts 源码)
|
|
90
|
+
package.json # dsh.bundle.patch + dsh.client 声明;exports 指向 lib/ 构建产物
|
|
91
|
+
cordis.patch.yml # 插件挂载 patch(insert 块,entry 用包根)
|
|
92
|
+
tsdown*.config.ts # 构建:client → lib/client.js;host/store/descriptors → lib/*.mjs
|
|
93
|
+
host/ # TeamflowService + core/*(流水线 / backlog / runner / guard / triage / state…)
|
|
94
|
+
client/ # Web 工作台(会话内 tab + 全局面板 + 右栏 run 详情)
|
|
95
|
+
store.ts # 持久化层(原子写 / 备份 / 损坏自愈 + journal 序列化)
|
|
96
|
+
descriptors.ts # Remote 描述符(纯数据,host / client 共用)
|
|
97
|
+
test/ # 无依赖测试(node test/*.js,14 套件)
|
|
98
|
+
docs/ # ADR / 开发日志 / 评测语料 / release notes
|
|
121
99
|
```
|
|
122
100
|
|
|
123
|
-
|
|
101
|
+
全仓 TS/TSX:**host 必须构建**(Node 的 type stripping 对 `node_modules` 下的文件不生效,而宿主从 profile 的 `node_modules` 加载插件),改源码后跑 `pnpm bundle` 重建并同步 profile 副本的 `lib/`。逐文件说明与开发环境见 `CONTRIBUTING.md`。
|
|
102
|
+
|
|
124
103
|
|
|
125
104
|
## 环境要求
|
|
126
105
|
|
|
@@ -130,18 +109,16 @@ dsh-plugin-teamflow/
|
|
|
130
109
|
|
|
131
110
|
### 版本锚定(dsh 宿主兼容性)
|
|
132
111
|
|
|
133
|
-
本插件开发与验证基于 **dsh v0.1.
|
|
112
|
+
本插件开发与验证基于 **dsh v0.1.7-alpha.1**(session 格式 v4)。**这也是「能跑流水线」的宿主下限**:插件注入的每条 message 必须带 producer-owned 的 `source.kind`(`plugin:dsh-plugin-teamflow`),而 v3 宿主把 `source.kind` 校验为**封闭词表**(`SOURCE_KINDS` 不含 `plugin:*`)——旧写法 `{kind:'plugin', plugin:…}` 在 v4 宿主当场被拒,新写法在 v3 宿主同样非法,两种形态**互不兼容**,故不再声称可回退到 v0.1.5-rc.2 运行。Remote 描述符仍同时提供 `schema` 与 `create()` 两个字段(供不同代际的宿主读取),见下「typert 描述符契约」。`package.json` 的 `engines.dsh: ">=0.1.7-alpha.1 <0.2.0"`(**已随本次下限收窄**,见下条实测)与 `dsh.manifestVersion: 1` 是作者声明性元数据(宿主不读取/校验)。
|
|
113
|
+
|
|
114
|
+
⚠️ **预发布 tuple 规则与本次区间的实测关系**(2026-09-23 用 semver 7.7.4 的 `satisfies` 实测):受「预发布版本只匹配同 `[major,minor,patch]` tuple 的区间」规则约束——`>=0.1.7-alpha.1 <0.2.0` 对 **`0.1.7-alpha.1` / `0.1.7-alpha.2` / `0.1.7` / `0.1.8` / `0.1.9` 判 PASS**,对 **`0.1.6-alpha.2` / `0.1.6` / `0.2.0-rc.1` / `0.2.0` 判 fail**(与上条 v4 下限恰好一致)。注意旧区间 `>=0.1.5-rc.2 <0.2.0` 在同一 rule 下连**当时正在用的 `0.1.6-alpha.2` 都判 false**,所以这类字段只表达**对正式版的兼容声明**;宿主既不校验它,日常应以 **`next`** 为准——`latest` 常滞后于 `next`,不要用 `latest` 判断发布线。
|
|
134
115
|
|
|
135
|
-
|
|
116
|
+
**v0.1.7-alpha.1 的 breaking 面(本次核对)**:session 事件格式升到 **v4**——宿主在事件被 Session 采纳前校验每条 message 的 `source.kind`,**拒绝 v3 退役的 plugin wrapper**(`{kind:'plugin', plugin:…}` → 抛 `format v4 message requires a producer-owned source kind`),要求 `kind:'plugin:<name>'`。插件原先四处注入(团队上下文 ×2 / 完成汇报 / 护栏提醒)写的都是旧 wrapper → 新 run 在写入阶段即失败(journal 都落不了盘)。现已全部改为 `plugin:dsh-plugin-teamflow`。全量核对其余面(typert 严格描述符仍要 `create()`、`subagents.start`/`SubagentRun`、`tokenUsage` 四桶 + `sessionStats.steps`、`agent.inject/followup/steer`、`settings.locale` 只读端口、`remote.$mount`、`sessions.openSubagent`、`sidebarRight.openResource`)**均无破坏**。
|
|
136
117
|
|
|
137
|
-
-
|
|
118
|
+
**v0.1.6-alpha.2 的 breaking 面(上次核对)**:typert strict codec 由 `{ mode, typeSymbol, schema }` 变为 `{ mode, typeSymbol, create: () => Schema }`(懒物化,`materializeSchema` 里 `record.value ??= record.create()`);`validateCodec` 对缺 `create()` 的 strict codec **注册即抛** `"strict codec has no create() factory"`。叠加 dsh-app-boot 的策略(required 插件 activate 失败 → 整个 profile `startup failed`),表现为**插件一挂就是「dsh 起不来」**(`web boot: N entries did not activate`)。全量 diff 其余面(client-modules / subagent / agent runtime / manifest / tools 的 llm 投影)对本插件无破坏,三个 UI slot 包的 `src/index.ts` 零变更 → slot 名安全。
|
|
138
119
|
|
|
139
|
-
|
|
120
|
+
升级 dsh 后若行为异常,先核对两处:① 插件注入的 session 事件(`tool-workflow/agent-start`、`user/message` + `source.kind='plugin:dsh-plugin-teamflow'`)必须落在宿主事件词表内——**v4 宿主只收 producer-owned 的 source kind(`plugin` 这个 v3 wrapper 已退役)**,而 v3 宿主的封闭词表也不收 `plugin:*`(因此下限是 v4 宿主);`tool-workflow/agent-start` 不带 message/source 槽位,不在该校验范围内。**新增自定义事件类型要带 `ignorable: true`**、已知类型不要加词表外的键;② 计量读的是**宿主投影 key**(`tokenUsage` / `sessionStats`),宿主改 key 或 state 版本时需同步 `host/core/metering.ts`。历次兼容核对结论与待跟进项见 `CHANGELOG.md`(0.1.6–0.1.9 段)与 `docs/TODO.md`(例如复读检测仍读已弃用的事件读取器)。
|
|
140
121
|
|
|
141
|
-
插件侧契约约束(dsh 升级后若行为异常先核对本段;锚定版本变更会在此更新):
|
|
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` 同步更新。
|
|
145
122
|
|
|
146
123
|
## 安装(对使用者)
|
|
147
124
|
|
|
@@ -184,13 +161,13 @@ dsh plugin --profile web remove dsh-plugin-teamflow
|
|
|
184
161
|
## 开发与验证
|
|
185
162
|
|
|
186
163
|
```bash
|
|
187
|
-
|
|
188
|
-
|
|
164
|
+
pnpm test # smoke(描述符/结构/安全)+ journal(断点续跑行为)
|
|
165
|
+
pnpm run typecheck # tsc --noEmit 类型检查(需本机 dsh profile 提供 @deepseek-ai/* 类型)
|
|
189
166
|
node --check lib/host.mjs lib/client.js lib/store.mjs lib/descriptors.mjs
|
|
190
|
-
|
|
167
|
+
pnpm run bundle # 构建 client(tsdown → lib/client.js,__ModuleLoader__.load 注册)
|
|
191
168
|
```
|
|
192
169
|
|
|
193
|
-
**插件开发者**(本插件的本地开发链路)见仓库内 [`AGENTS.md`](./AGENTS.md) 与 [`docs/adr/`](./docs/adr)——含部署同步(`node deploy.mjs` → 重启 `dsh --profile web`)、生效前提(运行中 web 从 profile 部署副本加载 host,只构建源码不生效)、设计决策记录(ADR-0001~
|
|
170
|
+
**插件开发者**(本插件的本地开发链路)见仓库内 [`AGENTS.md`](./AGENTS.md) 与 [`docs/adr/`](./docs/adr)——含部署同步(`node deploy.mjs` → 重启 `dsh --profile web`)、生效前提(运行中 web 从 profile 部署副本加载 host,只构建源码不生效)、设计决策记录(ADR-0001~0009)与基准对比(`docs/benchmarks/`)。本仓库其余源码均为 TS/TSX,需先 `pnpm bundle` 构建后再运行(`node_modules` 下 strip-types 不生效)。
|
|
194
171
|
|
|
195
172
|
注意:`lib/` 被 `.gitignore` 排除,但发布必须带上构建产物(`files` 白名单已含 `lib/`;`exports["./client"]` 指向 `./lib/client.js`)。
|
|
196
173
|
|
|
@@ -203,7 +180,7 @@ npm run bundle # 构建 client(tsdown → lib/client.js,__ModuleLoa
|
|
|
203
180
|
| `teamflow_backlog` / `teamflow.backlog(product)` | 查看 backlog(+ persistence 落盘路径) |
|
|
204
181
|
| `teamflow_claim` | 认领任务或缺陷 |
|
|
205
182
|
| `teamflow_update` / `teamflow.backlogUpdate(kind, id, to, product, reason)` | 人工流转状态(处理 needs-human) |
|
|
206
|
-
| `teamflow_cancel` / `teamflow.cancel(runId)` |
|
|
183
|
+
| `teamflow_cancel` / `teamflow.cancel(runId)` | 取消运行(工作台 / 全局面板 run 行 / run 详情三处按钮,两段式确认;仅对正在跑的 run 生效) |
|
|
207
184
|
| `teamflow_resume` / `teamflow.resume(runId, sessionId)` | 断点续跑(从第一个未完成阶段重跑) |
|
|
208
185
|
| `teamflow_triage` | 需求分诊预览(默认 start 自动分诊,仅在想预评估/强制 mode 时使用) |
|
|
209
186
|
| `teamflow_assign` | 指定任务/缺陷的负责人(与 claim 分离:claim 只改状态) |
|