pi-skill-evolve 0.1.9 → 0.1.10
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/extensions/skill-evolve/fixtures/selftest/good-description/after.md +9 -0
- package/extensions/skill-evolve/fixtures/selftest/good-description/change.diff +13 -0
- package/extensions/skill-evolve/fixtures/selftest/good-description/fixture.json +6 -0
- package/extensions/skill-evolve/lib/replay-fixture.ts +5 -2
- package/extensions/skill-evolve/lib/review-post.ts +92 -21
- package/extensions/skill-evolve/lib/review-prompt.ts +5 -1
- package/extensions/skill-evolve/lib/review-record.ts +14 -1
- package/extensions/skill-evolve/lib/review-supervisor.ts +13 -1
- package/extensions/skill-evolve/lib/runs.ts +4 -0
- package/extensions/skill-evolve/lib/selftest.ts +22 -5
- package/extensions/skill-evolve/lib/web/applied.ts +6 -1
- package/extensions/skill-evolve/lib/web/approvals.ts +7 -0
- package/extensions/skill-evolve/lib/web/done.ts +20 -6
- package/extensions/skill-evolve/lib/web/pending.ts +7 -1
- package/extensions/skill-evolve/lib/web/render-rows.ts +11 -2
- package/extensions/skill-evolve/lib/web/render-run.ts +46 -10
- package/extensions/skill-evolve/lib/web/reports.ts +11 -3
- package/extensions/skill-evolve/lib/web/run-detail.ts +41 -13
- package/extensions/skill-evolve/lib/web/style.ts +2 -0
- package/extensions/skill-evolve/test/review-post.test.ts +53 -6
- package/extensions/skill-evolve/test/review-prompt.test.ts +9 -0
- package/extensions/skill-evolve/test/review-record.test.ts +59 -0
- package/extensions/skill-evolve/test/review-supervisor.test.ts +15 -1
- package/extensions/skill-evolve/test/selftest.test.ts +51 -16
- package/extensions/skill-evolve/test/web-redesign.test.ts +1 -1
- package/extensions/skill-evolve/test/web-render-run.test.ts +70 -1
- package/extensions/skill-evolve/test/web-run-detail.test.ts +27 -0
- package/extensions/skill-evolve/test/web-view-coverage.test.ts +100 -0
- package/package.json +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 视图覆盖性单测(用户 2026-11-08:「tab 包含所有状态了吗?」)。
|
|
3
|
+
*
|
|
4
|
+
* `review_failed` / `abandoned` / `unauthorized_write` 这三种终态曾没有任何视图收,
|
|
5
|
+
* 这些 run 在面板上直接消失、只能翻 `runs/` 目录。本文件钉住两件事:
|
|
6
|
+
* 1. 行为:七种终态都真的能进「已处理」,徽章文案与颜色对得上;
|
|
7
|
+
* 2. 结构:`RUN_STATUSES` 每一项至少被五个视图之一的判据清单收 ——
|
|
8
|
+
* 以后新增状态却忘了接视图,这条测试会红并打印漏掉的状态,不会再静默消失。
|
|
9
|
+
*
|
|
10
|
+
* 五个清单都是各视图「判据旁边」的导出常量,而不是测试里另抄一份:抄一份的话,
|
|
11
|
+
* 代码改了测试不会发现(rolledback 那种抄错字符的坑就是这么漏过去的)。
|
|
12
|
+
*/
|
|
13
|
+
import assert from "node:assert/strict";
|
|
14
|
+
import * as fs from "node:fs";
|
|
15
|
+
import * as os from "node:os";
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
import test from "node:test";
|
|
18
|
+
import { RUN_STATUSES, type RunSummary } from "../lib/runs.ts";
|
|
19
|
+
import { APPLIED_RUN_STATUSES } from "../lib/web/applied.ts";
|
|
20
|
+
import { APPROVALS_RUN_STATUSES } from "../lib/web/approvals.ts";
|
|
21
|
+
import { buildDone, DONE_STATUSES } from "../lib/web/done.ts";
|
|
22
|
+
import { PENDING_RUN_STATUSES } from "../lib/web/pending.ts";
|
|
23
|
+
import { REPORTS_RUN_STATUSES } from "../lib/web/reports.ts";
|
|
24
|
+
import { doneRows } from "../lib/web/render-rows.ts";
|
|
25
|
+
|
|
26
|
+
const NOW = Date.UTC(2026, 10, 8, 12);
|
|
27
|
+
|
|
28
|
+
function workspace(): string {
|
|
29
|
+
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "skill-evolve-coverage-"));
|
|
30
|
+
const evolutionDir = path.join(cwd, ".pi", "evolution");
|
|
31
|
+
fs.mkdirSync(path.join(evolutionDir, "runs"), { recursive: true });
|
|
32
|
+
return evolutionDir;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function run(runId: string, status: string, at: number): RunSummary {
|
|
36
|
+
return {
|
|
37
|
+
runId,
|
|
38
|
+
status,
|
|
39
|
+
dispatchedAt: at,
|
|
40
|
+
sessionId: `session-${runId}`,
|
|
41
|
+
sessionFile: null,
|
|
42
|
+
coverage: null,
|
|
43
|
+
pid: null,
|
|
44
|
+
supervisorPid: null,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
test("三个曾静默消失的终态都进「已处理」,徽章文案与颜色对得上,排序仍是时间倒序", () => {
|
|
49
|
+
const evolutionDir = workspace();
|
|
50
|
+
const runs = [
|
|
51
|
+
run("r-review-failed", "review_failed", NOW),
|
|
52
|
+
run("r-abandoned", "abandoned", NOW + 1_000),
|
|
53
|
+
run("r-unauthorized", "unauthorized_write", NOW + 2_000),
|
|
54
|
+
];
|
|
55
|
+
const done = buildDone([], runs, evolutionDir);
|
|
56
|
+
assert.deepEqual(
|
|
57
|
+
done.map((item) => item.status),
|
|
58
|
+
["unauthorized_write", "abandoned", "review_failed"],
|
|
59
|
+
);
|
|
60
|
+
const rows = doneRows(done);
|
|
61
|
+
const badge = (runId: string) => rows.find((row) => row.runId === runId)?.badge;
|
|
62
|
+
assert.deepEqual(badge("r-review-failed"), { text: "评审失败", tone: "red", title: "" });
|
|
63
|
+
assert.equal(badge("r-abandoned")?.text, "已放弃");
|
|
64
|
+
assert.equal(badge("r-abandoned")?.tone, "faint");
|
|
65
|
+
assert.equal(badge("r-unauthorized")?.text, "越权写入");
|
|
66
|
+
assert.equal(badge("r-unauthorized")?.tone, "red");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("覆盖性:RUN_STATUSES 每一项至少被一个视图的判据清单收", () => {
|
|
70
|
+
const views: Record<string, readonly string[]> = {
|
|
71
|
+
待处理: PENDING_RUN_STATUSES,
|
|
72
|
+
待审批: APPROVALS_RUN_STATUSES,
|
|
73
|
+
已采纳: APPLIED_RUN_STATUSES,
|
|
74
|
+
已处理: DONE_STATUSES,
|
|
75
|
+
复盘报告: REPORTS_RUN_STATUSES,
|
|
76
|
+
};
|
|
77
|
+
const missing = RUN_STATUSES.filter((status) => !Object.values(views).some((list) => list.includes(status)));
|
|
78
|
+
assert.deepEqual(missing, [], `这些状态没有任何 tab 收,会在面板上直接消失:${missing.join("、")}`);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("「已处理」清单里的每个状态都能真的被 buildDone 收到(防 rolledback 这种抄错字符)", () => {
|
|
82
|
+
const evolutionDir = workspace();
|
|
83
|
+
for (const status of DONE_STATUSES) {
|
|
84
|
+
const done = buildDone([], [run(`r-${status}`, status, NOW)], evolutionDir);
|
|
85
|
+
assert.equal(done.length, 1, `${status} 没进已处理`);
|
|
86
|
+
assert.equal(done[0]?.status, status);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("七个终态都有中文徽章文案,不许回落成原始英文 status", () => {
|
|
91
|
+
const evolutionDir = workspace();
|
|
92
|
+
const runs = DONE_STATUSES.map((status, index) => run(`r-${status}`, status, NOW + index));
|
|
93
|
+
const rows = doneRows(buildDone([], runs, evolutionDir));
|
|
94
|
+
for (const status of DONE_STATUSES) {
|
|
95
|
+
const badge = rows.find((row) => row.runId === `r-${status}`)?.badge;
|
|
96
|
+
assert.ok(badge, `${status} 缺行`);
|
|
97
|
+
assert.notEqual(badge.text, status, `${status} 回落成了原始英文:tone 表的键与真实 status 不一致`);
|
|
98
|
+
assert.match(badge.text, /^[\u4e00-\u9fa5]+$/, `${status} 的文案不是中文`);
|
|
99
|
+
}
|
|
100
|
+
});
|