tianshu-mcp 0.4.0 → 0.5.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.
Files changed (54) hide show
  1. package/CHANGELOG.en.md +95 -1
  2. package/CHANGELOG.md +72 -1
  3. package/README.en.md +45 -7
  4. package/README.md +45 -7
  5. package/dist/agents/codex/fixplan.js +8 -1
  6. package/dist/agents/zcode/recovery.js +14 -2
  7. package/dist/config/schema.js +3 -1
  8. package/dist/index.js +5 -0
  9. package/dist/loop/fix-loop.js +54 -7
  10. package/dist/loop/repair-plan.js +2 -0
  11. package/dist/mcp/handlers.js +7 -5
  12. package/dist/mcp/tools.js +15 -0
  13. package/dist/server.js +5 -1
  14. package/dist/tasks/task-manager.js +4 -1
  15. package/dist/tasks/task-store.js +5 -0
  16. package/dist/verify/acceptance.js +124 -14
  17. package/dist/verify/report.js +16 -2
  18. package/dist/version.generated.js +1 -1
  19. package/dist/visual/baselines.js +209 -0
  20. package/dist/visual/budget.js +52 -0
  21. package/dist/visual/capture.js +368 -0
  22. package/dist/visual/cli.js +96 -0
  23. package/dist/visual/compare.js +142 -0
  24. package/dist/visual/config.js +22 -0
  25. package/dist/visual/defaults.js +25 -0
  26. package/dist/visual/engine.js +115 -0
  27. package/dist/visual/errors.js +15 -0
  28. package/dist/visual/images.js +144 -0
  29. package/dist/visual/lock.js +29 -0
  30. package/dist/visual/manage.js +107 -0
  31. package/dist/visual/paths.js +31 -0
  32. package/dist/visual/report.js +48 -0
  33. package/dist/visual/runtime.js +116 -0
  34. package/dist/visual/schema.js +225 -0
  35. package/dist/visual/services.js +155 -0
  36. package/dist/visual/snapshot.js +57 -0
  37. package/dist/visual/types.js +1 -0
  38. package/docs/visual-acceptance.en.md +123 -0
  39. package/docs/visual-acceptance.md +128 -0
  40. package/docs/visual-validation-evidence/macos-15-arm64-node20.environment.json +11 -0
  41. package/docs/visual-validation-evidence/macos-15-arm64-node22.environment.json +11 -0
  42. package/docs/visual-validation-evidence/macos-15-arm64-node24.environment.json +11 -0
  43. package/docs/visual-validation-evidence/macos-15-intel-node20.environment.json +11 -0
  44. package/docs/visual-validation-evidence/macos-15-intel-node22.environment.json +11 -0
  45. package/docs/visual-validation-evidence/macos-15-intel-node24.environment.json +11 -0
  46. package/docs/visual-validation-evidence/macos-ci-summary.txt +32 -0
  47. package/docs/visual-validation-evidence/windows-10-matrix.json +75 -0
  48. package/docs/visual-validation-evidence/windows-10-tests.log +22 -0
  49. package/docs/visual-validation.en.md +83 -0
  50. package/docs/visual-validation.md +83 -0
  51. package/package.json +17 -4
  52. package/scripts/evidence-visual-windows.mjs +321 -0
  53. package/skills/tianshu-mcp/SKILL.md +65 -15
  54. package/skills/tianshu-mcp/usage-examples.md +138 -24
package/CHANGELOG.en.md CHANGED
@@ -10,6 +10,16 @@ Chinese version: [CHANGELOG.md](CHANGELOG.md)
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ### Tests
14
+
15
+ - Two additional real-browser-gated visual cases (added after v0.5.0): screenshots succeed when the project path contains CJK characters and spaces; a main-document 302 redirect to a non-allowlisted origin is blocked by policy and passes once explicitly allowed. Full suite: **486 passed / 10 skipped**.
16
+ - New `npm run evidence:visual:windows` (`scripts/evidence-visual-windows.mjs`): collects the full Windows 10 local functional matrix (existing/static/command sources, port conflict that blocks without terminating another service, bounded readiness failure that cleans up the child process, local Edge isolated instance and version mismatch, missing-browser blocker), 9/9 passed.
17
+ - Collected macOS 13+ platform evidence: on macOS 15 hardware runners, Intel x64 and Apple Silicon arm64 (Node 20/22/24) each passed 10 files with 51 cases; raw records are committed under `docs/visual-validation-evidence/`.
18
+
19
+ ### Docs
20
+
21
+ - `docs/visual-validation{,.en}.md` rewritten with full platform evidence tables (system, Node, browser version, command, result), plus the new `docs/visual-validation-evidence/` raw machine-readable records.
22
+
13
23
  ### Planned
14
24
 
15
25
  - More external AI-Agent adapters (a new agent = one profile + an optional adapter file).
@@ -21,6 +31,79 @@ Chinese version: [CHANGELOG.md](CHANGELOG.md)
21
31
 
22
32
  ---
23
33
 
34
+ ## [0.5.0] — 2026-09-14
35
+
36
+ Adds an **optional visual acceptance module** that wires screenshot comparison and static image specification checks into the "develop → verify → repair → re-verify" loop. Projects that do not enable visuals behave compatibly, and legacy reports and task snapshots remain readable. See the [v0.5.0 release notes](docs/release-v0.5.0.en.md) for the full description.
37
+
38
+ ### Added
39
+
40
+ - **Page sources**: mutually exclusive `existing` / `command` / `static`; identical service definitions share one managed instance per round; the static host rejects traversal and out-of-project symlinks; an occupied port blocks instead of reusing or terminating another service.
41
+ - **Screenshots and interaction**: `viewport` / `fullPage` / `element` modes with declarative `click` / `input` / `hover` / `scroll` / `wait` steps; a fixed readiness flow (isolated context, login state, fonts and images, disabled animations, masks, sampling); bounded full-page scrolling to trigger lazy loading.
42
+ - **Stabilization and masks**: up to 3 samples taking two adjacent identical captures; continuously changing pages, exceeded pixel budgets and unstable captures block; an unmatchable mask selector or a fully masked image never passes.
43
+ - **Pixel comparison**: unified PNG; size mismatches fail without scaling; masked regions are excluded from numerator and denominator; pixelmatch antialiasing is excluded by default; connected-component analysis outputs coordinates, areas and an annotated image, keeping at most 100 regions while recording the remaining count and overall bounds.
44
+ - **Static image specifications**: explicit file lists; encoded-format/extension consistency, existence with complete decoding, EXIF-orientation-normalized dimensions, aspect ratio, byte size, optional DPI and real-transparent-pixel detection; unsupported formats are reported explicitly.
45
+ - **Two-phase baselines**: `prepare` produces a candidate (candidate ID, digest, target paths, preview) and `approve` verifies candidate/original-baseline/configuration digests before atomically writing the official baseline and manifest; a missing baseline can only produce a candidate and never a pass; automatic repair never calls the approval entry point.
46
+ - **Rule freezing**: visual configuration and baseline digests are saved before the agent starts and checked around each round; changes require a new snapshot through the dedicated `rules review` / `rules approve` flow.
47
+ - **MCP tools**: new `prepare_visual_baseline` and `approve_visual_baseline`, both side-effecting `write` operations requiring host approval.
48
+ - **CLI**: new `tianshu-mcp visual` subcommand (`init`, `browser install`, `doctor`, `baseline prepare/approve`, `rules review/approve`, `artifacts clean`), dispatched before the stdio connection.
49
+ - **Reports and artifacts**: `VerifyReport` gains an optional `visual` field and `files.html`; the offline HTML supports status filtering, side-by-side images, opacity overlays and region location with only local artifacts, escaped text and no CDN; each round's artifacts live at `<home>/tasks/<taskId>/visual/<round>/` with rounds allocated by a unified task-level lock.
50
+ - **Blockers and recovery**: distinguishes repairable defects, environment blockers and user cancellation; visual blockers enter `needs_attention` with a re-verification-pending marker; `rework_task` re-verifies first for visually blocked tasks and only real defects consume the repair budget; both the generic and Codex-specific repair plans include visual evidence and state that baselines, thresholds and switches must not be modified to bypass failures.
51
+ - **Configuration robustness**: an invalid acceptance configuration blocks explicitly instead of falling back silently; only an explicit `checks: []` disables command checks; `extraChecks` and `checksMode=replace` never override the visual gate; `visual` strictly validates unknown fields, duplicate IDs, empty rules and conflicting options.
52
+ - **Dependencies and runtime**: pinned `puppeteer-core@24.43.1`, `@puppeteer/browsers@2.13.2`, `sharp@0.34.5`, `pixelmatch@7.2.0`; the image library is an optional dynamic dependency whose absence does not prevent startup; browsers are installed explicitly on demand with no download during npm install or MCP startup; the visual module requires Node.js >=20.3 while non-visual features retain >=20.
53
+ - **Docs and gates**: new bilingual visual acceptance guide and validation progress; CI adds a real-browser matrix (ubuntu/windows/macos-intel/macos × Node 20/22/24) plus production-package consumer acceptance; release requires a successful CI for the target commit and blocks when mirror credentials are missing.
54
+
55
+ ### Fixed
56
+
57
+ - The acceptance engine no longer silently falls back to default checks when a project configuration is invalid; it blocks explicitly with a reason.
58
+ - Manual and automatic verification share the task-level lock for report round allocation, preventing concurrency or recovery from overwriting historical evidence.
59
+ - Manual verification now lands a visually blocked task in `needs_attention` instead of misreporting `failed`.
60
+ - `rework_task` allows a visually blocked task that lacks original session location information to re-verify first instead of being rejected outright.
61
+ - The ZCode recovery budget now determines the controlling reason before aborting dependent operations, so the reason is not overwritten by downstream abort listeners.
62
+ - `TaskOrchestrator` distinguishes "cancelled" from "blocked" when a visual integrity problem appears during startup, so cancellation is no longer misrecorded as `needs_attention`.
63
+
64
+ ### Tests
65
+
66
+ - Full suite: **486 passed / 8 skipped** (Windows 10 x64, Node 24.18.0), adding visual configuration, image specification, report, baseline, budget, snapshot, service, real-browser capture, flow and repair cases.
67
+ - The 8 real-browser-gated cases pass separately with `TIANSHU_VISUAL_BROWSER_TEST=1`; the production tarball visual smoke test passes in an isolated consumer.
68
+
69
+ ---
70
+
71
+ ## [0.4.1] — 2026-09-13
72
+
73
+ Documentation release: the orchestration skill docs are aligned with the actual v0.4.0 tool
74
+ surface, and the open-source repos now credit community contributors. No code behaviour changes.
75
+
76
+ ### Docs
77
+
78
+ - **Skill docs fully aligned with the v0.4.0 tool surface** (`skills/tianshu-mcp/`, idempotently synced
79
+ into `~/.rivet/skills/tianshu-mcp/` at server startup):
80
+ - `SKILL.md` now documents the **projectPath safety gate** (absolute path + existing directory +
81
+ realpath canonicalization, rejection of the home directory and system/root directories, dirty-repo
82
+ warning), so an infrastructure rejection is not mistaken for an agent failure.
83
+ - `SKILL.md` adds a **hard-failure error-code reference** (`setup_failed`/`project_ambiguous`/
84
+ `project_mismatch`/`model_unavailable`/`model_mismatch`/`permission_unknown`/`cdp_disconnected`/
85
+ `instance_busy`/`session_lost`/`input_mismatch`/`send_unknown`/`idle_timeout` and more), stating
86
+ that hard failures never enter acceptance or auto-rework.
87
+ - `SKILL.md` covers all `needs_user` kinds, including the new `setup_recovery` (zcode initialization
88
+ recovery exhausted), plus `continue_task` state/type restrictions and the refusal semantics when the
89
+ zcode session anchor is lost.
90
+ - `SKILL.md` documents the `codex-cli` headless path (user-defined `driver=spawn` profile, `model` not
91
+ applicable, CLI ≥0.154.0 requirement), the `ready`/`research` status semantics, **default-parallel 2**
92
+ acceptance checks (`verifyConcurrency`), and the `requireChanges` zero-change gate.
93
+ - `usage-examples.md` adds: a `codex-cli` dispatch example; the **full meta-block field table** (now
94
+ including `agentEndReason`/`lastRunSignal`/`checks`/`round`/`keptInstance`/`zcodeSessionId`/
95
+ `modelProvider`/`permissionMode`/`progressSummary`); an **error-code reference table**; a project-level
96
+ `.tianshu-mcp/acceptance.json` template (with the parallel-interference warning and `requireChanges`
97
+ guidance); a `setup_recovery` recovery example; and the profile whole-key override semantics.
98
+ - **Bilingual README contributor credits**: a new "Contributors" section lists, in order of first
99
+ participation, the community members who took part through Issues and pull requests (avatar + name).
100
+
101
+ ### Other
102
+
103
+ - `package.json` version bumped to `0.4.1` (`serverInfo.version` is synced automatically at build time).
104
+
105
+ ---
106
+
24
107
  ## [0.4.0] — 2026-09-13
25
108
 
26
109
  ### Added
@@ -62,6 +145,16 @@ Chinese version: [CHANGELOG.md](CHANGELOG.md)
62
145
  calls blew the `taskTimeoutMs` wall-clock budget under full-suite load.
63
146
  - CDP `connect()` failure paths now dispose of the WebSocket themselves (no longer relying on
64
147
  callers to disconnect); the `send()` timeout timer is unref'd.
148
+ - **Drive roots were not rejected by the `projectPath` gate** (Windows): `normPath` strips the
149
+ trailing slash (`D:\` -> `d:`), which never equals the `d:/` entries in the reject list, so the
150
+ gate was effectively a no-op for drive roots; a dedicated drive-root check now covers every
151
+ drive letter instead of relying on enumeration.
152
+ - `test/unit/project-dir-guard.test.ts` had a non-portable system-directory assertion: `/etc` and
153
+ `/usr` are POSIX paths, and on Windows they hit "directory does not exist" rather than the reject
154
+ list; the assertion is now platform-branched and verifies drive roots plus `C:/Windows` on Windows.
155
+ - `test/unit/acceptance-parallel.test.ts` cancellation case was flaky (green alone, red in a full
156
+ run): a fixed 250ms delay can precede the child spawn on slower platforms, mislabelling an
157
+ in-flight check as `skipped`; it now waits until both in-flight checks have really started.
65
158
 
66
159
  ### Performance
67
160
 
@@ -591,7 +684,8 @@ project → pick model and reasoning level → send instructions → run detecti
591
684
 
592
685
  ---
593
686
 
594
- [Unreleased]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.4.0...HEAD
687
+ [Unreleased]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.4.1...HEAD
688
+ [0.4.1]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.4.0...v0.4.1
595
689
  [0.4.0]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.3.4...v0.4.0
596
690
  [0.3.4]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.3.3...v0.3.4
597
691
  [0.3.3]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.3.2...v0.3.3
package/CHANGELOG.md CHANGED
@@ -9,6 +9,16 @@
9
9
 
10
10
  ## [未发布]
11
11
 
12
+ ### 测试
13
+
14
+ - 视觉验收补两条真实浏览器门禁用例(v0.5.0 之后补充):项目路径含中文与空格时截图正常;主文档 302 跳转到未放行来源时按策略拦截,显式放行后通过。全量测试 **486 passed / 10 skipped**。
15
+ - 新增 `npm run evidence:visual:windows`(`scripts/evidence-visual-windows.mjs`):在 Windows 10 本机采集完整功能矩阵证据(`existing`/静态/命令三种来源、端口冲突阻塞且不结束他人服务、就绪失败有界阻塞并清理子进程、本机 Edge 独立实例与版本不匹配、缺浏览器阻塞),9/9 通过。
16
+ - 采集 macOS 13+ 平台证据:macOS 15 真机 runner 上 Intel x64 与 Apple Silicon arm64(Node 20/22/24)各跑通 10 文件 51 用例;原始记录随 `docs/visual-validation-evidence/` 入库。
17
+
18
+ ### 文档
19
+
20
+ - `docs/visual-validation{,.en}.md` 重写为完整平台证据表(系统、Node、浏览器版本、命令、结果),并新增 `docs/visual-validation-evidence/` 原始机器可读记录。
21
+
12
22
  ### 计划中
13
23
 
14
24
  - 更多外部 AI-Agent 适配(新 agent = 一个 profile +(如需)一个 adapter 文件)。
@@ -19,6 +29,63 @@
19
29
 
20
30
  ---
21
31
 
32
+ ## [0.5.0] — 2026-09-14
33
+
34
+ 新增**可选视觉验收模块**:把页面截图对比与静态图片规格检查接入「开发 → 验收 → 返修 → 再验收」闭环。未启用视觉的项目行为兼容;旧报告与旧任务快照仍可读取。完整说明见 [v0.5.0 发布说明](docs/release-v0.5.0.md)。
35
+
36
+ ### 新增
37
+
38
+ - **页面来源**:互斥的 `existing` / `command` / `static` 三种来源;服务按定义在同轮复用;静态托管拒绝目录穿越与项目外符号链接;端口占用即阻塞,不擅自复用或结束其他服务。
39
+ - **截图与交互**:`viewport` / `fullPage` / `element` 模式与声明式 `click` / `input` / `hover` / `scroll` / `wait` 步骤;固定就绪流程(隔离上下文、登录态、字体与图片、关闭动画、屏蔽、采样);支持整页有界滚动触发懒加载。
40
+ - **稳定化与屏蔽**:最多 3 次采样取相邻一致;持续变化、超像素预算或无法稳定即阻塞;屏蔽选择器定位失败或全图屏蔽都不通过。
41
+ - **像素对比**:统一 PNG;尺寸不一致直接失败不缩放;屏蔽区域不计入分子分母;pixelmatch 抗锯齿默认排除;连通区域分析输出坐标、面积、标注图,最多保留 100 个区域并记录其余数量与整体包围框。
42
+ - **静态图片规格**:显式文件列表;编码格式与扩展名一致性、存在非空且完整解码、EXIF 方向归一后的宽高、宽高比、字节数、可选 DPI 与真实透明像素判定;不支持格式明确报告。
43
+ - **基准两阶段**:`prepare` 生成候选(候选 ID、摘要、目标路径、预览),`approve` 核对候选/原基准/配置摘要后原子写入正式基准与 manifest;缺基准只能生成候选、不能判视觉通过;自动返修不调用批准入口。
44
+ - **规则冻结**:任务动工前保存视觉配置与基准摘要,每轮前后核对;变化需经独立 `rules review` / `rules approve` 重建快照。
45
+ - **MCP 工具**:新增 `prepare_visual_baseline`、`approve_visual_baseline`(均为有副作用、需宿主审批的 `write` 操作)。
46
+ - **CLI**:新增 `tianshu-mcp visual` 子命令(`init`、`browser install`、`doctor`、`baseline prepare/approve`、`rules review/approve`、`artifacts clean`),在 stdio 连接前分流。
47
+ - **报告与产物**:`VerifyReport` 新增可选 `visual` 字段与 `files.html`;离线 HTML 支持状态过滤、图片并排、透明叠加与区域定位,纯本地产物、文本转义、无 CDN;每轮产物位于 `<home>/tasks/<taskId>/visual/<round>/`,轮次由统一任务级锁分配。
48
+ - **阻塞与恢复**:区分可返修缺陷、环境阻塞与用户取消;视觉阻塞进 `needs_attention` 并保留待重新验收标记;`rework_task` 对视觉阻塞先重新验收、仅真实缺陷才消耗返修预算;通用与 Codex 专用返修计划均含视觉证据并明示不得修改基准/阈值/开关绕过。
49
+ - **配置健壮性**:无效 acceptance 配置显式阻塞而非静默回退;显式 `checks: []` 才关闭命令检查;`extraChecks` 与 `checksMode=replace` 不覆盖视觉门禁;`visual` 严格校验未知字段、重复 ID、空规则与冲突选项。
50
+ - **依赖与运行时**:固定 `puppeteer-core@24.43.1`、`@puppeteer/browsers@2.13.2`、`sharp@0.34.5`、`pixelmatch@7.2.0`;图像库为可选动态依赖,缺失不阻止启动;浏览器按需显式安装,npm 安装与 MCP 启动均不下载浏览器;视觉模块要求 Node.js >=20.3,非视觉功能保留 >=20。
51
+ - **文档与门禁**:新增双语视觉验收指南与验证进度;CI 新增真实浏览器矩阵(ubuntu/windows/macos-intel/macos × Node 20/22/24)与生产包消费者验收;release 要求目标提交存在成功 CI 且缺少镜像凭据时阻塞。
52
+
53
+ ### 修复
54
+
55
+ - 验收引擎解析到无效项目配置时不再静默回退默认检查,改为显式阻塞并给出原因。
56
+ - 手动验收与自动验收统一使用任务级锁分配报告轮次,避免并发或恢复覆盖历史证据。
57
+ - 手动验收遇到视觉阻塞时任务落 `needs_attention`,不再误记 `failed`。
58
+ - `rework_task` 允许对视觉阻塞但缺少原会话定位的任务先重新验收,不再直接拒绝。
59
+ - ZCode 恢复预算在取消/截止时间到达时先确定原因再中止依赖操作,避免原因被下游 abort 监听覆盖。
60
+ - `TaskOrchestrator` 启动阶段遇到视觉完整性问题时区分「被取消」与「阻塞」,取消不再误记为 `needs_attention`。
61
+
62
+ ### 测试
63
+
64
+ - 全量 **486 passed / 8 skipped**(Windows 10 x64,Node 24.18.0):新增视觉配置、图片规格、报告、基准、缓冲、快照、服务、真实浏览器捕获、流程与返修用例。
65
+ - 8 项真实浏览器门禁用例以 `TIANSHU_VISUAL_BROWSER_TEST=1` 单独跑通;生产 tarball 独立消费者视觉冒烟通过。
66
+
67
+ ---
68
+
69
+ ## [0.4.1] — 2026-09-13
70
+
71
+ 文档版本:把编排技能文档对齐 v0.4.0 实际工具面,并补齐开源仓库的贡献者名录。本版本无代码行为变更。
72
+
73
+ ### 文档
74
+
75
+ - **技能文档全面对齐 v0.4.0 工具面**(`skills/tianshu-mcp/`,server 启动时幂等同步到 `~/.rivet/skills/tianshu-mcp/`):
76
+ - `SKILL.md` 新增 **projectPath 安全闸门**说明(绝对路径 + 存在目录 + realpath 归一、主目录与系统根目录拒绝、脏仓警示),避免把基础设施拒绝误判为 agent 失败。
77
+ - `SKILL.md` 新增 **硬失败错误码速查**(`setup_failed`/`project_ambiguous`/`project_mismatch`/`model_unavailable`/`model_mismatch`/`permission_unknown`/`cdp_disconnected`/`instance_busy`/`session_lost`/`input_mismatch`/`send_unknown`/`idle_timeout` 等),明确硬失败不进验收与自动返修。
78
+ - `SKILL.md` 补全 needs_user 等待类型:新增 `setup_recovery`(zcode 初始化恢复未完成);补 `continue_task` 的状态与类型限制、zcode 会话定位信息丢失时的拒绝语义。
79
+ - `SKILL.md` 补 `codex-cli` 无头路径(用户自建 `driver=spawn` profile、model 不生效、CLI ≥0.154.0 版本要求)、`ready`/`research` 状态语义、验收 **默认并行 2**(`verifyConcurrency`)与 `requireChanges` 零变更门禁。
80
+ - `usage-examples.md` 新增:`codex-cli` 派活示例;meta 块**字段全表**(补 `agentEndReason`/`lastRunSignal`/`checks`/`round`/`keptInstance`/`zcodeSessionId`/`modelProvider`/`permissionMode`/`progressSummary` 等);**错误码速查表**;项目级 `.tianshu-mcp/acceptance.json` 配置模板(含 `verifyConcurrency` 并行干扰警示与 `requireChanges` 用法);`setup_recovery` 恢复示例;profile 整键覆盖语义。
81
+ - **双语 README 补贡献者名录**:新增「贡献者 / Contributors」小节,按首次参与顺序列出通过 Issue 与 PR 参与项目的社区成员(头像 + 名字)。
82
+
83
+ ### 其他
84
+
85
+ - `package.json` 版本号提升至 `0.4.1`(`serverInfo.version` 经 build 自动同步)。
86
+
87
+ ---
88
+
22
89
  ## [0.4.0] — 2026-09-13
23
90
 
24
91
  ### 新增
@@ -50,6 +117,9 @@
50
117
  - `get_profiles` 列出数据目录 `agent-profiles.json` 中的用户自定义 profile(此前未 resolve 不显示,`run_task` 却可用,探测反馈不一致)。
51
118
  - zcode-flow 测试桩补 `listDialogs`,消除真实 osascript/PowerShell 调用在全量负载下撞 `taskTimeoutMs` 墙钟导致的 flake。
52
119
  - CDP `connect()` 失败分支自清理 WebSocket(不再依赖调用方兜底 disconnect);`send()` 超时定时器 unref。
120
+ - **盘符根未被 `projectPath` 闸门拦截**(Windows):`normPath` 会剥掉尾斜杠(`D:\` → `d:`),与拒绝清单里的 `d:/` 永不相等,故闸门对盘符根形同虚设;改为**单独的盘符根判定**,覆盖所有盘符而不依赖枚举。
121
+ - `test/unit/project-dir-guard.test.ts` 的系统目录断言不可移植:`/etc`、`/usr` 是 POSIX 路径,Windows 上命中的是「目录不存在」而非拒绝清单;按平台分支,Windows 侧改验盘符根与 `C:/Windows`。
122
+ - `test/unit/acceptance-parallel.test.ts` 取消用例偶发(单跑绿、全量红):固定 250ms 在慢平台可能早于子进程 spawn,使在途 check 被误记为 `skipped`;改为**等两个在途 check 真正启动后再取消**。
53
123
 
54
124
  ### 性能
55
125
 
@@ -509,7 +579,8 @@ Codex 桌面端改为 **GUI 驱动**:新增 `codex-gui` adapter,通过 MSIX
509
579
 
510
580
  ---
511
581
 
512
- [未发布]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.4.0...HEAD
582
+ [未发布]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.4.1...HEAD
583
+ [0.4.1]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.4.0...v0.4.1
513
584
  [0.4.0]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.3.4...v0.4.0
514
585
  [0.3.4]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.3.3...v0.3.4
515
586
  [0.3.3]: https://github.com/lanlan0811/tianshu-mcp/compare/v0.3.2...v0.3.3
package/README.en.md CHANGED
@@ -8,6 +8,8 @@
8
8
 
9
9
  # tianshu-mcp
10
10
 
11
+ Visual acceptance (v0.5.0): [English guide](docs/visual-acceptance.en.md) · [Validation record](docs/visual-validation.en.md) · [Release notes](<docs/release-v0.5.0.en.md>).
12
+
11
13
  **Tianshu × AI-Agent orchestration MCP server**
12
14
 
13
15
  Registered by Tianshu as a standard MCP server, it dispatches external AI-Agents (Codex desktop, TraeWork/TRAE SOLO CN and ZCode, all driven through their desktop UIs over CDP) to drive the closed loop of **project development → acceptance → failure rework → re-acceptance** (horizontally extensible).
@@ -37,6 +39,7 @@ Tianshu plays the role of the overall commander; this MCP server is the **schedu
37
39
  - **9 MCP tools**: `run_task / continue_task / query_task / list_tasks / get_task_report / cancel_task / verify_task / rework_task / get_profiles`.
38
40
  - **Async contract**: `run_task` returns a `taskId` immediately; long-running work is polled via `query_task` (never blocks `tools/call`).
39
41
  - **Objective acceptance**: automated command checks (typecheck/lint/test/build — skipped when absent, plus tech-stack derivation) + programmatic code analysis (changed-file list / diffstat / suspicious signals such as TODO, debugger, secret-like patterns), all relative to a **git baseline**; never auto-commits or stashes. The acceptance engine is **fail-closed**: a test check fails when its output reports zero executed tests even if the exit code is 0; git projects must produce changes relative to the pre-work baseline by default (pure analysis tasks can opt out with `"requireChanges": false` in `.tianshu-mcp/acceptance.json`).
42
+ - **Acceptance parallelism**: command checks run **bounded-parallel** by default (`verifyConcurrency`, default 2, range 1–4). When checks depend on an order (a later check reading build output, `--fix`, shared cache dirs), set it to `1` for fully serial behaviour; a project can override it in `.tianshu-mcp/acceptance.json`, and the server level lives in `config.json`. Report and log formats are unchanged (results are returned in declaration order).
40
43
  - **Rework loop**: automatic rework (`autoFixRounds`) + manual `rework_task`; on verification failure a repair-plan file is generated and fed back to the agent; when rounds run out → `needs_attention` awaiting Tianshu's verdict.
41
44
  - **Execution surfaces**: `driver: "gui"` selects an explicit, isolated Codex/TraeWork/ZCode CDP adapter; `driver: "spawn"` runs an external CLI child process.
42
45
  - **Scheduling discipline**: per-project serial queue + global concurrency cap (default 2, configurable).
@@ -63,7 +66,7 @@ git clone https://github.com/lanlan0811/tianshu-mcp.git
63
66
  cd tianshu-mcp
64
67
  npm ci
65
68
  npm run build # sync-version + tsc → dist/
66
- npm test # 443 tests across 46 files, including Codex/ZCode unit/fake-CDP/restart/recovery/repair coverage
69
+ npm test # 496 tests across 56 files, including Codex/ZCode/TraeWork unit/fake-CDP/restart/recovery/repair loops and visual acceptance
67
70
  ```
68
71
 
69
72
  ### Install the npm package
@@ -89,7 +92,7 @@ In Tianshu go to **Settings → MCP Servers → Add** and fill in the fields bel
89
92
  > - The server ID becomes the tool prefix: with `tianshu-mcp` the tools are `mcp__tianshu-mcp__run_task` and 8 others.
90
93
  > - Arguments are space-separated, **no quotes**; for local dev replace `<absolute-repo-path>` with a real path (e.g. `D:/TraeProject/tianshu-mcp/dist/index.js`).
91
94
  > - The dialog has no env-var field; to customize the data directory, use the `config.json` method below and set `TIANSHU_MCP_HOME`.
92
- > - Once the server connects, open a new session and the 9 tools appear.
95
+ > - Once the server connects, open a new session and the 11 tools appear.
93
96
 
94
97
  ### Or edit config.json (supports env vars)
95
98
 
@@ -109,7 +112,7 @@ Register as a Tianshu MCP server (local dev mode):
109
112
  }
110
113
  ```
111
114
 
112
- After opening a new session, the 9 tools such as `mcp__tianshu-mcp__run_task` appear. Rehearse with the stub agent first (no real login state), then switch to the `codex` profile for real tasks:
115
+ After opening a new session, the 11 tools such as `mcp__tianshu-mcp__run_task` appear. Rehearse with the stub agent first (no real login state), then switch to the `codex` profile for real tasks:
113
116
 
114
117
  ```text
115
118
  run_task(projectPath=D:/xxx/my-app, task=「…task brief…」, agentId=codex,
@@ -147,7 +150,7 @@ run_task(projectPath=D:/xxx/my-app, agentId=zcode, task="Implement `./plan.md`",
147
150
 
148
151
  Questions, login, an existing non-CDP instance, or system permission pause as `needs_user`; call `continue_task(taskId, message)` to resume the recorded session. Model selection is adapted to ZCode 3.11.2: flat models are selected directly first, with provider/family group expansion as a fallback — both new and legacy layouts are supported. See [docs/zcode-cdp.en.md](docs/zcode-cdp.en.md).
149
152
 
150
- ## Tool surface (9 tools)
153
+ ## Tool surface (11 tools)
151
154
 
152
155
  | Tool | Capability / approval | Purpose |
153
156
  |---|---|---|
@@ -160,6 +163,8 @@ Questions, login, an existing non-CDP instance, or system permission pause as `n
160
163
  | `verify_task` | read | Run one verification pass on a task/project path (no source changes) |
161
164
  | `rework_task` | write + approval | Manual rework (feed the failure report back to the same agent) |
162
165
  | `get_profiles` | read | Inspect agent adapters and executable discovery results |
166
+ | `prepare_visual_baseline` | write + approval | Capture or import reference images into a reviewable candidate with a digest |
167
+ | `approve_visual_baseline` | write + approval | Validate the reviewed digest and write the baseline and approval record |
163
168
 
164
169
  > Every result is "human-readable text + a `---tianshu-mcp-meta---` JSON block" so the host can extract it with a regex.
165
170
 
@@ -190,6 +195,11 @@ Use `server.log` when troubleshooting connections; do not treat stderr output it
190
195
  | [docs/codex-gui-cdp.en.md](docs/codex-gui-cdp.en.md) | Codex desktop GUI driver: MSIX COM activation, CDP attach, selectors, run detection, verify/repair |
191
196
  | [docs/codex-windows-smoke.en.md](docs/codex-windows-smoke.en.md) | Codex Windows hardware record (incl. verify-fail → auto plan → repair-pass loop) |
192
197
  | [docs/release-v0.3.4.en.md](<docs/release-v0.3.4.en.md>) | v0.3.4 release notes (ZCode project/model read-back, initialization recovery, session dispatch confirmation, issues #8/#9/#10) |
198
+ | [docs/release-v0.5.0.en.md](<docs/release-v0.5.0.en.md>) | v0.5.0 release notes (optional visual acceptance: screenshots, image specs, baseline approval, offline report) |
199
+ | [docs/visual-acceptance.en.md](<docs/visual-acceptance.en.md>) | Visual acceptance primer and full configuration: three page sources, baseline candidates/approval, rule freezing, thresholds and troubleshooting |
200
+ | [docs/visual-validation.en.md](<docs/visual-validation.en.md>) | Visual acceptance validation progress: full Windows 10 matrix and macOS Intel/Apple Silicon platform evidence (system/Node/browser/command/result) |
201
+ | [docs/visual-validation-evidence/](<docs/visual-validation-evidence/>) | Raw machine-readable records for the above (environment JSON, matrix results, test output and macOS CI summaries) |
202
+ | [docs/release-v0.4.1.en.md](<docs/release-v0.4.1.en.md>) | v0.4.1 release notes (skill docs aligned with the v0.4.0 tool surface + contributor credits) |
193
203
  | [docs/zcode-issue-8-10-validation.en.md](<docs/zcode-issue-8-10-validation.en.md>) | ZCode #8/#9/#10 Windows hardware record (cold import, imported-project reuse, same-task recovery) |
194
204
  | [docs/release-v0.3.3.en.md](<docs/release-v0.3.3.en.md>) | v0.3.3 release notes (ZCode 3.11.2 adaptation + fail-closed acceptance engine) |
195
205
  | [docs/release-v0.3.2.en.md](docs/release-v0.3.2.en.md) | v0.3.2 release notes (Codex wait-user detection + cancel truly stops the GUI) |
@@ -226,9 +236,9 @@ Use `server.log` when troubleshooting connections; do not treat stderr output it
226
236
  - Zcode headless entry (Z1) verified: ZCode desktop ships no headless CLI → unsupported
227
237
  - **R1–R8 / S1–S6 — two acceptance hardening rounds** ✅ (cancel / timeout / baseline attribution / parameter semantics / hot reload / CI hardening) — **72 tests**
228
238
  - **Engineering / CI** ✅
229
- - GitHub Actions: `CI` (ubuntu/windows/macos × Node 20/22/24 + pack-check, **10/10 green**, re-verified with the v0.3.4 tag) and `Release` (tag-triggered) both green
239
+ - GitHub Actions: `CI` (`build-test` ubuntu/windows/macos × Node 20/22/24 + `pack-check`, plus a `visual-browser` real-browser matrix ubuntu/windows/macos-15-intel/macos-15 × Node 20/22/24, all green with the v0.5.0 tag) and `Release` (tag-triggered) both green
230
240
  - Skill self-install verified idempotent on this machine's real `~/.rivet/skills/tianshu-mcp`
231
- - npm package name `tianshu-mcp` published continuously since v0.1.1 (currently `0.3.4`)
241
+ - npm package name `tianshu-mcp` published continuously since v0.1.1 (currently `0.5.0`)
232
242
  - **Real Tianshu host integration (DoD #6)** ✅ (2026-09-07)
233
243
  - Configured the local mode in the real `D:\Tianshu` desktop host `mcp.servers` → sidecar reported `MCP: 2 servers connected, 10 tools` (including this server's 8 tools), spawned the child process and connected over stdio
234
244
  - Exposed and fixed a skill-install source-path bug (fileURLToPath, commit 55cf2d0)
@@ -286,6 +296,17 @@ Use `server.log` when troubleshooting connections; do not treat stderr output it
286
296
  - **projectPath safety gate**: realpath canonicalization + home/system-root rejection + dirty-repo coexistence warning — see "Path safety gate"
287
297
  - **Fixes**: `get_profiles` missing user-defined profiles; zcode macOS `needsPermission` false positives; `normalizeProjectPath` symlink ambiguity; CDP polling now reconnects across renderer replacement/transient hangs
288
298
  - **Engineering**: all `execFileSync`/`spawnSync` calls async (no more event-loop freezes during Windows polling); bounded-parallel acceptance checks (`verifyConcurrency`); test suite 267s → 51s
299
+ - **M18 — skill docs aligned with the v0.4.0 tool surface + contributor credits + v0.4.1** (2026-09-13) — **443 tests**
300
+ - `skills/tianshu-mcp/` now covers every v0.3.3 → v0.4.0 tool-surface change: the projectPath safety gate, the hard-failure error-code reference, the `setup_recovery` wait kind, the codex-cli headless path, `ready`/`research` status semantics, default-parallel-2 acceptance and the `requireChanges` gate; usage-examples adds the error-code table, the full meta field table, a project-level acceptance-config template and a `codex-cli` example
301
+ - Bilingual README gains a contributor credits section (avatar + name, in order of first participation)
302
+ - **No code behaviour changes**; no migration needed
303
+ - **M19 — optional visual acceptance module + v0.5.0** (2026-09-14) — **486 tests**
304
+ - **Page screenshot comparison**: three mutually exclusive page sources (existing service / command startup / temporary static host), three capture modes, declarative interaction steps, stabilization sampling with explicit masks, pixelmatch antialiasing exclusion and connected-region annotation; size mismatches fail directly
305
+ - **Static image specifications**: encoded-format/extension consistency, complete decoding, EXIF-orientation-normalized dimensions, aspect ratio/byte size/DPI/real transparent pixels; unsupported formats reported explicitly
306
+ - **Two-phase baselines and freezing**: candidate preparation → user approval; a missing baseline never passes; automatic repair may not approve; configuration and baseline digests are frozen before the agent starts and checked every round
307
+ - **MCP/CLI**: new `prepare_visual_baseline` / `approve_visual_baseline` and the `tianshu-mcp visual` subcommand family, dispatched before the stdio connection
308
+ - **Reports and recovery**: `VerifyReport` gains an optional `visual` section and offline HTML (status filter, opacity overlay, region location); visual blockers enter `needs_attention` and `rework_task` re-verifies first so only real defects consume repair budget
309
+ - **Gates**: CI adds a four-system, three-Node real-browser matrix plus isolated production-package consumer acceptance; release requires a successful CI for the target commit and blocks when Gitee credentials are missing rather than claiming success
289
310
 
290
311
  ## Agent support status
291
312
 
@@ -358,7 +379,7 @@ Behavior and limits:
358
379
 
359
380
  | Document | Content |
360
381
  |---|---|
361
- | [CHANGELOG.en.md](<CHANGELOG.en.md>) | Version history (v0.1.0 → v0.3.4) |
382
+ | [CHANGELOG.en.md](<CHANGELOG.en.md>) | Version history (v0.1.0 → v0.5.0) |
362
383
  | [CONTRIBUTING.en.md](CONTRIBUTING.en.md) | Dev setup, conventions, commit/release flow, adding an agent |
363
384
  | [SECURITY.en.md](SECURITY.en.md) | Security model (zero credentials / command whitelist / process & desktop-automation boundaries) and private reporting |
364
385
  | [CODE_OF_CONDUCT.en.md](CODE_OF_CONDUCT.en.md) | Contributor Code of Conduct |
@@ -368,6 +389,23 @@ Behavior and limits:
368
389
  - **Mirror repository**: <https://gitee.com/lan0811/tianshu-mcp> (Gitee)
369
390
  - **Feedback**: bugs / feature requests via the repo Issue templates; report security vulnerabilities privately per [SECURITY.en.md](SECURITY.en.md) — **do not** open a public issue.
370
391
 
392
+ ### Contributors
393
+
394
+ Thanks to the community members below who contributed through Issues and pull requests (listed in order of first participation):
395
+
396
+ <table>
397
+ <tr>
398
+ <td align="center"><a href="https://github.com/liuchsong"><img src="https://github.com/liuchsong.png" width="72" height="72" alt="liuchsong" /><br /><sub>liuchsong</sub></a></td>
399
+ <td align="center"><a href="https://github.com/a13612745638"><img src="https://github.com/a13612745638.png" width="72" height="72" alt="a13612745638" /><br /><sub>a13612745638</sub></a></td>
400
+ <td align="center"><a href="https://github.com/king195547"><img src="https://github.com/king195547.png" width="72" height="72" alt="king195547" /><br /><sub>king195547</sub></a></td>
401
+ </tr>
402
+ <tr>
403
+ <td align="center"><a href="https://github.com/zhaoxc857"><img src="https://github.com/zhaoxc857.png" width="72" height="72" alt="zhaoxc857" /><br /><sub>zhaoxc857</sub></a></td>
404
+ <td align="center"><a href="https://github.com/jian-in"><img src="https://github.com/jian-in.png" width="72" height="72" alt="jian-in" /><br /><sub>jian-in</sub></a></td>
405
+ <td align="center"><a href="https://github.com/huiliyi37"><img src="https://github.com/huiliyi37.png" width="72" height="72" alt="huiliyi37" /><br /><sub>huiliyi37</sub></a></td>
406
+ </tr>
407
+ </table>
408
+
371
409
  > Chinese counterparts: see [README.md](README.md). The handoff document [HANDOFF.md](HANDOFF.md) is Chinese-only.
372
410
 
373
411
  ## License
package/README.md CHANGED
@@ -8,6 +8,8 @@
8
8
 
9
9
  # tianshu-mcp
10
10
 
11
+ 视觉验收(v0.5.0):[中文指南](docs/visual-acceptance.md) · [验证记录](docs/visual-validation.md) · [发布说明](<docs/release-v0.5.0.md>)。
12
+
11
13
  **天枢 × AI-Agent 编排 MCP server**
12
14
 
13
15
  由天枢(Tianshu)当作标准 MCP server 接入,调度外部 AI-Agent(Codex 桌面端、TraeWork/TRAE SOLO CN、ZCode 均经 CDP 驱动桌面 UI)完成 **项目开发 → 验收 → 失败返修 → 再验收** 的闭环(架构可横向扩展)。
@@ -37,6 +39,7 @@
37
39
  - **9 个 MCP 工具**:`run_task / continue_task / query_task / list_tasks / get_task_report / cancel_task / verify_task / rework_task / get_profiles`。
38
40
  - **异步契约**:`run_task` 秒回 `taskId`,长任务用 `query_task` 轮询(长任务不卡 `tools/call`)。
39
41
  - **客观验收**:自动命令检查(typecheck/lint/test/build,缺则跳过 + 技术栈推导)+ 程序化代码分析(变更清单/diffstat/TODO·debugger·密钥形态等可疑标记),全部相对 **git 基线**,不自动 commit/stash。验收引擎 **fail-closed**:测试命令退出码为 0 但输出显示零用例时判失败;git 项目默认要求相对动工前基线产生变更(纯分析任务可在 `.tianshu-mcp/acceptance.json` 设 `"requireChanges": false` 显式关闭)。
42
+ - **验收并行度**:命令检查默认**有界并行**(`verifyConcurrency`,默认 2、范围 1–4)。检查项之间有顺序依赖时(后续检查读取 build 产物、带 `--fix`、共享缓存目录)请设 `1` 完全退化为串行;项目级 `.tianshu-mcp/acceptance.json` 可覆盖,server 级在 `config.json`。报告与日志格式不变(结果按声明顺序返回)。
40
43
  - **失败返修闭环**:自动返修(`autoFixRounds`)+ 手动 `rework_task`;验收失败时自动生成修复计划文件并回填给 agent;轮次用尽 → `needs_attention` 等天枢裁决。
41
44
  - **执行面**:`driver: "gui"` 由显式 adapter 驱动桌面 UI(Codex / TraeWork / ZCode 各自使用隔离的 CDP 流程);`driver: "spawn"` 走外部 CLI 子进程。
42
45
  - **调度纪律**:每项目串行队列 + 全局并发上限(默认 2,可配)。
@@ -63,7 +66,7 @@ git clone https://github.com/lanlan0811/tianshu-mcp.git
63
66
  cd tianshu-mcp
64
67
  npm ci
65
68
  npm run build # sync-version + tsc → dist/
66
- npm test # 443 项测试:46 个文件,含 Codex/ZCode 单元/假 CDP/重启/恢复/返修闭环
69
+ npm test # 496 项测试:56 个文件,含 Codex/ZCode/TraeWork 单元/假 CDP/重启/恢复/返修闭环与视觉验收
67
70
  ```
68
71
 
69
72
  ### 安装 npm 包
@@ -88,7 +91,7 @@ npm install -g tianshu-mcp
88
91
  > - 服务器 ID 即工具前缀:填 `tianshu-mcp` 后工具名为 `mcp__tianshu-mcp__run_task` 等 9 个。
89
92
  > - 参数按空格分隔填写,**不要加引号**;本地开发模式请把 `<仓库绝对路径>` 换成真实绝对路径(如 `D:/Trae项目/tianshu-mcp/dist/index.js`)。
90
93
  > - 界面未提供环境变量输入框;如需自定义数据目录,改用下面的 `config.json` 方式设置 `TIANSHU_MCP_HOME`。
91
- > - 添加后连接成功即完成;新开会话即可看到 9 个工具。
94
+ > - 添加后连接成功即完成;新开会话即可看到 11 个工具。
92
95
 
93
96
  ### 或改 config.json(可配环境变量)
94
97
 
@@ -108,7 +111,7 @@ npm install -g tianshu-mcp
108
111
  }
109
112
  ```
110
113
 
111
- 新开会话后,工具面出现 `mcp__tianshu-mcp__run_task` 等 9 个工具。用 stub 预演(不碰真实登录态)→ 切 codex 跑真实任务:
114
+ 新开会话后,工具面出现 `mcp__tianshu-mcp__run_task` 等 11 个工具。用 stub 预演(不碰真实登录态)→ 切 codex 跑真实任务:
112
115
 
113
116
  ```text
114
117
  run_task(projectPath=D:/xxx/my-app, task=「…任务书…」, agentId=codex,
@@ -143,7 +146,7 @@ run_task(projectPath=D:/xxx/my-app, agentId=zcode, task=「按 `./plan.md` 完
143
146
 
144
147
  ZCode 提问、需要登录、旧实例无 CDP、系统权限不足,或自动恢复未完成(`needs_user/setup_recovery`)时进入 `needs_user`;处理后调用 `continue_task(taskId, message)` 恢复——确认文本不发给模型,无锚点的环境恢复会补发完整原任务、上下文与已验证引用,且不消耗返修轮数。模型选择已适配 ZCode 3.11.2:直选平铺模型优先,展开 provider/family 分组兜底,新旧布局均兼容。完整约束见 docs/zcode-cdp.md。
145
148
 
146
- ## 工具面(9 个)
149
+ ## 工具面(11 个)
147
150
 
148
151
  | 工具 | 能力 / 审批 | 作用 |
149
152
  |---|---|---|
@@ -156,6 +159,8 @@ ZCode 提问、需要登录、旧实例无 CDP、系统权限不足,或自动
156
159
  | `verify_task` | read | 对任务/项目路径做一次验收(不改源码) |
157
160
  | `rework_task` | write + 审批 | 手动返修(把失败报告喂回同一 agent) |
158
161
  | `get_profiles` | read | 查看 agent 适配与可执行探测结果 |
162
+ | `prepare_visual_baseline` | write + 审批 | 截图或导入参考图,生成待审阅候选和摘要 |
163
+ | `approve_visual_baseline` | write + 审批 | 用户审阅后校验摘要并写入基准与审批记录 |
159
164
 
160
165
  > 返回统一为「人类可读文本 + `---tianshu-mcp-meta---` JSON 块」,便于宿主正则抽取。
161
166
 
@@ -185,6 +190,11 @@ ZCode 提问、需要登录、旧实例无 CDP、系统权限不足,或自动
185
190
  | [docs/zcode-windows-smoke.md](docs/zcode-windows-smoke.md) | ZCode Windows 真机开发、同会话返修与提问续跑验收记录 |
186
191
  | [docs/codex-gui-cdp.md](docs/codex-gui-cdp.md) | Codex 桌面端 GUI 驱动:MSIX COM 激活、CDP 接管、选择器、运行检测、验收返修 |
187
192
  | [docs/codex-windows-smoke.md](docs/codex-windows-smoke.md) | Codex Windows 真机验收记录(含验收失败→自动生成计划→返修通过闭环) |
193
+ | [docs/release-v0.5.0.md](<docs/release-v0.5.0.md>) | v0.5.0 发布说明(可选视觉验收模块:截图对比、图片规格、基准批准、离线报告) |
194
+ | [docs/visual-acceptance.md](<docs/visual-acceptance.md>) | 视觉验收入门与完整配置:三种页面来源、基准候选/批准、规则冻结、阈值与排查 |
195
+ | [docs/visual-validation.md](<docs/visual-validation.md>) | 视觉验收验证进度:Windows 10 完整功能矩阵与 macOS Intel/Apple Silicon 平台证据(系统/Node/浏览器/命令/结果) |
196
+ | [docs/visual-validation-evidence/](<docs/visual-validation-evidence/>) | 上述验证的原始机器可读记录(环境 JSON、矩阵结果、测试输出与 macOS CI 摘要) |
197
+ | [docs/release-v0.4.1.md](<docs/release-v0.4.1.md>) | v0.4.1 发布说明(技能文档对齐 v0.4.0 工具面 + 贡献者名录) |
188
198
  | [docs/release-v0.3.4.md](<docs/release-v0.3.4.md>) | v0.3.4 发布说明(ZCode 项目/模型回读、初始化恢复与会话发送确认,issue #8/#9/#10) |
189
199
  | [docs/zcode-issue-8-10-validation.md](<docs/zcode-issue-8-10-validation.md>) | ZCode #8/#9/#10 Windows 真机验收记录(冷导入、已导入复用、同任务恢复) |
190
200
  | [docs/release-v0.3.3.md](<docs/release-v0.3.3.md>) | v0.3.3 发布说明(ZCode 3.11.2 适配 + 验收引擎 fail-closed) |
@@ -225,9 +235,9 @@ ZCode 提问、需要登录、旧实例无 CDP、系统权限不足,或自动
225
235
  - Zcode 无头接口(Z1)实测定论:ZCode 桌面无随包 headless CLI → unsupported
226
236
  - **R1–R8 / S1–S6 — 两轮验收整改** ✅(取消/超时/基线归因/参数语义/热加载/CI 加固)— **72 测试**
227
237
  - **工程 / CI** ✅
228
- - GitHub Actions:`CI`(ubuntu/windows/macos × Node 20/22/24 + pack-check,**10/10 全绿**,随 v0.3.4 tag 再次校验)与 `Release`(tag 触发)均绿
238
+ - GitHub Actions:`CI`(`build-test` ubuntu/windows/macos × Node 20/22/24 + `pack-check`,另加 `visual-browser` 真实浏览器矩阵 ubuntu/windows/macos-15-intel/macos-15 × Node 20/22/24,随 v0.5.0 tag 全绿)与 `Release`(tag 触发)均绿
229
239
  - 技能自检安装已在本机真实 `~/.rivet/skills/tianshu-mcp` 验证生效且幂等
230
- - npm 包名 `tianshu-mcp` 自 v0.1.1 起持续发布(当前 `0.3.4`)
240
+ - npm 包名 `tianshu-mcp` 自 v0.1.1 起持续发布(当前 `0.5.0`)
231
241
  - **天枢宿主真实接入(DoD #6)** ✅(2026-09-07,[host-integration-record.md](docs/host-integration-record.md))
232
242
  - 在真实 `D:\Tianshu` 桌面宿主 `mcp.servers` 配置本地模式 → sidecar `MCP: 2 servers connected, 10 tools`(含本 server 8 工具),spawn 子进程并 stdio 连通
233
243
  - 实测暴露并修复技能安装源路径 bug(fileURLToPath,提交 55cf2d0)
@@ -285,6 +295,17 @@ ZCode 提问、需要登录、旧实例无 CDP、系统权限不足,或自动
285
295
  - **projectPath 安全闸门**:realpath 归一 + 主目录/系统根目录拒绝 + 脏仓共处警示——见「路径安全闸门」
286
296
  - **修复**:`get_profiles` 漏列用户自定义 profile;zcode macOS `needsPermission` 误报;`normalizeProjectPath` 符号链接歧义;CDP 轮询在 renderer 替换/瞬时无响应时重连
287
297
  - **工程**:`execFileSync`/`spawnSync` 全量异步化(消除 Windows 轮询期事件循环冻结);验收命令有界并行(`verifyConcurrency`);测试套件 267s → 51s
298
+ - **M18 — 技能文档对齐 v0.4.0 工具面 + 贡献者名录 + v0.4.1**(2026-09-13)— **443 测试**
299
+ - `skills/tianshu-mcp/` 逐项补齐 v0.3.3 → v0.4.0 的工具面变化:projectPath 安全闸门、硬失败错误码速查表、`setup_recovery` 等待类型、codex-cli 无头路径、`ready`/`research` 状态语义、验收默认并行 2 与 `requireChanges` 门禁;usage-examples 新增错误码表、meta 字段全表、项目级验收配置模板与 `codex-cli` 示例
300
+ - 双语 README 新增贡献者名录(头像 + 名字,按首次参与顺序)
301
+ - 本版本**无代码行为变更**,升级无需迁移
302
+ - **M19 — 可选视觉验收模块 + v0.5.0**(2026-09-14)— **486 测试**
303
+ - **页面截图对比**:三种互斥页面来源(已有服务/命令启动/临时静态托管)、三种截图模式、声明式交互步骤、稳定化采样与显式屏蔽、pixelmatch 抗锯齿排除与连通区域标注;尺寸不一致直接失败
304
+ - **静态图片规格**:编码格式/扩展名一致性、完整解码、EXIF 方向归一宽高、宽高比/字节数/DPI/真实透明像素;不支持格式明确报告
305
+ - **基准两阶段与冻结**:候选准备 → 用户批准写入;缺基准不得判通过;自动返修禁止批准;任务动工前冻结配置与基准摘要并每轮核对
306
+ - **MCP/CLI**:新增 `prepare_visual_baseline` / `approve_visual_baseline` 与 `tianshu-mcp visual` 子命令族;CLI 在 stdio 连接前分流
307
+ - **报告与恢复**:`VerifyReport` 新增可选 `visual` 与离线 HTML(状态过滤、透明叠加、区域定位);视觉阻塞进 `needs_attention`,`rework_task` 先重新验收、仅真实缺陷才消耗返修预算
308
+ - **门禁**:CI 新增真实浏览器四系统三 Node 矩阵与生产包独立消费者验收;release 要求目标提交存在成功 CI,缺少 Gitee 凭据时阻塞不冒充成功
288
309
 
289
310
  ## Agent 适配现状
290
311
 
@@ -358,7 +379,7 @@ run_task(projectPath=/path/to/项目, agentId=codex-cli, task="任务书", autoV
358
379
  | 文档 | 内容 |
359
380
  |---|---|
360
381
  | [HANDOFF.md](HANDOFF.md) | 项目交接文档:当前状态快照、架构导览、硬性红线、已知限制、接手建议 |
361
- | [CHANGELOG.md](<CHANGELOG.md>) | 版本变更日志(v0.1.0 → v0.3.4) |
382
+ | [CHANGELOG.md](<CHANGELOG.md>) | 版本变更日志(v0.1.0 → v0.5.0) |
362
383
  | [CONTRIBUTING.md](CONTRIBUTING.md) | 开发环境、工程规范、提交与发布流程、如何新增 agent |
363
384
  | [SECURITY.md](SECURITY.md) | 安全模型(凭证零管理/命令白名单/进程与桌面自动化边界)与私密报告渠道 |
364
385
  | [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) | 贡献者行为准则 |
@@ -368,6 +389,23 @@ run_task(projectPath=/path/to/项目, agentId=codex-cli, task="任务书", autoV
368
389
  - **镜像仓库**:<https://gitee.com/lan0811/tianshu-mcp>(Gitee)
369
390
  - **问题反馈**:Bug / 功能请求走仓库 Issue 模板;安全漏洞请按 [SECURITY.md](SECURITY.md) 私密报告,**不要**开公开 Issue。
370
391
 
392
+ ### 贡献者
393
+
394
+ 感谢以下通过 Issue 与 PR 为本项目做出贡献的社区成员(按首次参与顺序排列):
395
+
396
+ <table>
397
+ <tr>
398
+ <td align="center"><a href="https://github.com/liuchsong"><img src="https://github.com/liuchsong.png" width="72" height="72" alt="liuchsong" /><br /><sub>liuchsong</sub></a></td>
399
+ <td align="center"><a href="https://github.com/a13612745638"><img src="https://github.com/a13612745638.png" width="72" height="72" alt="a13612745638" /><br /><sub>a13612745638</sub></a></td>
400
+ <td align="center"><a href="https://github.com/king195547"><img src="https://github.com/king195547.png" width="72" height="72" alt="king195547" /><br /><sub>king195547</sub></a></td>
401
+ </tr>
402
+ <tr>
403
+ <td align="center"><a href="https://github.com/zhaoxc857"><img src="https://github.com/zhaoxc857.png" width="72" height="72" alt="zhaoxc857" /><br /><sub>zhaoxc857</sub></a></td>
404
+ <td align="center"><a href="https://github.com/jian-in"><img src="https://github.com/jian-in.png" width="72" height="72" alt="jian-in" /><br /><sub>jian-in</sub></a></td>
405
+ <td align="center"><a href="https://github.com/huiliyi37"><img src="https://github.com/huiliyi37.png" width="72" height="72" alt="huiliyi37" /><br /><sub>huiliyi37</sub></a></td>
406
+ </tr>
407
+ </table>
408
+
371
409
  > 英文版对应文档见 [README.en.md](README.en.md)。
372
410
 
373
411
  ## 许可
@@ -9,6 +9,7 @@
9
9
  * 而 Codex 只能读项目工作区内的文件。
10
10
  */
11
11
  import path from "node:path";
12
+ import { visualEvidence } from "../../visual/report.js";
12
13
  import { mkdirp, writeTextAtomic } from "../../util/fs.js";
13
14
  import { fixPlanRelPath, fixPlanAbsPath } from "./input.js";
14
15
  /** 渲染修复计划正文(含失败证据、通过项、代码分析、修复要求) */
@@ -20,6 +21,7 @@ export function renderCodexFixPlan(input) {
20
21
  const a = report.analysis;
21
22
  const roundNo = input.round + 1;
22
23
  const lines = [
24
+ visualEvidence(report),
23
25
  `# Codex 修复计划(第 ${roundNo} 轮返修)`,
24
26
  "",
25
27
  `- 任务 ID:\`${input.taskId}\``,
@@ -59,7 +61,12 @@ export function renderCodexFixPlan(input) {
59
61
  lines.push("## 4. 代码分析结果", "");
60
62
  const changed = [...a.changedFiles, ...a.untrackedFiles];
61
63
  lines.push(`- 变更文件(${changed.length} 个):`);
62
- lines.push(changed.length ? changed.slice(0, 50).map((f) => ` - \`${f}\``).join("\n") : " (无变更)");
64
+ lines.push(changed.length
65
+ ? changed
66
+ .slice(0, 50)
67
+ .map((f) => ` - \`${f}\``)
68
+ .join("\n")
69
+ : " (无变更)");
63
70
  lines.push(`- diffstat:+${a.diffstat.totalAdd} -${a.diffstat.totalDel}`);
64
71
  const sig = a.signals;
65
72
  lines.push(`- 可疑标记:TODO/FIXME ${sig.todo} 处、console.log/debugger ${sig.consoleDebug} 处、注释代码块 ${sig.commentedBlock} 处、疑似密钥 ${sig.secretLike} 处`);
@@ -65,13 +65,18 @@ export class ZcodeBudget {
65
65
  }
66
66
  async run(operation, cap = Infinity) {
67
67
  const timeoutMs = this.remaining(cap);
68
+ const deadline = Math.min(Date.now() + timeoutMs, this.taskDeadline, this.bound ? Infinity : this.setupDeadline);
68
69
  const controller = new AbortController();
69
70
  let reject;
70
71
  const aborted = new Promise((_, fail) => {
71
72
  reject = fail;
72
73
  });
74
+ let timer;
73
75
  const stop = () => {
74
- controller.abort();
76
+ if (!this.opts.signal?.aborted && Date.now() < deadline) {
77
+ timer = setTimeout(stop, Math.max(1, deadline - Date.now()));
78
+ return;
79
+ }
75
80
  const reason = this.opts.signal?.aborted
76
81
  ? "aborted"
77
82
  : Date.now() >= this.taskDeadline
@@ -80,14 +85,21 @@ export class ZcodeBudget {
80
85
  ? "setup_recovery"
81
86
  : "operation_timeout";
82
87
  reject(new ZcodeBudgetError(reason, this.stage));
88
+ // Preserve the controlling deadline/cancellation reason before dependent CDP
89
+ // operations synchronously reject their own promises in abort listeners.
90
+ controller.abort();
83
91
  };
84
- const timer = setTimeout(stop, timeoutMs);
92
+ timer = setTimeout(stop, timeoutMs);
85
93
  this.opts.signal?.addEventListener("abort", stop, { once: true });
86
94
  try {
87
95
  const result = await Promise.race([operation(controller.signal, timeoutMs), aborted]);
88
96
  this.check();
89
97
  return result;
90
98
  }
99
+ catch (error) {
100
+ this.check();
101
+ throw error;
102
+ }
91
103
  finally {
92
104
  clearTimeout(timer);
93
105
  this.opts.signal?.removeEventListener("abort", stop);
@@ -3,6 +3,7 @@
3
3
  * 所有外部输入都经这里解析,失败给默认值或明确报错(开发计划 §13)。
4
4
  */
5
5
  import { z } from "zod";
6
+ import { VisualConfigSchema } from "../visual/schema.js";
6
7
  /* ---------------- 工具入参 ---------------- */
7
8
  const AbsPath = z.string().min(1, "projectPath 不能为空");
8
9
  /** TraeWork 面板模式(Work=自带 agent 循环;Code=纯编码;Design=设计) */
@@ -286,7 +287,8 @@ export const ProjectRecordSchema = z.object({
286
287
  export const ProjectsFileSchema = z.record(z.string().min(1), ProjectRecordSchema);
287
288
  /* ---------------- 项目内 .tianshu-mcp/acceptance.json ---------------- */
288
289
  export const AcceptanceConfigSchema = z.object({
289
- checks: z.array(AcceptanceCheckSchema).default([]),
290
+ checks: z.array(AcceptanceCheckSchema).optional(),
291
+ visual: VisualConfigSchema.optional(),
290
292
  requireChanges: z.boolean().default(true),
291
293
  /** 命令检查并行度:1=串行(与历史行为一致);缺省继承 server config.json 的 verifyConcurrency(默认 2)。越界值 clamp 到 1..4(不再株连整份 acceptance.json 失效) */
292
294
  verifyConcurrency: z
package/dist/index.js CHANGED
@@ -11,6 +11,11 @@ import path from "node:path";
11
11
  import { resolveDataHome } from "./config/store.js";
12
12
  import { Logger } from "./util/log.js";
13
13
  async function main() {
14
+ if (process.argv[2] === "visual") {
15
+ const { runVisualCli } = await import("./visual/cli.js");
16
+ await runVisualCli(process.argv.slice(3));
17
+ return;
18
+ }
14
19
  const home = resolveDataHome();
15
20
  const logger = await Logger.create(path.join(home, "logs"));
16
21
  const skipSkillInstall = process.argv.includes("--no-skill-install") || process.env.TIANSHU_MCP_NO_SKILL_INSTALL === "1";