@godv61/dsh-task-engine 0.22.7 → 0.23.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.
@@ -0,0 +1,34 @@
1
+ # 0.23.0 修改清单与发布说明
2
+
3
+ ## 本次实现
4
+
5
+ | 分类 | 问题 | 处理 |
6
+ |---|---|---|
7
+ | 安装 | 目录逐级浏览步骤多,Web host 原生选择器可能无 provider | 默认使用浏览器系统文件选择器,技能选目录,规则选 .md;高级主机路径入口保留 |
8
+ | 安装 | 写入前看不清目标与内容 | 预览名称、正文、数量、大小、路径、同名冲突,确认后写入 |
9
+ | 安全 | 路径、体积、链接与失败残留处理分散 | 公用导入模块,全包校验、摘要绑定、独占写入、失败清理 |
10
+ | 安全 | client workspace 只有路径黑名单 | 优先查询 Harness workspaceRegistry;未知路径拒绝,旧 host 使用已有严格注册策略 |
11
+ | 并发 | 读取内容后才读取文件版本仍可能覆盖并发修改 | 先读版本再读内容,逻辑 revision 和文件版本共同检查 |
12
+ | UI | 技能/规则两套重复界面,状态不统一 | 共用资源管理器,卡片、搜索、来源筛选、目标说明、加载/错误/成功状态 |
13
+ | UI | 删除动作不够明确 | 显示实际目标和永久删除说明,提供保留按钮 |
14
+ | UI | 弹窗键盘操作不完整 | Escape、焦点限制、关闭后恢复焦点 |
15
+ | UI | 台账难定位任务 | 标题/任务/分支搜索,风险/阶段筛选,验证/审核/更新时间 |
16
+ | 错误 | 保存和台账读取失败提示不全 | 捕获传输与校验错误、保存防重、读失败可见;损坏记录报错 |
17
+ | 文档 | 历史文案夸大防篡改保证 | 明确 hash、CAS、hook、workspace registry 各自能力与限制 |
18
+ | 发布 | 仓库与包元信息不完整 | repository/homepage/bugs、MIT LICENSE、Windows CI、发布包行为验证 |
19
+
20
+ ## 删减与保留
21
+
22
+ 删除重复技能/规则 UI 和旧目录复制实现;替换 14 条仅搜索复制器源码文本的旧断言。保留已有 Remote 安装方法以兼容旧客户端;保留高级主机目录导入和现有流程预设。未删除用户已有技能、规则、任务或流程配置。
23
+
24
+ ## 后续建议
25
+
26
+ 1. Harness 层:Typert 注入会话身份与授权 workspace;可信持久化签名与 CI 验证交付回执。注册工作区不能替代会话权限。
27
+ 2. 大包导入:改为分块上传、取消与进度、服务端临时包 TTL、并发与内存预算;当前 100 MB 是代码上限,不是远程实测容量承诺。
28
+ 3. 资源维护:记录来源与版本、显式升级/差异预览、备份与恢复;当前同名拒绝覆盖。
29
+ 4. 产品完善:全量中英语言字典、更多屏幕/浏览器/辅助技术验证,台账分页与完整任务数据 schema。
30
+ 5. 市场材料:公开源码、`dsh-plugin` topic、真实截图;符合仓库至少一天的条件后提交收录 PR。
31
+
32
+ ## 验证与发布
33
+
34
+ 以[测试报告](testing/0.23.0/测试报告.md)记录实际结果。源代码与 npm 发布各自验证;GitHub CI 未完成时不能称已通过。市场 PR 只添加 `data/plugins/godv61__dsh-task-engine.yml`,按[贡献指南](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/blob/main/contributing.md)检查,npm 关联来自 package.json repository。
@@ -0,0 +1,18 @@
1
+ # 安装技能和规则
2
+
3
+ 在 Harness 打开「工程流程」,先选择目标工作区,再进入「技能」或「规则」。
4
+
5
+ 1. 点「安装技能」,在系统文件选择器中选择技能文件夹;或点「安装规则」选择一个 Markdown 文件。
6
+ 2. 查看预览中的名称、正文、目标路径、文件数、体积和冲突提示。
7
+ 3. 选择项目或个人范围。切换范围后重新预览。
8
+ 4. 点「确认安装」。成功后列表刷新;同名资源拒绝覆盖。新安装的技能仍需在「流程配置」中挂到对应节点。
9
+
10
+ 技能根目录包含 UTF-8 的 `SKILL.md`,frontmatter 提供单行 `name` 和 `description`。名称使用小写字母、数字和连字符,例如 `code-check`。规则名称来自 `.md` 文件名,同样采用上述格式。支持 UTF-8 BOM 和 CRLF;其他文本编码请先转换。技能的脚本与附件保留原始字节,安装不会执行脚本。
11
+
12
+ 项目范围写入所选工作区 `.dsh/skills` 或 `.dsh/rules`;个人范围写入 `$DSH_HOME/skills` 或 `$DSH_HOME/rules`(默认用户主目录下 `.dsh`)。删除确认框显示实际路径;删除不经过回收站。
13
+
14
+ 浏览器选择器访问浏览器所在电脑的文件;高级目录模式访问 Harness 主机的目录。两者在远程部署中可能不是同一台电脑。浏览器不会暴露源文件绝对路径或符号链接元数据,不能宣称浏览器上传也完成了源链接检查。
15
+
16
+ 导入限制为 1000 文件、100 MB 总量、20 MB 单文件、20 层相对路径;清单和规则正文最多 1 MB。自动排除 `node_modules`、`.git`、`__pycache__`、`.venv`、`venv`、`.cache` 和 `.DS_Store`。禁止路径穿越、Windows ADS、保留名称、大小写重名及文件/目录冲突。高级目录扫描拒绝链接和特殊文件。合法包的上传仍会在内存中编码及校验,大包经远程网关的容量和并发性能未完成压力测试。
17
+
18
+ 预览不写入目标。确认时重新校验内容和目标的摘要,并使用独占创建避免覆盖现有资源;失败时清理本次新建的技能目录。此机制不构成针对具有同等主机文件权限的恶意进程的完整隔离。
@@ -0,0 +1,189 @@
1
+ # 0.23.0 测试执行记录
2
+
3
+ 日期:2026-09-15。Windows,Node 22.22.3,npm 10.9.8;插件基线 7f13fc6 加本次改动;Harness 源码 d347e70390(0.1.3-alpha.1),web profile,Codex 内置 Chromium 浏览器。
4
+
5
+ ## 执行命令
6
+
7
+ `npm run build`、`npm run typecheck`、`npm test` 均通过。为生成逐条记录,执行 `$env:DSH_TEST_DETAILS='1'; node .p0-test.mjs` 以及 `node --test .resource-test.mjs`;以下表由这次输出生成。
8
+
9
+ `npm run verify:package` 通过:npm pack、解包、8 个必备文件、排除源码与构建脚本、干净项目 npm 安装、主入口导入、客户端 ModuleLoader 注册、包内 P0 与资源测试、CLI 语法,共 18 个检查点。包内测试与源码测试重复覆盖,不另计为独立用例。该脚本的 CLI 检查仅检查语法,不能替代实际 CLI 启用流程。
10
+
11
+ ## 实机记录
12
+
13
+ | 编号 | 操作/测试数据 | 实际结果 | 状态 |
14
+ |---|---|---|---|
15
+ | UI-01 | 最终 tarball 经 dsh plugin --profile web add 安装并重启 3080 | 工作台加载,主机注册工作区读取成功 | 通过 |
16
+ | UI-02 | 安装 codex-ui-review-skill 目录 | 系统 filechooser 接收目录,预览 2 文件/162 B,正文不含 frontmatter | 通过 |
17
+ | UI-03 | 预览后、确认前检查目标 | Test-Path 为 False;预览没有落盘 | 通过 |
18
+ | UI-04 | 确认项目技能安装 | 成功提示与列表更新,附件 SHA-256 与源相同 | 通过 |
19
+ | UI-05 | 重复选择同名技能 | 冲突提示出现,确认安装按钮 disabled | 通过 |
20
+ | UI-06 | 安装 codex-ui-review-rule.md,切换个人范围 | 预览目标切换为个人规则目录,1 文件/26 B,确认后落盘并显示个人来源 | 通过 |
21
+ | UI-07 | 搜索测试技能,打开删除框后选择保留 | 匹配结果正确,目标/永久删除说明可见,取消未删除 | 通过(本次早期同版构建) |
22
+ | UI-08 | 安装弹窗按 Escape | 弹窗关闭,返回工作台 | 通过 |
23
+ | UI-09 | 台账读取既有任务,选择高风险 | 显示任务验证/审核结果;无匹配时显示调整筛选提示 | 通过 |
24
+ | UI-10 | 420×850 视口查看技能页 | 卡片单列、标签与工作区选择换行、按钮可见,随后恢复视口 | 通过 |
25
+ | UI-11 | 流程配置页读取 | 显示有效标准预设与绑定,不改写用户配置 | 通过 |
26
+
27
+ ## 自动化明细
28
+
29
+ P0 是 125 条验收断言,包含部分历史源码文本断言,不等同于 125 个独立端到端场景。资源集合包含 18 个 Node test 用例。P0 没有每条耗时记录;未伪造时间。
30
+
31
+ | 用例标识 | 状态 | 耗时 | 失败/错误原因 | 证据 |
32
+ |---|---|---:|---|---|
33
+ | P0-1:standard satisfies high-risk capabilities | 通过 | 未单独计时 | 无 | P0 明细输出 |
34
+ | P0-2:agile lacks a high-risk capability | 通过 | 未单独计时 | 无 | P0 明细输出 |
35
+ | P0-3:minimal lacks a high-risk capability | 通过 | 未单独计时 | 无 | P0 明细输出 |
36
+ | P0-4:preset carries a version | 通过 | 未单独计时 | 无 | P0 明细输出 |
37
+ | P0-5:unknown flow returns UNKNOWN_FLOW | 通过 | 未单独计时 | 无 | P0 明细输出 |
38
+ | P0-6:known flow list is surfaced | 通过 | 未单独计时 | 无 | P0 明细输出 |
39
+ | P0-7:emptying a stage override keeps the core rule | 通过 | 未单独计时 | 无 | P0 明细输出 |
40
+ | P0-8:newTask stores the frozen snapshot | 通过 | 未单独计时 | 无 | P0 明细输出 |
41
+ | P0-9:newTask starts at the frozen start stage | 通过 | 未单独计时 | 无 | P0 明细输出 |
42
+ | P0-10:high_risk on minimal is rejected (got: high_risk task cannot run on flow "minimal" — it lacks the required capabilities (verification_gate, file_scope, review_gate). Use the standard flow or lower the task risk.) | 通过 | 未单独计时 | 无 | P0 明细输出 |
43
+ | P0-11:standard create starts at 需求评审 | 通过 | 未单独计时 | 无 | P0 明细输出 |
44
+ | P0-12:status re-reads the frozen snapshot | 通过 | 未单独计时 | 无 | P0 明细输出 |
45
+ | P0-13:gates come from the frozen standard flow, not the live minimal flow | 通过 | 未单独计时 | 无 | P0 明细输出 |
46
+ | P0-14:create on an unknown flow fails closed (got: invalid .dsh/eng.json — fix the project config first: | 通过 | 未单独计时 | 无 | P0 明细输出 |
47
+ | P0-15:eng.json without a flow field is a config error (got: invalid .dsh/eng.json — fix the project config first: | 通过 | 未单独计时 | 无 | P0 明细输出 |
48
+ | P0-16:inspect on empty project prompts a scan | 通过 | 未单独计时 | 无 | P0 明细输出 |
49
+ | P0-17:propose previews without writing | 通过 | 未单独计时 | 无 | P0 明细输出 |
50
+ | P0-18:propose writes nothing | 通过 | 未单独计时 | 无 | P0 明细输出 |
51
+ | P0-19:apply writes the file | 通过 | 未单独计时 | 无 | P0 明细输出 |
52
+ | P0-20:apply persisted the draft | 通过 | 未单独计时 | 无 | P0 明细输出 |
53
+ | P0-21:propose returns the existing-file hash when the file exists | 通过 | 未单独计时 | 无 | P0 明细输出 |
54
+ | P0-22:apply without existing_hash on an existing file is rejected (got: init apply requires existing_hash returned by propose when AGENTS.md exists — re-propose to obtain it) | 通过 | 未单独计时 | 无 | P0 明细输出 |
55
+ | P0-23:apply with a stale existing_hash is rejected (TOCTOU) (got: AGENTS.md changed since propose (existing_hash mismatch) — re-inspect and re-propose before overwriting) | 通过 | 未单独计时 | 无 | P0 明细输出 |
56
+ | P0-24:apply without overwrite on an existing file is rejected (got: AGENTS.md already exists (2 lines) and is protected. Inspect via init phase=inspect, merge, then resubmit with phase=apply plus overwrite: true (human approval).) | 通过 | 未单独计时 | 无 | P0 明细输出 |
57
+ | P0-25:overwrite requires an approval service (got: overwriting the protected AGENTS.md requires human approval, but the approval service is unavailable) | 通过 | 未单独计时 | 无 | P0 明细输出 |
58
+ | P0-26:apply without expected_hash is rejected (got: init apply requires expected_hash returned by propose — re-propose to obtain it) | 通过 | 未单独计时 | 无 | P0 明细输出 |
59
+ | P0-27:bundled security-redlines exists as expected | 通过 | 未单独计时 | 无 | P0 明细输出 |
60
+ | P0-28:security-redlines is disclosed at the start stage | 通过 | 未单独计时 | 无 | P0 明细输出 |
61
+ | P0-29:a project shadow of a core rule is ignored | 通过 | 未单独计时 | 无 | P0 明细输出 |
62
+ | P0-30:the bundled core rule body wins over a shadow | 通过 | 未单独计时 | 无 | P0 明细输出 |
63
+ | P0-31:inspect reads the session workspace AGENTS.md | 通过 | 未单独计时 | 无 | P0 明细输出 |
64
+ | P0-32:inspect does not read the harness repo AGENTS.md | 通过 | 未单独计时 | 无 | P0 明细输出 |
65
+ | P0-33:task record lands in the session workspace | 通过 | 未单独计时 | 无 | P0 明细输出 |
66
+ | P0-34:task record does not land in the backend base | 通过 | 未单独计时 | 无 | P0 明细输出 |
67
+ | P0-35:cross-stage duplicate artifact id is rejected | 通过 | 未单独计时 | 无 | P0 明细输出 |
68
+ | P0-36:recording an artifact at a non-owning stage is rejected (got: artifact "design" belongs to stage "设计", but the task is at "需求评审" — record it at its owning stage) | 通过 | 未单独计时 | 无 | P0 明细输出 |
69
+ | P0-37:high_risk with text-only evidence is blocked (no command receipt) | 通过 | 未单独计时 | 无 | P0 明细输出 |
70
+ | P0-38:high_risk with an exit-0 receipt passes the verified gate | 通过 | 未单独计时 | 无 | P0 明细输出 |
71
+ | P0-39:high_risk with a non-zero exit receipt is blocked | 通过 | 未单独计时 | 无 | P0 明细输出 |
72
+ | P0-40:high_risk with a timed-out receipt is blocked | 通过 | 未单独计时 | 无 | P0 明细输出 |
73
+ | P0-41:high_risk with an aborted receipt is blocked | 通过 | 未单独计时 | 无 | P0 明细输出 |
74
+ | P0-42:standard summary yields its task id | 通过 | 未单独计时 | 无 | P0 明细输出 |
75
+ | P0-43:item-label summary yields its task id | 通过 | 未单独计时 | 无 | P0 明细输出 |
76
+ | P0-44:non-matching summary yields no task id | 通过 | 未单独计时 | 无 | P0 明细输出 |
77
+ | P0-45:pattern-less flow yields no task id | 通过 | 未单独计时 | 无 | P0 明细输出 |
78
+ | P0-46:task record and eng.json do not violate file scope | 通过 | 未单独计时 | 无 | P0 明细输出 |
79
+ | P0-47:an out-of-scope code file is still flagged | 通过 | 未单独计时 | 无 | P0 明细输出 |
80
+ | P0-48:hook disables git octal path quoting | 通过 | 未单独计时 | 无 | P0 明细输出 |
81
+ | P0-49:hook reads NUL-separated raw-byte paths | 通过 | 未单独计时 | 无 | P0 明细输出 |
82
+ | P0-50:hook includes deletions and type changes in the scope check | 通过 | 未单独计时 | 无 | P0 明细输出 |
83
+ | P0-51:hook checks the task frozen flow snapshot | 通过 | 未单独计时 | 无 | P0 明细输出 |
84
+ | P0-52:hook extracts the task id independent of the live config | 通过 | 未单独计时 | 无 | P0 明细输出 |
85
+ | P0-53:hook bundles the single source (workflows.ts), not a hand mirror | 通过 | 未单独计时 | 无 | P0 明细输出 |
86
+ | P0-54:workbench writeInit refuses to overwrite without an explicit intent | 通过 | 未单独计时 | 无 | P0 明细输出 |
87
+ | P0-55:writeInit request carries an overwrite field | 通过 | 未单独计时 | 无 | P0 明细输出 |
88
+ | P0-56:node marker resolves to node | 通过 | 未单独计时 | 无 | P0 明细输出 |
89
+ | P0-57:root discovery climbs to the package.json directory | 通过 | 未单独计时 | 无 | P0 明细输出 |
90
+ | P0-58:pom.xml resolves to java | 通过 | 未单独计时 | 无 | P0 明细输出 |
91
+ | P0-59:go.mod resolves to go | 通过 | 未单独计时 | 无 | P0 明细输出 |
92
+ | P0-60:Cargo.toml resolves to rust | 通过 | 未单独计时 | 无 | P0 明细输出 |
93
+ | P0-61:requirements.txt resolves to python | 通过 | 未单独计时 | 无 | P0 明细输出 |
94
+ | P0-62:empty tree reports unknown type | 通过 | 未单独计时 | 无 | P0 明细输出 |
95
+ | P0-63:root discovery falls back to the start directory | 通过 | 未单独计时 | 无 | P0 明细输出 |
96
+ | P0-64:mixed tree reports unknown, never a silent single-language guess | 通过 | 未单独计时 | 无 | P0 明细输出 |
97
+ | P0-65:root discovery stops at the git repository | 通过 | 未单独计时 | 无 | P0 明细输出 |
98
+ | P0-66:node default verify command | 通过 | 未单独计时 | 无 | P0 明细输出 |
99
+ | P0-67:java default verify command | 通过 | 未单独计时 | 无 | P0 明细输出 |
100
+ | P0-68:go default verify command | 通过 | 未单独计时 | 无 | P0 明细输出 |
101
+ | P0-69:unknown type has no default command | 通过 | 未单独计时 | 无 | P0 明细输出 |
102
+ | P0-70:governance files are recognized as present | 通过 | 未单独计时 | 无 | P0 明细输出 |
103
+ | P0-71:absent governance files are not listed | 通过 | 未单独计时 | 无 | P0 明细输出 |
104
+ | P0-72:init write escaping the root is rejected (got: write target D:\outside.txt escapes the project root D:\repo) | 通过 | 未单独计时 | 无 | P0 明细输出 |
105
+ | P0-73:absolute target outside the root is rejected (got: write target C:\elsewhere\x.txt escapes the project root D:\repo) | 通过 | 未单独计时 | 无 | P0 明细输出 |
106
+ | P0-74:hook bundles the risk policy table (single source) | 通过 | 未单独计时 | 无 | P0 明细输出 |
107
+ | P0-75:hook requires high_risk before touching sensitive paths | 通过 | 未单独计时 | 无 | P0 明细输出 |
108
+ | P0-76:project rules list from .dsh/rules/*.md | 通过 | 未单独计时 | 无 | P0 明细输出 |
109
+ | P0-77:project skills list only dirs carrying SKILL.md | 通过 | 未单独计时 | 无 | P0 明细输出 |
110
+ | P0-78:hashConfig is a deterministic sha256 | 通过 | 未单独计时 | 无 | P0 明细输出 |
111
+ | P0-79:editing the frozen config changes the hash | 通过 | 未单独计时 | 无 | P0 明细输出 |
112
+ | P0-80:status on a tampered snapshot is rejected (got: task "HASH-1" snapshot hash mismatch — the frozen workflow config was edited after creation. Restore the original record or recreate the task; the gate refuses to run on a tampered snapshot.) | 通过 | 未单独计时 | 无 | P0 明细输出 |
113
+ | P0-81:hook reuses the single hashConfig source | 通过 | 未单独计时 | 无 | P0 明细输出 |
114
+ | P0-82:hook bundles the sha256 snapshot check | 通过 | 未单独计时 | 无 | P0 明细输出 |
115
+ | P0-83:verify_hook reports an absent hook | 通过 | 未单独计时 | 无 | P0 明细输出 |
116
+ | P0-84:verify_hook passes on the bundled hook | 通过 | 未单独计时 | 无 | P0 明细输出 |
117
+ | P0-85:verify_hook rejects a tampered hook (got: hook integrity FAILED — .git/hooks/commit-msg differs from the bundled gate; reinstall with install_hook) | 通过 | 未单独计时 | 无 | P0 明细输出 |
118
+ | P0-86:downgrade without an approval service is rejected (got: downgrading a high_risk task requires human approval, but the approval service is unavailable) | 通过 | 未单独计时 | 无 | P0 明细输出 |
119
+ | P0-87:same-risk set_risk is a no-op | 通过 | 未单独计时 | 无 | P0 明细输出 |
120
+ | P0-88:approved downgrade succeeds | 通过 | 未单独计时 | 无 | P0 明细输出 |
121
+ | P0-89:downgrade is recorded in the audit trail | 通过 | 未单独计时 | 无 | P0 明细输出 |
122
+ | P0-90:fresh task shows no bindings drift | 通过 | 未单独计时 | 无 | P0 明细输出 |
123
+ | P0-91:create records the bundled-rules fingerprint | 通过 | 未单独计时 | 无 | P0 明细输出 |
124
+ | P0-92:verify falls back to the eng.json command and fails loud without a shell service (got: verify 带 command 需要 host 提供 shell 服务(用于跑真实验证命令),但当前未挂载) | 通过 | 未单独计时 | 无 | P0 明细输出 |
125
+ | P0-93:verify falls back to the language default (node → npm test) and fails loud without a shell service (got: verify 带 command 需要 host 提供 shell 服务(用于跑真实验证命令),但当前未挂载) | 通过 | 未单独计时 | 无 | P0 明细输出 |
126
+ | P0-94:unknown-type verify keeps the legacy self-reported path | 通过 | 未单独计时 | 无 | P0 明细输出 |
127
+ | P0-95:two tasks in one repo advance independently | 通过 | 未单独计时 | 无 | P0 明细输出 |
128
+ | P0-96:propose returns the content hash | 通过 | 未单独计时 | 无 | P0 明细输出 |
129
+ | P0-97:apply with a mismatched hash is rejected (got: init content changed since propose (expected_hash mismatch) — resubmit the identical proposed content) | 通过 | 未单独计时 | 无 | P0 明细输出 |
130
+ | P0-98:apply with the matching hash writes the file | 通过 | 未单独计时 | 无 | P0 明细输出 |
131
+ | P0-99:project binding dir (.dsh/rules, .dsh/skills) stays committable by normal tasks | 通过 | 未单独计时 | 无 | P0 明细输出 |
132
+ | P0-100:env files remain sensitive | 通过 | 未单独计时 | 无 | P0 明细输出 |
133
+ | P0-101:dev_task writes carry the sandbox mode (default workspace-write) | 通过 | 未单独计时 | 无 | P0 明细输出 |
134
+ | P0-102:dev_task writes carry the session workspace root so in-workspace paths are never misjudged as out-of-root | 通过 | 未单独计时 | 无 | P0 明细输出 |
135
+ | P0-103:escalation without a justification is rejected (got: invalid escalation: sandbox_permissions requires a justification) | 通过 | 未单独计时 | 无 | P0 明细输出 |
136
+ | P0-104:approved escalation upgrades the per-call write mode | 通过 | 未单独计时 | 无 | P0 明细输出 |
137
+ | P0-105:escalation without an approval service fails closed (got: sandbox escalation to danger-full-access requires human approval, but the approval service is unavailable) | 通过 | 未单独计时 | 无 | P0 明细输出 |
138
+ | P0-106:raising risk on a minimal flow is rejected (same gate as create) (got: cannot raise risk to high_risk on flow "minimal" — it lacks the required capabilities (verification_gate, file_scope, review_gate). Use the standard flow.) | 通过 | 未单独计时 | 无 | P0 明细输出 |
139
+ | P0-107:raising risk on the standard flow succeeds | 通过 | 未单独计时 | 无 | P0 明细输出 |
140
+ | P0-108:remote rejects non-absolute workspace paths | 通过 | 未单独计时 | 无 | P0 明细输出 |
141
+ | P0-109:remote rejects system-wide roots | 通过 | 未单独计时 | 无 | P0 明细输出 |
142
+ | P0-110:bare verify ran the default command | 通过 | 未单独计时 | 无 | P0 明细输出 |
143
+ | P0-111:verify ran in the recorded project root, not the session cwd | 通过 | 未单独计时 | 无 | P0 明细输出 |
144
+ | P0-112:receipt binds the recorded project root | 通过 | 未单独计时 | 无 | P0 明细输出 |
145
+ | P0-113:revision increments on every write | 通过 | 未单独计时 | 无 | P0 明细输出 |
146
+ | P0-114:concurrent-write CAS guard is present | 通过 | 未单独计时 | 无 | P0 明细输出 |
147
+ | P0-115:absolute workspace passes | 通过 | 未单独计时 | 无 | P0 明细输出 |
148
+ | P0-116:trailing slash is normalized | 通过 | 未单独计时 | 无 | P0 明细输出 |
149
+ | P0-117:relative path is rejected (got: task-engine: workspace path must be absolute: relative/path) | 通过 | 未单独计时 | 无 | P0 明细输出 |
150
+ | P0-118:system root is rejected (got: task-engine: path is not an allowed workspace: C:/Windows/system32) | 通过 | 未单独计时 | 无 | P0 明细输出 |
151
+ | P0-119:case variant of a system root is rejected (got: task-engine: path is not an allowed workspace: c:/windows) | 通过 | 未单独计时 | 无 | P0 明细输出 |
152
+ | P0-120:registered workspace passes under any case | 通过 | 未单独计时 | 无 | P0 明细输出 |
153
+ | P0-121:unregistered workspace is rejected once the registry is active (got: task-engine: workspace not registered on this host: D:/other-project) | 通过 | 未单独计时 | 无 | P0 明细输出 |
154
+ | P0-122:strict mode keeps rejecting unregistered workspaces (got: task-engine: workspace not registered on this host: D:/still-unregistered) | 通过 | 未单独计时 | 无 | P0 明细输出 |
155
+ | P0-123:strict mode still admits registered workspaces | 通过 | 未单独计时 | 无 | P0 明细输出 |
156
+ | P0-124:CAS rejects writes when version changes after the content read (got: task "CAS-RACE" changed concurrently (file version moved) — reload status and retry this operation) | 通过 | 未单独计时 | 无 | P0 明细输出 |
157
+ | P0-125:CAS preserves the concurrent writer record | 通过 | 未单独计时 | 无 | P0 明细输出 |
158
+ | Import-1:preview has no filesystem side effects and reports exact bytes | 通过 | 11.0717 ms | 无 | Node TAP 输出 |
159
+ | Import-2:confirmed install preserves binary assets and refuses duplicates | 通过 | 8.0443 ms | 无 | Node TAP 输出 |
160
+ | Import-3:changed content and changed installation target invalidate preview | 通过 | 2.3299 ms | 无 | Node TAP 输出 |
161
+ | Import-4:path traversal, Windows ADS and reserved names are rejected | 通过 | 1.572 ms | 无 | Node TAP 输出 |
162
+ | Import-5:case-colliding filenames are rejected | 通过 | 1.3899 ms | 无 | Node TAP 输出 |
163
+ | Import-6:bundled names and ambiguous containers are rejected | 通过 | 0.8907 ms | 无 | Node TAP 输出 |
164
+ | Import-7:single-file rule accepts UTF-8 BOM and CRLF; empty rules are refused | 通过 | 3.1442 ms | 无 | Node TAP 输出 |
165
+ | Import-8:file and directory prefix conflicts fail during preview | 通过 | 0.7124 ms | 无 | Node TAP 输出 |
166
+ | Import-9:failed installation removes only its own incomplete directory | 通过 | 6.7741 ms | 无 | Node TAP 输出 |
167
+ | Import-10:host directory scanner resolves one container child and excludes caches | 通过 | 5.6005 ms | 无 | Node TAP 输出 |
168
+ | Import-11:host scanner rejects symlink or junction source paths | 通过 | 2.4246 ms | 无 | Node TAP 输出 |
169
+ | Import-12:deep directories and oversized files fail before installation | 通过 | 21.9509 ms | 无 | Node TAP 输出 |
170
+ | Import-13:invalid UTF-8, encoding and absent source directories report errors | 通过 | 1.2419 ms | 无 | Node TAP 输出 |
171
+ | Import-14:registered host workspace wins over client spelling; unknown paths fail | 通过 | 2.6087 ms | 无 | Node TAP 输出 |
172
+ | Import-15:legacy host retains its explicit workspace policy | 通过 | 0.214 ms | 无 | Node TAP 输出 |
173
+ | Import-16:host registry failures are not downgraded to legacy permissions | 通过 | 0.1672 ms | 无 | Node TAP 输出 |
174
+ | Import-17:ledger shows absent storage as empty and propagates access errors | 通过 | 18.696 ms | 无 | Node TAP 输出 |
175
+ | Import-18:ledger rejects malformed records instead of pretending there are no tasks | 通过 | 0.3443 ms | 无 | Node TAP 输出 |
176
+
177
+ ## 缺陷与复测
178
+
179
+ 首次大文件边界测试触发 Base64 正则回溯导致 RangeError;已改用 Buffer 解码后规范编码比对,本次 Import-12 通过。目录中同时含文件 a 与 a/b 的输入现于预览拒绝(Import-8);磁盘故障回滚通过独立写入故障注入覆盖(Import-9),且验证兄弟文件保留。任务 CAS 测试在读取期间注入另一写者,拒绝覆盖并保留并发内容。
180
+
181
+ ## 数据与环境
182
+
183
+ 单元测试使用 mkdtemp 独立临时目录并在 teardown 删除;文件写入故障注入在 finally 恢复 fs 方法。实机只添加 codex-ui-review-skill 与 codex-ui-review-rule.md 两个一次性测试资源,清理结果见报告。用户原有 software-testing 资源和任务未修改。
184
+
185
+ profile 的 pnpm peers check 报缺少五个 Harness peer;实际运行由 Harness 源码环境提供,工作台功能通过。干净 npm 项目自动解析 peer 安装通过。显式添加已实测 0.1.3-alpha.1 预发布分支,避免 semver 将其排除。没有通过关闭依赖安全策略来安装。
186
+
187
+ ## 首轮 CI 差异与修复
188
+
189
+ GitHub run 34950017436:Node 22 与 24 的安装、类型检查和 npm test 均通过;Node 24 发布包脚本错误地把测试成功输出判为失败,Node 22 发布包任务随后被矩阵 fail-fast 取消。原因是检查脚本依赖 `# fail 0`,却没有固定 Node test reporter,Node 24 默认输出格式与本机不同。修复为显式 `--test-reporter=tap`;矩阵关闭 fail-fast 以保留各版本完整结果,没有跳过测试或降低通过条件。复验状态见 GitHub Actions。
@@ -0,0 +1,42 @@
1
+ # 0.23.0 测试报告
2
+
3
+ 本地发布候选验证通过。范围为资源导入、工作台交互、工作区注册路径、任务并发写入和 npm 包入口;不代表完成所有模型驱动的需求到提交流程、全部平台验证或安全认证。
4
+
5
+ 环境与逐条结果见[测试执行记录](测试执行记录.md)。
6
+
7
+ | 验证集 | 已执行 | 通过 | 失败 | 跳过 |
8
+ |---|---:|---:|---:|---:|
9
+ | P0 验收断言(含部分静态断言) | 125 | 125 | 0 | 0 |
10
+ | Node 行为用例 | 18 | 18 | 0 | 0 |
11
+ | 实机交互场景 | 11 | 11 | 0 | 0 |
12
+ | 发布包检查点 | 18 | 18 | 0 | 0 |
13
+ | 构建/host+client 类型检查命令 | 2 | 2 | 0 | 0 |
14
+
15
+ 各组包含重复验证,不相加为独立测试总数。源码和实际安装包内的行为测试均通过。首次 Base64 大包测试发现并修复了栈溢出;最终无失败。
16
+
17
+ ## 需求追踪
18
+
19
+ | 需求 | 证据 |
20
+ |---|---|
21
+ | 系统文件选择与项目/个人安装 | UI-02~06,Import-1~7 |
22
+ | 安装前校验、拒绝覆盖与失败清理 | Import-1~13,UI-03~05 |
23
+ | 工作区信任来源 | Import-14~16,UI-01 |
24
+ | CAS 竞态 | P0 明细中的读取期间并发写入/保留另一写者断言 |
25
+ | 窄屏、筛选与弹窗 | UI-07~11 |
26
+ | 损坏/不可读任务可见 | Import-17~18 |
27
+ | 真实 npm 包可安装、入口可用 | 发布包 18 个检查点 |
28
+
29
+ ## 剩余限制
30
+
31
+ - 主机工作区注册不等于会话级授权;本地任务 JSON 没有签名。需要 Harness 调用上下文与可信存储支持才能完成多用户边界。
32
+ - 整包内存上传未做 100 MB 远程网关/并发压力测试;浏览器源符号链接不可辨识;未覆盖断电中断和恶意同权限进程抢改目录。
33
+ - 实机为 Windows/Chromium、当前 Harness 源码;没有执行 macOS/Linux、其他浏览器或真实模型从建任务到提交的全流程。本地 hook 不能替代服务端 CI 验证。
34
+ - 原生选择器取消、完整屏幕阅读器与深色主题尚未形成专门验收矩阵;全量语言字典、资源升级和备份属于后续建议。
35
+ - profile 缺少单独声明的 Harness peer 会产生警告;源码主机与干净 npm 安装验证都通过,不能推断所有第三方 profile 都兼容。
36
+ - GitHub Actions 与 npm 公网发布状态单独记录,不以本地成功代替。
37
+
38
+ ## 清理与发布状态
39
+
40
+ 实机技能附件与规则文件均核对 SHA-256 一致,两个一次性资源已清理并确认目标不存在;源码 fixture 留在评测工作目录,不进入发布仓库。源历史 163 个 blob 和当前待发布文件的常见凭据模式扫描无命中;模式扫描不保证发现所有形式的秘密。
41
+
42
+ 完整修改与后续建议见[发布说明](../../release-0.23.0.md)。收录指南要求仓库创建满一天,申请材料已准备,提交与合并应分别确认。