@marsken/dsh-studio 0.1.10 → 0.1.11

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.
@@ -6,7 +6,7 @@
6
6
 
7
7
  | 项 | 值 |
8
8
  | --- | --- |
9
- | dsh-studio | `package.json` `version: 0.1.10` |
9
+ | dsh-studio | `package.json` `version: 0.1.11` |
10
10
  | DeepSeek Harness | `0.2.2-rc.1`(`dsh --version`) |
11
11
  | Node | `v24.22.2`(Linux 目标机);本机 Windows `v24.19.0` |
12
12
  | 目标系统 | Ubuntu 24.04,`dsh web` 监听 `18080`,nginx `:80` 反代并注入 `dsh-auth-*` cookie |
package/docs/publish.md CHANGED
@@ -127,6 +127,7 @@ token 只写进临时 npmrc(放在仓库外或 `tmp/` 且不提交),发完
127
127
  | --- | --- | --- |
128
128
  | `0.1.0` | 2026-11-13 | 首个公开版:看板 / 需求 / 用例回归 / 效能 / 设计评审四期 |
129
129
  | `0.1.1` | 2026-11-13 | 补三张 README 截图(npm 页可看图);默认值与文档去掉公司内网信息 |
130
+ | `0.1.11` | 2026-11-15 | 需求变更影响面(接口 + 面板)、可跑用例口径修正、成本口径文档 |
130
131
  | `0.1.10` | 2026-11-15 | shell/db 用例可跑、GitLab 核对结果常驻显示、事件带 truncated、角色归并 |
131
132
  | `0.1.9` | 2026-11-14 | 准出门禁提示「代码事实核对不通过」(只提醒,不拦) |
132
133
  | `0.1.8` | 2026-11-14 | 卡进「待评审」时自动核对代码事实,对不上就写进 history 并记 gate/blocked |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marsken/dsh-studio",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "description": "DSH Studio: role-based multi-agent workspace (product / architect / developer / QA) with a live work board, GitLab + Feishu connection settings, all configurable from the web GUI.",
6
6
  "main": "index.js",
@@ -11,7 +11,9 @@
11
11
  "scripts": {
12
12
  "test": "node --test tests/repo.test.mjs tests/store-boot.test.mjs tests/client-units.test.mjs tests/notify.test.mjs",
13
13
  "check": "node --check index.js && node --check client.src.js && node --test tests/repo.test.mjs tests/store-boot.test.mjs tests/client-units.test.mjs tests/notify.test.mjs",
14
- "smoke:store": "node scripts/smoke-store.mjs"
14
+ "smoke:store": "node scripts/smoke-store.mjs",
15
+ "mock:gitlab": "node tools/mock-gitlab.mjs",
16
+ "verify:gitlab": "node tools/verify-gitlab-facts.mjs"
15
17
  },
16
18
  "exports": {
17
19
  ".": "./index.js",
@@ -13,7 +13,9 @@ export function casesOfTasks(tasks, limit = 40) {
13
13
  key: `${task.id}:${item.id}`,
14
14
  title: String(item.title ?? '').slice(0, 160),
15
15
  result: String(item.result ?? 'pending'),
16
- http: item.http === true,
16
+ // 能自动跑的判断要和执行器一致:接口 / shell / 数据库任一都算。
17
+ http: item.http !== null && item.http !== undefined,
18
+ runnable: item.http != null || item.shell != null || item.db != null,
17
19
  })
18
20
  }
19
21
  }
@@ -26,7 +28,7 @@ export function impactSummary(tasks) {
26
28
  return {
27
29
  cards: (Array.isArray(tasks) ? tasks : []).length,
28
30
  cases: cases.length,
29
- runnable: cases.filter(item => item.http).length,
31
+ runnable: cases.filter(item => item.runnable === true).length,
30
32
  failing: cases.filter(item => item.result === 'fail').length,
31
33
  }
32
34
  }
@@ -7,6 +7,7 @@ import {
7
7
  sanitizeRequirementPool,
8
8
  text,
9
9
  } from '../domain.js'
10
+ import { casesOfTasks, impactSummary } from '../impact.js'
10
11
  import {
11
12
  ensureReqFolder,
12
13
  mutateReqDoc,
@@ -405,7 +406,25 @@ export async function handleRequirementRoute({ method, route, req, res, store, u
405
406
  host.sendJson(res, 200, { ok: true, requirement: result, state: host.publicState(store) })
406
407
  return true
407
408
  }
408
- if (method === 'POST' && route === '/requirement/pull') {
409
+ if (method === 'POST' && route === '/requirement/impact') {
410
+ // 需求一改,这条需求下面的卡和用例就要重看。这里只算、不改数据。
411
+ const body = await host.readJsonBody(req)
412
+ const id = String(body.id ?? '')
413
+ const snapshot = store.snapshot()
414
+ const requirement = (snapshot.requirements ?? []).find(item => item.id === id)
415
+ if (requirement === undefined) throw new Error(`no requirement ${id}`)
416
+ const tasks = (snapshot.tasks ?? []).filter(task => task.requirementId === id)
417
+ const summary = impactSummary(tasks)
418
+ const cases = casesOfTasks(tasks, 60)
419
+ host.sendJson(res, 200, {
420
+ ok: true,
421
+ summary,
422
+ cases,
423
+ cards: tasks.map(task => ({ id: task.id, code: task.code ?? '', title: task.title ?? '', status: task.status ?? '' })),
424
+ })
425
+ return true
426
+ }
427
+ if (method === 'POST' && route === '/requirement/pull') {
409
428
  const body = await host.readJsonBody(req)
410
429
  const result = await pullFeishuDoc(body.url ?? body.docUrl ?? '')
411
430
  host.sendJson(res, 200, { ok: true, ...result })