dsh-flakefinder 0.3.4 → 0.4.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 +21 -0
- package/README.en.md +30 -41
- package/README.md +27 -95
- package/docs/USAGE.en.md +56 -0
- package/docs/USAGE.md +109 -0
- package/docs/VALIDATION.md +15 -0
- package/lib/config.d.ts +1 -0
- package/lib/config.js +2 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +3 -1
- package/lib/runner.d.ts +3 -1
- package/lib/runner.js +8 -4
- package/lib/store.js +85 -52
- package/lib/tools.js +18 -3
- package/lib/update-client.js +408 -0
- package/package.json +24 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 更新记录
|
|
2
|
+
|
|
3
|
+
[返回简介](README.md) · [使用说明](docs/USAGE.md) · [验证记录](docs/VALIDATION.md)
|
|
4
|
+
|
|
5
|
+
## 0.4.0 (2026-10-26)
|
|
6
|
+
|
|
7
|
+
- Add this plugin’s own update controls and independent preferences. Automatic installation stays off until explicitly enabled.
|
|
8
|
+
- Confirm manual installs, preserve local sources and disabled state, pause for tasks or unsaved changes, and use native DSH recovery without forced restarts.
|
|
9
|
+
- Require the public DSH 0.2.1-rc.3 update APIs; Suite components remain managed through Suite.
|
|
10
|
+
|
|
11
|
+
## 0.3.5 (2026-10-05)
|
|
12
|
+
|
|
13
|
+
- 测试进程和隔离清单使用当前会话工作区,取消后不再执行后续轮次或保存成功记录;跨实例锁定历史与隔离清单,损坏文件保持原样。
|
|
14
|
+
|
|
15
|
+
## 0.3.4 (2026-09-28)
|
|
16
|
+
|
|
17
|
+
- 更新官方 Harness 0.2.0-rc.1 的兼容声明和共同加载验证;运行时代码未变。验证范围见[验证记录](docs/VALIDATION.md)。
|
|
18
|
+
|
|
19
|
+
## 更早的改动
|
|
20
|
+
|
|
21
|
+
完整历史可查阅 [GitHub 提交记录](https://github.com/STARDUSTLC666/dsh-flakefinder/commits/master)。
|
package/README.en.md
CHANGED
|
@@ -1,65 +1,54 @@
|
|
|
1
1
|
# dsh-flakefinder
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[中文](README.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Repeat test runs to identify intermittent failures and keep investigation history.
|
|
8
8
|
|
|
9
|
-
[](https://www.npmjs.com/package/dsh-flakefinder) [](https://www.npmjs.com/package/dsh-flakefinder)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Feedback and contributions are welcome: report [issues](https://github.com/STARDUSTLC666/dsh-flakefinder/issues) or submit [pull requests](https://github.com/STARDUSTLC666/dsh-flakefinder/pulls).
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
| :-- | :-- | :-- |
|
|
15
|
-
| `flaky_detect` | Repeat tests N times and classify stable-pass / stable-fail / flaky | history only |
|
|
16
|
-
| `flaky_history` | Query detection history, filter by target | no |
|
|
17
|
-
| `flaky_report` | Combine quarantine manifest and history into a report | no |
|
|
18
|
-
| `flaky_quarantine` | Write flaky cases to `.flakefinder.json` | yes (approval) |
|
|
19
|
-
| `flaky_clear` | Remove recovered cases from the manifest | yes (approval) |
|
|
13
|
+
## What it does
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Validation host: Harness `0.2.0-rc.1` built from official sources (commit `407e65c8`) with Node `24.16.0` on 2026-09-28. All 44 plugin tests pass in an isolated environment; all 18 plugins mount together in one host registering 6 tools, with tool schemas and health-check contracts passing. No live ports or external services were exercised in this round.
|
|
26
|
-
|
|
27
|
-
2026-09-13 fix: retain the service receiver when calling `subprocess.spawn`, preventing failures caused by passing the method as an unbound callback. Verified with official `0.1.5-rc.1` and `0.1.5-rc.2` on Node `24.16.0`. `flaky_detect` runs three real Node test processes through the host subprocess service and returns `stable-pass`.
|
|
15
|
+
- Support Vitest, Jest, pytest and node:test.
|
|
16
|
+
- Track repeated run results and failure history.
|
|
17
|
+
- Generate and maintain a quarantine list.
|
|
28
18
|
|
|
29
19
|
## Install
|
|
30
20
|
|
|
21
|
+
In DSH Desktop, install `dsh-flakefinder` from the Plugins panel. If the bundled dsh command is available:
|
|
22
|
+
|
|
31
23
|
```bash
|
|
32
|
-
dsh plugin --profile
|
|
24
|
+
dsh plugin --profile desktop add dsh-flakefinder
|
|
33
25
|
```
|
|
34
26
|
|
|
35
|
-
|
|
27
|
+
For the web version, replace `desktop` with `web`. Restart DSH after installation.
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
dsh plugin --profile web remove dsh-flakefinder
|
|
39
|
-
```
|
|
29
|
+
## Start using it
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
Ask: “Run this test group ten times, identify intermittent failures and summarize the differences.”
|
|
42
32
|
|
|
33
|
+
## Requirements and configuration
|
|
43
34
|
|
|
44
|
-
|
|
35
|
+
Requires a working test command in your project. Quarantine records and gates follow project configuration.
|
|
45
36
|
|
|
46
|
-
|
|
47
|
-
User: src/checkout.test.ts keeps failing recently, is it real?
|
|
48
|
-
Agent:
|
|
49
|
-
flaky_detect(target="src/checkout.test.ts", runs=5)
|
|
50
|
-
-> verdict: flaky (3/5 passed; failures cluster on fake timers)
|
|
51
|
-
-> flaky_quarantine(tests=["src/checkout.test.ts > timer restore"], reason="timer race")
|
|
52
|
-
```
|
|
37
|
+
Detailed configuration, tool arguments and troubleshooting are in the [usage guide](docs/USAGE.en.md). For standalone development, follow the Node requirement in [package.json](package.json).
|
|
53
38
|
|
|
54
|
-
##
|
|
39
|
+
## Documentation
|
|
55
40
|
|
|
56
|
-
|
|
41
|
+
- [Usage and troubleshooting](docs/USAGE.en.md)
|
|
42
|
+
- [Changelog](CHANGELOG.md)
|
|
43
|
+
- [Validation scope and history](docs/VALIDATION.md)
|
|
44
|
+
- [Report a problem or suggest a feature](https://github.com/STARDUSTLC666/dsh-flakefinder/issues)
|
|
57
45
|
|
|
58
|
-
##
|
|
46
|
+
## Plugin updates
|
|
59
47
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
48
|
+
Requires DSH 0.2.1-rc.3 or newer. Each plugin provides its own check, release-note and confirmed-install controls on its page or in settings. Preferences are independent. Automatic checks are on by default; **automatic installation is off by default**. Explicitly enabled automatic updates only install compatible stable patches while idle with no unsaved changes. Disable, defer or ignore reminders per plugin. DSH is never restarted or upgraded automatically, and local-source installs are preserved. Suite components clearly direct updates through Suite.
|
|
49
|
+
|
|
50
|
+
Older releases need one manual update in native plugin management to acquire these controls. Publishing to npm does not replace an existing user installation.
|
|
51
|
+
|
|
52
|
+
## License
|
|
64
53
|
|
|
65
|
-
MIT
|
|
54
|
+
[MIT](LICENSE)
|
package/README.md
CHANGED
|
@@ -1,122 +1,54 @@
|
|
|
1
1
|
# dsh-flakefinder
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[English](README.en.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
重复运行测试,找出偶发失败用例并保留调查记录。
|
|
8
8
|
|
|
9
|
-
[](https://www.npmjs.com/package/dsh-flakefinder) [](https://www.npmjs.com/package/dsh-flakefinder)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
欢迎使用,遇到问题或有改进建议,请提交 [issues](https://github.com/STARDUSTLC666/dsh-flakefinder/issues) 和 [PR](https://github.com/STARDUSTLC666/dsh-flakefinder/pulls)。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## 功能
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
| :-- | :-- | :-- |
|
|
19
|
-
| `flaky_detect` | 重复运行测试 N 次,判定 stable-pass / stable-fail / flaky | 否(写历史) |
|
|
20
|
-
| `flaky_history` | 查询检测历史,按目标过滤 | 否 |
|
|
21
|
-
| `flaky_report` | 汇总隔离清单 + 历史,输出稳定性报告 | 否 |
|
|
22
|
-
| `flaky_quarantine` | 把 flaky 用例写入 `.flakefinder.json` 隔离清单 | 是(审批门) |
|
|
23
|
-
| `flaky_clear` | 从隔离清单移除已恢复的用例 | 是(审批门) |
|
|
24
|
-
|
|
25
|
-
支持框架:
|
|
26
|
-
|
|
27
|
-
- vitest:读取 `node_modules/vitest/vitest.mjs`,使用 JSON reporter
|
|
28
|
-
- jest:读取 `node_modules/jest/bin/jest.js`,使用 `--json --outputFile`
|
|
29
|
-
- pytest:`python -m pytest --junitxml`,解析 JUnit XML(支持 setup.cfg / pyproject / pytest.ini / tox.ini 探测与 XML 实体解码)
|
|
30
|
-
- node:test:`node --test --test-reporter=tap`,解析 TAP(含 SKIP 指令归类)
|
|
31
|
-
- `framework: auto` 按 vitest → jest → pytest → node:test 自动探测
|
|
32
|
-
|
|
33
|
-
## 兼容性
|
|
34
|
-
|
|
35
|
-
已在官方 `@deepseek-ai/dsh@0.1.5-rc.1`、Node `24.16.0` 上验证(2026-09-11):18 个组件与 Modlens 同载,工具 schema、技能注册及离线只读调用检查通过。采用 `cordis.patch.yml` + `dsh.bundle.patch` 组合包模型。Node 要求与该版本 Harness 一致:22.19 及以上的 22.x,或 24 及以上。外部服务的实际业务操作需按各组件配置单独验证。
|
|
36
|
-
|
|
37
|
-
2026-09-13 修复:保留宿主 `subprocess.spawn` 的服务对象,避免方法独立传递后因 `this` 丢失而报错。已在官方 `0.1.5-rc.1` 和 `0.1.5-rc.2`、Node `24.16.0` 上验证。`flaky_detect` 已通过真实宿主进程服务连续运行三轮 Node 测试,正确返回 `stable-pass`。
|
|
15
|
+
- 支持 Vitest、Jest、pytest 和 node:test。
|
|
16
|
+
- 记录重复运行结果与失败历史。
|
|
17
|
+
- 生成和维护用例隔离清单。
|
|
38
18
|
|
|
39
19
|
## 安装
|
|
40
20
|
|
|
41
|
-
|
|
42
|
-
dsh plugin --profile web add dsh-flakefinder
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
或手动安装后在 profile 的 `cordis.patch.yml` 插入:
|
|
46
|
-
|
|
47
|
-
```yaml
|
|
48
|
-
- id: flakefinder
|
|
49
|
-
name: 'dsh-flakefinder'
|
|
50
|
-
config:
|
|
51
|
-
defaultRuns: 5
|
|
52
|
-
writeApproval: true
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## 卸载
|
|
21
|
+
桌面版可在「插件」面板按包名 `dsh-flakefinder` 安装。已配置 dsh 命令时也可使用:
|
|
56
22
|
|
|
57
23
|
```bash
|
|
58
|
-
dsh plugin --profile
|
|
24
|
+
dsh plugin --profile desktop add dsh-flakefinder
|
|
59
25
|
```
|
|
60
26
|
|
|
61
|
-
|
|
27
|
+
网页版把命令中的 `desktop` 改为 `web`。安装后重启 DSH。
|
|
62
28
|
|
|
29
|
+
## 开始使用
|
|
63
30
|
|
|
64
|
-
|
|
31
|
+
可说:“把这组测试重复运行十次,找出偶发失败的用例并总结差异。”
|
|
65
32
|
|
|
66
|
-
|
|
67
|
-
用户:src/checkout.test.ts 最近老失败,帮我判断一下
|
|
68
|
-
Agent:
|
|
69
|
-
flaky_detect(target="src/checkout.test.ts", runs=5)
|
|
70
|
-
→ 判定:flaky;3/5 通过,失败集中在 useFakeTimers 用例
|
|
71
|
-
→ flaky_quarantine(tests=["src/checkout.test.ts > 定时器恢复"], reason="定时器竞态")
|
|
72
|
-
```
|
|
33
|
+
## 依赖与配置
|
|
73
34
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
| :-- | :-- | :-- |
|
|
78
|
-
| `defaultRuns` | `5` | `flaky_detect` 默认重复次数(3-20) |
|
|
79
|
-
| `maxRuns` | `20` | 单次允许的最大重复次数(3-50) |
|
|
80
|
-
| `timeoutMs` | `120000` | 单轮测试运行超时 |
|
|
81
|
-
| `graceMs` | `10000` | 超时后宽限 |
|
|
82
|
-
| `writeApproval` | `true` | 隔离清单写操作是否走审批门 |
|
|
83
|
-
| `dataDir` | `DSH_HOME/.dsh-flakefinder` | 历史存储目录 |
|
|
84
|
-
| `quarantineFile` | `<cwd>/.flakefinder.json` | 隔离清单路径 |
|
|
85
|
-
| `pythonPath` | `DSH_FLAKEFINDER_PYTHON` 或 `python`/`python3` | pytest 使用的 Python 解释器 |
|
|
86
|
-
|
|
87
|
-
## 隔离清单格式
|
|
88
|
-
|
|
89
|
-
```json
|
|
90
|
-
{
|
|
91
|
-
"version": 1,
|
|
92
|
-
"quarantined": [
|
|
93
|
-
{
|
|
94
|
-
"file": "src/checkout.test.ts",
|
|
95
|
-
"name": "使用假定时器后恢复真实定时器",
|
|
96
|
-
"reason": "定时器竞态,见 issue #12",
|
|
97
|
-
"since": "2026-08-16T00:00:00.000Z"
|
|
98
|
-
}
|
|
99
|
-
]
|
|
100
|
-
}
|
|
101
|
-
```
|
|
35
|
+
需要项目已有可执行的测试命令。隔离清单用于记录问题,具体门禁按项目配置。
|
|
36
|
+
|
|
37
|
+
详细配置、工具参数与排错见[使用说明](docs/USAGE.md)。从源码独立开发时,Node 要求以 [package.json](package.json) 为准。
|
|
102
38
|
|
|
103
|
-
|
|
39
|
+
## 文档
|
|
104
40
|
|
|
105
|
-
|
|
41
|
+
- [使用与排错](docs/USAGE.md)
|
|
42
|
+
- [更新记录](CHANGELOG.md)
|
|
43
|
+
- [验证范围与历史记录](docs/VALIDATION.md)
|
|
44
|
+
- [问题反馈与功能建议](https://github.com/STARDUSTLC666/dsh-flakefinder/issues)
|
|
106
45
|
|
|
107
|
-
|
|
108
|
-
- 测试进程走 DSH 官方 subprocess 服务,argv 数组、无 shell
|
|
109
|
-
- 全量单测 40+:解析、判定、存储、审批门、pytest 计划、subprocess 超时、注册与 manifest
|
|
110
|
-
- `pnpm test`:构建 + `node --test`
|
|
46
|
+
## 插件更新
|
|
111
47
|
|
|
112
|
-
|
|
48
|
+
需要 DSH 0.2.1-rc.3 或更新版本。每个插件在自己的页面或设置项提供检查、更新记录与确认安装入口,开关独立保存。自动检查默认开启;**自动安装默认关闭**,只有明确授权后,兼容的稳定补丁才会在空闲且没有未保存修改时安装。可单独关闭、推迟或忽略提醒;不会强制重启 DSH、升级 DSH 本体或替换本地源码安装。Suite 安装的组件会明确提示通过 Suite 整包更新。
|
|
113
49
|
|
|
114
|
-
|
|
115
|
-
2. `pnpm typecheck`
|
|
116
|
-
3. 危险模式扫描(eval / child_process / 密钥零容忍)
|
|
117
|
-
4. 真实 profile 冒烟:全新临时 profile 安装插件 → 真 boot → stderr 零报错
|
|
118
|
-
5. manifest 自检(bundle patch / exports / files 白名单)
|
|
50
|
+
旧版用户先在官方插件管理中手动更新一次,之后才会获得此入口。发布到 npm 不会直接替换用户已经安装的版本。
|
|
119
51
|
|
|
120
52
|
## License
|
|
121
53
|
|
|
122
|
-
MIT
|
|
54
|
+
[MIT](LICENSE)
|
package/docs/USAGE.en.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# dsh-flakefinder usage guide
|
|
2
|
+
|
|
3
|
+
[Overview](../README.en.md) · [Changelog](../CHANGELOG.md) · [Validation](VALIDATION.md)
|
|
4
|
+
|
|
5
|
+
## Current improvements
|
|
6
|
+
|
|
7
|
+
Relative quarantineFile defaults to .flakefinder.json in the current workspace. Cancellation stops the current process. Concurrent writers preserve history and quarantine entries; damaged files are preserved with explicit errors for inspection.
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
| Tool | Purpose | Write |
|
|
12
|
+
| :-- | :-- | :-- |
|
|
13
|
+
| `flaky_detect` | Repeat tests N times and classify stable-pass / stable-fail / flaky | history only |
|
|
14
|
+
| `flaky_history` | Query detection history, filter by target | no |
|
|
15
|
+
| `flaky_report` | Combine quarantine manifest and history into a report | no |
|
|
16
|
+
| `flaky_quarantine` | Write flaky cases to `.flakefinder.json` | yes (approval) |
|
|
17
|
+
| `flaky_clear` | Remove recovered cases from the manifest | yes (approval) |
|
|
18
|
+
|
|
19
|
+
Frameworks: vitest / jest / pytest (setup.cfg / pyproject / pytest.ini / tox.ini) / node:test, auto-detected in that order. JUnit XML entities and TAP SKIP directives are parsed.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
dsh plugin --profile web add dsh-flakefinder
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Uninstall
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
dsh plugin --profile web remove dsh-flakefinder
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then restart the web service. To clean up fully, also remove the plugin entry from your profile `cordis.patch.yml` if you overrode it.
|
|
34
|
+
|
|
35
|
+
## Example
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
User: src/checkout.test.ts keeps failing recently, is it real?
|
|
39
|
+
Agent:
|
|
40
|
+
flaky_detect(target="src/checkout.test.ts", runs=5)
|
|
41
|
+
-> verdict: flaky (3/5 passed; failures cluster on fake timers)
|
|
42
|
+
-> flaky_quarantine(tests=["src/checkout.test.ts > timer restore"], reason="timer race")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Config
|
|
46
|
+
|
|
47
|
+
See `cordis.patch.yml`; defaults: `defaultRuns=5`, `maxRuns=20`, `timeoutMs=120000`, `writeApproval=true`, `pythonPath=python` (`python3` on Linux/macOS; used for pytest runs).
|
|
48
|
+
|
|
49
|
+
## Development
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm test
|
|
53
|
+
pnpm typecheck
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
MIT
|
package/docs/USAGE.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# dsh-flakefinder 使用说明
|
|
2
|
+
|
|
3
|
+
[返回简介](../README.md) · [更新记录](../CHANGELOG.md) · [验证记录](VALIDATION.md)
|
|
4
|
+
|
|
5
|
+
## 本次改进
|
|
6
|
+
|
|
7
|
+
相对 quarantineFile 默认在当前工作区的 .flakefinder.json。取消会停止当前测试进程;同一数据目录的并发写入不会丢失历史或隔离条目。损坏文件会报错并保留,先备份后检查。
|
|
8
|
+
|
|
9
|
+
## 工具
|
|
10
|
+
|
|
11
|
+
| 工具 | 作用 | 写操作 |
|
|
12
|
+
| :-- | :-- | :-- |
|
|
13
|
+
| `flaky_detect` | 重复运行测试 N 次,判定 stable-pass / stable-fail / flaky | 否(写历史) |
|
|
14
|
+
| `flaky_history` | 查询检测历史,按目标过滤 | 否 |
|
|
15
|
+
| `flaky_report` | 汇总隔离清单 + 历史,输出稳定性报告 | 否 |
|
|
16
|
+
| `flaky_quarantine` | 把 flaky 用例写入 `.flakefinder.json` 隔离清单 | 是(审批门) |
|
|
17
|
+
| `flaky_clear` | 从隔离清单移除已恢复的用例 | 是(审批门) |
|
|
18
|
+
|
|
19
|
+
支持框架:
|
|
20
|
+
|
|
21
|
+
- vitest:读取 `node_modules/vitest/vitest.mjs`,使用 JSON reporter
|
|
22
|
+
- jest:读取 `node_modules/jest/bin/jest.js`,使用 `--json --outputFile`
|
|
23
|
+
- pytest:`python -m pytest --junitxml`,解析 JUnit XML(支持 setup.cfg / pyproject / pytest.ini / tox.ini 探测与 XML 实体解码)
|
|
24
|
+
- node:test:`node --test --test-reporter=tap`,解析 TAP(含 SKIP 指令归类)
|
|
25
|
+
- `framework: auto` 按 vitest → jest → pytest → node:test 自动探测
|
|
26
|
+
|
|
27
|
+
## 安装
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
dsh plugin --profile web add dsh-flakefinder
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
或手动安装后在 profile 的 `cordis.patch.yml` 插入:
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
- id: flakefinder
|
|
37
|
+
name: 'dsh-flakefinder'
|
|
38
|
+
config:
|
|
39
|
+
defaultRuns: 5
|
|
40
|
+
writeApproval: true
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 卸载
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
dsh plugin --profile web remove dsh-flakefinder
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
卸载后重启 Web 服务。如需彻底清理,可再手动删除自己 profile `cordis.patch.yml` 中覆盖的插件行。
|
|
50
|
+
|
|
51
|
+
## 使用示例
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
用户:src/checkout.test.ts 最近老失败,帮我判断一下
|
|
55
|
+
Agent:
|
|
56
|
+
flaky_detect(target="src/checkout.test.ts", runs=5)
|
|
57
|
+
→ 判定:flaky;3/5 通过,失败集中在 useFakeTimers 用例
|
|
58
|
+
→ flaky_quarantine(tests=["src/checkout.test.ts > 定时器恢复"], reason="定时器竞态")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 配置
|
|
62
|
+
|
|
63
|
+
| 字段 | 默认 | 说明 |
|
|
64
|
+
| :-- | :-- | :-- |
|
|
65
|
+
| `defaultRuns` | `5` | `flaky_detect` 默认重复次数(3-20) |
|
|
66
|
+
| `maxRuns` | `20` | 单次允许的最大重复次数(3-50) |
|
|
67
|
+
| `timeoutMs` | `120000` | 单轮测试运行超时 |
|
|
68
|
+
| `graceMs` | `10000` | 超时后宽限 |
|
|
69
|
+
| `writeApproval` | `true` | 隔离清单写操作是否走审批门 |
|
|
70
|
+
| `dataDir` | `DSH_HOME/.dsh-flakefinder` | 历史存储目录 |
|
|
71
|
+
| `quarantineFile` | `<cwd>/.flakefinder.json` | 隔离清单路径 |
|
|
72
|
+
| `pythonPath` | `DSH_FLAKEFINDER_PYTHON` 或 `python`/`python3` | pytest 使用的 Python 解释器 |
|
|
73
|
+
|
|
74
|
+
## 隔离清单格式
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"version": 1,
|
|
79
|
+
"quarantined": [
|
|
80
|
+
{
|
|
81
|
+
"file": "src/checkout.test.ts",
|
|
82
|
+
"name": "使用假定时器后恢复真实定时器",
|
|
83
|
+
"reason": "定时器竞态,见 issue #12",
|
|
84
|
+
"since": "2026-08-16T00:00:00.000Z"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
隔离清单只记录,不修改测试源码;agent 跑测试前应先查阅 `flaky_report`。
|
|
91
|
+
|
|
92
|
+
## 工程
|
|
93
|
+
|
|
94
|
+
- Node >= 22.13,TypeScript,仅依赖文件锁库
|
|
95
|
+
- 测试进程走 DSH 官方 subprocess 服务,argv 数组、无 shell
|
|
96
|
+
- 全量单测 40+:解析、判定、存储、审批门、pytest 计划、subprocess 超时、注册与 manifest
|
|
97
|
+
- `pnpm test`:构建 + `node --test`
|
|
98
|
+
|
|
99
|
+
## 发布门禁
|
|
100
|
+
|
|
101
|
+
1. `pnpm test` 全绿
|
|
102
|
+
2. `pnpm typecheck`
|
|
103
|
+
3. 危险模式扫描(eval / child_process / 密钥零容忍)
|
|
104
|
+
4. 真实 profile 冒烟:全新临时 profile 安装插件 → 真 boot → stderr 零报错
|
|
105
|
+
5. manifest 自检(bundle patch / exports / files 白名单)
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# dsh-flakefinder 验证记录
|
|
2
|
+
|
|
3
|
+
本页整理原 README 的历史验证说明,保留当时的版本、日期与范围。自动测试、启动检查、浏览器操作和真实服务验收分别记录,不能相互替代。更详细的版本验收文件仍保留在仓库中。
|
|
4
|
+
|
|
5
|
+
## 原中文记录
|
|
6
|
+
|
|
7
|
+
验证宿主:官方源码构建的 Harness `0.2.0-rc.1`(commit `407e65c8`)+ Node `24.16.0`(2026-09-28)。44 项插件测试在隔离环境全部通过;同一个宿主里 18 个插件共同加载,注册 6 个工具,工具 schema 与健康检查契约通过。本轮未启用真实端口与外部服务。
|
|
8
|
+
|
|
9
|
+
2026-09-13 修复:保留宿主 `subprocess.spawn` 的服务对象,避免方法独立传递后因 `this` 丢失而报错。该路径已在隔离宿主进程服务中实测通过。`flaky_detect` 已通过真实宿主进程服务连续运行三轮 Node 测试,正确返回 `stable-pass`。
|
|
10
|
+
|
|
11
|
+
## Original English record
|
|
12
|
+
|
|
13
|
+
Validation host: Harness `0.2.0-rc.1` built from official sources (commit `407e65c8`) with Node `24.16.0` on 2026-09-28. All 44 plugin tests pass in an isolated environment; all 18 plugins mount together in one host registering 6 tools, with tool schemas and health-check contracts passing. No live ports or external services were exercised in this round.
|
|
14
|
+
|
|
15
|
+
2026-09-13 fix: retain the service receiver when calling `subprocess.spawn`, preventing failures caused by passing the method as an unbound callback. Verified against a real isolated host subprocess service. `flaky_detect` runs three real Node test processes through the host subprocess service and returns `stable-pass`.
|
package/lib/config.d.ts
CHANGED
package/lib/config.js
CHANGED
|
@@ -49,7 +49,8 @@ export function resolveConfig(config, cwd = process.cwd()) {
|
|
|
49
49
|
const pythonPath = typeof cfg.pythonPath === 'string' && cfg.pythonPath.trim() !== ''
|
|
50
50
|
? cfg.pythonPath.trim()
|
|
51
51
|
: (process.env.DSH_FLAKEFINDER_PYTHON?.trim() || (process.platform === 'win32' ? 'python' : 'python3'));
|
|
52
|
-
|
|
52
|
+
const relativeQuarantine = typeof cfg.quarantineFile === 'string' && cfg.quarantineFile.trim() ? cfg.quarantineFile.trim() : '.flakefinder.json';
|
|
53
|
+
return { defaultRuns, maxRuns, timeoutMs, graceMs, writeApproval, dataDir, quarantineFile, pythonPath, ...(path.isAbsolute(relativeQuarantine) ? {} : { quarantineFileRelative: relativeQuarantine }) };
|
|
53
54
|
}
|
|
54
55
|
function readRuns(label, value, lo, hi) {
|
|
55
56
|
if (typeof value !== 'number' || !Number.isFinite(value))
|
package/lib/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 插件导出 apply(ctx, config):注册五个面向模型的工具(flaky_detect / flaky_history /
|
|
5
5
|
* flaky_quarantine / flaky_clear / flaky_report)。测试进程走 DSH 官方 subprocess 服务
|
|
6
|
-
* (argv 数组、无 shell
|
|
6
|
+
* (argv 数组、无 shell),隔离清单写操作默认走宿主审批门。仅依赖文件锁库。
|
|
7
7
|
*
|
|
8
8
|
* @module dsh-flakefinder
|
|
9
9
|
*/
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { registerUpdates } from '@stardustlc/dsh-updates';
|
|
1
2
|
/**
|
|
2
3
|
* dsh-flakefinder —— 测试稳定性工具插件(node 半身,配置走 cordis.patch.yml)。
|
|
3
4
|
*
|
|
4
5
|
* 插件导出 apply(ctx, config):注册五个面向模型的工具(flaky_detect / flaky_history /
|
|
5
6
|
* flaky_quarantine / flaky_clear / flaky_report)。测试进程走 DSH 官方 subprocess 服务
|
|
6
|
-
* (argv 数组、无 shell
|
|
7
|
+
* (argv 数组、无 shell),隔离清单写操作默认走宿主审批门。仅依赖文件锁库。
|
|
7
8
|
*
|
|
8
9
|
* @module dsh-flakefinder
|
|
9
10
|
*/
|
|
@@ -18,6 +19,7 @@ export const inject = ['subprocess', 'tools'];
|
|
|
18
19
|
* 插件入口:解析配置、封装执行器与存储、注册五个工具。
|
|
19
20
|
*/
|
|
20
21
|
export function apply(ctx, config) {
|
|
22
|
+
registerUpdates(ctx, { name: "dsh-flakefinder" });
|
|
21
23
|
let cfg;
|
|
22
24
|
try {
|
|
23
25
|
cfg = resolveConfig(config);
|
package/lib/runner.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export interface RunResult {
|
|
|
14
14
|
export interface ProcessRunner {
|
|
15
15
|
run(argv: readonly string[], options?: {
|
|
16
16
|
timeoutMs?: number;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
signal?: AbortSignal;
|
|
17
19
|
}): Promise<RunResult>;
|
|
18
20
|
}
|
|
19
21
|
export interface SubprocessHandleLike {
|
|
@@ -63,4 +65,4 @@ export interface FlakeRun {
|
|
|
63
65
|
error?: string;
|
|
64
66
|
}
|
|
65
67
|
/** 执行一个测试计划并读取报告;进程失败但报告存在时仍返回报告。 */
|
|
66
|
-
export declare function executePlan(runner: ProcessRunner, plan: TestPlan, index: number, timeoutMs: number): Promise<FlakeRun>;
|
|
68
|
+
export declare function executePlan(runner: ProcessRunner, plan: TestPlan, index: number, timeoutMs: number, cwd?: string, signal?: AbortSignal): Promise<FlakeRun>;
|
package/lib/runner.js
CHANGED
|
@@ -12,19 +12,21 @@ export function createSubprocessRunner(spawn, graceMs, defaultTimeoutMs) {
|
|
|
12
12
|
async run(argv, options) {
|
|
13
13
|
const timeoutMs = options?.timeoutMs ?? defaultTimeoutMs;
|
|
14
14
|
const controller = new AbortController();
|
|
15
|
+
const signal = options?.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal;
|
|
16
|
+
signal.throwIfAborted();
|
|
15
17
|
const timer = setTimeout(() => controller.abort(new Error('flakefinder test run timed out')), timeoutMs);
|
|
16
18
|
let handle;
|
|
17
19
|
try {
|
|
18
20
|
handle = spawn({
|
|
19
21
|
argv,
|
|
20
|
-
cwd: process.cwd(),
|
|
22
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
21
23
|
stdio: {
|
|
22
24
|
stdin: 'ignore',
|
|
23
25
|
stdout: { maxBytes: COLLECT_BYTES },
|
|
24
26
|
stderr: { maxBytes: COLLECT_BYTES },
|
|
25
27
|
},
|
|
26
28
|
graceMs,
|
|
27
|
-
signal
|
|
29
|
+
signal,
|
|
28
30
|
});
|
|
29
31
|
const outcome = await handle.done;
|
|
30
32
|
const stdout = handle.collected.stdout?.readFrom(0).text ?? '';
|
|
@@ -42,9 +44,11 @@ function stderrTail(stderr) {
|
|
|
42
44
|
return tail || '无错误输出';
|
|
43
45
|
}
|
|
44
46
|
/** 执行一个测试计划并读取报告;进程失败但报告存在时仍返回报告。 */
|
|
45
|
-
export async function executePlan(runner, plan, index, timeoutMs) {
|
|
47
|
+
export async function executePlan(runner, plan, index, timeoutMs, cwd, signal) {
|
|
46
48
|
const started = Date.now();
|
|
47
|
-
|
|
49
|
+
signal?.throwIfAborted();
|
|
50
|
+
const result = await runner.run(plan.argv, { timeoutMs, cwd, signal });
|
|
51
|
+
signal?.throwIfAborted();
|
|
48
52
|
const durationMs = Date.now() - started;
|
|
49
53
|
if (plan.reportKind === 'tap') {
|
|
50
54
|
return {
|