pi-skill-evolve 0.1.3 → 0.1.4

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.
@@ -27,7 +27,7 @@ export const SUBCOMMANDS: readonly SubcommandItem[] = [
27
27
  { value: "dispatch", label: "dispatch", description: "只开/关自动复盘(on|off;会派生子进程,花 token)" },
28
28
  { value: "review", label: "review", description: "只开/关自动评审(on|off;提案后再起督导,再花一份 token)" },
29
29
  { value: "apply", label: "apply", description: "只开/关自动采纳(on|off;auto 提案自动落盘,可回滚)" },
30
- { value: "on", label: "on", description: "复盘与评审一起打开(不动采集,也不动自动采纳)" },
30
+ { value: "on", label: "on", description: "只打开自动复盘(采集 / 评审 / 采纳都不动)" },
31
31
  { value: "off", label: "off", description: "四个开关(采集/复盘/评审/采纳)一起关闭" },
32
32
  ];
33
33
 
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * 技能进化配置:唯一来源是 `.pi/evolution/config.json`。
3
3
  *
4
- * **默认只开自动评审,其余三个关**(采集 `telemetry:false` / 复盘 `enabled:false` / 自动采纳 `autoApply:false`,
5
- * 自动评审 `autoReview:true`):别人 clone 下来不采集、不派生、不落盘,也就没有 token 开销 ——
6
- * `autoReview` 单独为 true 是安全的,因为它只在「复盘真的跑起来」之后才起作用(`enabled` 关着就永远走不到)。
4
+ * **四个开关默认全关**(采集 `telemetry` / 复盘 `enabled` / 评审 `autoReview` / 采纳 `autoApply` 都是 false,
5
+ * 2026-11-08 用户定「autoReview 默认也关」):别人 clone 下来不采集、不派生、不评审、不落盘,零 token 开销。
6
+ * 要用就一条一条显式打开(`collect` / `dispatch` / `review` / `apply`),谁开谁负责。
7
7
  * 每一档花不花 token:
8
8
  * - 采集遥测:只写本地 jsonl,**不花 token**;
9
9
  * - 自动复盘:起子进程跑 agent,**花 token**;
@@ -76,9 +76,9 @@ export const DEFAULT_CONFIG: Readonly<EvolutionConfig> = Object.freeze({
76
76
  maxRuntimeMs: 20 * 60_000,
77
77
  perSessionCap: 20,
78
78
  telemetry: false,
79
- // 自动评审默认开:设计原意就是「复盘 → 评审 → 采纳」一条流水线,评审只是流程的一部分,
80
- // 而 enabled 关着时它根本不生效,所以默认 true 不会让 clone 下来的人白花 token。
81
- autoReview: true,
79
+ // 自动评审默认关(2026-11-08 用户定):评审本身也要起子进程再花一份 token,
80
+ // 不能让「打开复盘」顺手把 token 翻倍。要评审就显式 `/skill-evolve review on`。
81
+ autoReview: false,
82
82
  // 自动采纳默认关:它改的是仓库文件,必须人工先开一次;默认开等于替用户做决定。
83
83
  autoApply: false,
84
84
  ui: Object.freeze({ widget: false, entries: false }),
@@ -193,7 +193,7 @@ export async function saveConfigSwitch(
193
193
  ): Promise<EvolutionConfig> {
194
194
  const raw = readRawConfig(evolutionDir);
195
195
  const patch = on
196
- ? { enabled: true, autoReview: true }
196
+ ? { enabled: true }
197
197
  : { enabled: false, telemetry: false, autoReview: false, autoApply: false };
198
198
  const next = normalizeConfig({ ...raw, ...patch });
199
199
  const file = configFile(evolutionDir);
@@ -17,11 +17,11 @@ function workspace(): string {
17
17
  return path.join(cwd, ".pi", "evolution");
18
18
  }
19
19
 
20
- test("DEFAULT_CONFIG:只开自动评审,采集 / 复盘 / 自动采纳都默认关", () => {
21
- // 自动评审单独为 true 是安全的:enabled 关着时它永远走不到,不会替 clone 下来的人花 token
20
+ test("DEFAULT_CONFIG:四个开关默认全关", () => {
21
+ // 四个默认全关:clone 下来不采集、不派生、不评审、不落盘(2026-11-08 用户定)
22
22
  assert.deepEqual(
23
23
  [DEFAULT_CONFIG.enabled, DEFAULT_CONFIG.telemetry, DEFAULT_CONFIG.autoReview, DEFAULT_CONFIG.autoApply],
24
- [false, false, true, false],
24
+ [false, false, false, false],
25
25
  );
26
26
  });
27
27
 
@@ -30,14 +30,14 @@ test("loadConfig:没有 config.json 时只开自动评审,且不会顺手造
30
30
  const config = loadConfig(evolutionDir);
31
31
  assert.deepEqual(
32
32
  [config.enabled, config.telemetry, config.autoReview, config.autoApply],
33
- [false, false, true, false],
33
+ [false, false, false, false],
34
34
  );
35
35
  assert.equal(fs.existsSync(configFile(evolutionDir)), false, "读配置不能有副作用");
36
36
  });
37
37
 
38
38
  test("normalizeConfig:空对象与缺字段都回落到默认(评审开、其余关)", () => {
39
39
  const empty = normalizeConfig({});
40
- assert.deepEqual([empty.enabled, empty.telemetry, empty.autoReview, empty.autoApply], [false, false, true, false]);
40
+ assert.deepEqual([empty.enabled, empty.telemetry, empty.autoReview, empty.autoApply], [false, false, false, false]);
41
41
  const onlyEnabled = normalizeConfig({ enabled: true });
42
42
  assert.deepEqual(
43
43
  [onlyEnabled.enabled, onlyEnabled.telemetry, onlyEnabled.autoApply],
@@ -49,12 +49,12 @@ test("normalizeConfig:空对象与缺字段都回落到默认(评审开、
49
49
  test("normalizeConfig:autoReview / autoApply 写错类型回落到默认值", () => {
50
50
  // 手改配置写成字符串是常事:坏值只回退那一个字段,不能让整份配置失效
51
51
  const wrong = normalizeConfig({ autoReview: "off", autoApply: 1 });
52
- assert.deepEqual([wrong.autoReview, wrong.autoApply], [true, false]);
52
+ assert.deepEqual([wrong.autoReview, wrong.autoApply], [false, false]);
53
53
  const explicit = normalizeConfig({ autoReview: false, autoApply: true, enabled: true });
54
54
  assert.deepEqual([explicit.enabled, explicit.autoReview, explicit.autoApply], [true, false, true]);
55
55
  });
56
56
 
57
- test("saveConfigSwitch:on 只开复盘 + 评审,采集与自动采纳保持原值", async () => {
57
+ test("saveConfigSwitch:on 只开复盘,采集 / 评审 / 采纳都保持原值", async () => {
58
58
  const evolutionDir = workspace();
59
59
  fs.mkdirSync(evolutionDir, { recursive: true });
60
60
  fs.writeFileSync(
@@ -65,13 +65,13 @@ test("saveConfigSwitch:on 只开复盘 + 评审,采集与自动采纳保持
65
65
  const next = await saveConfigSwitch(evolutionDir, true, directQueue);
66
66
  assert.deepEqual(
67
67
  [next.enabled, next.autoReview, next.telemetry, next.autoApply, next.idleMs, next.perSessionCap],
68
- [true, true, true, false, 1_234, 3],
68
+ [true, false, true, false, 1_234, 3],
69
69
  );
70
70
  const raw = JSON.parse(fs.readFileSync(configFile(evolutionDir), "utf8"));
71
71
  assert.deepEqual(
72
72
  [raw.enabled, raw.autoReview, raw.telemetry, raw.autoApply, raw.idleMs, raw.perSessionCap],
73
- [true, true, true, false, 1_234, 3],
74
- "写盘内容必须与返回值一致:采集关着不能被 on 顺手打开,自动采纳更不能被打开",
73
+ [true, false, true, false, 1_234, 3],
74
+ "写盘内容必须与返回值一致:on 只开复盘,采集 / 评审 / 采纳都保持原值",
75
75
  );
76
76
  });
77
77
 
@@ -68,7 +68,8 @@ function harness(
68
68
  }
69
69
 
70
70
  test("派发成功时同一轮就起评审督导,并把评审模型透传过去", async () => {
71
- const h = harness({ reviewModel: () => "deepseek/deepseek-v3.2" });
71
+ // 评审默认关(2026-11-08),这里显式打开才测得到「起督导 + 透传模型」
72
+ const h = harness({ config: { autoReview: true }, reviewModel: () => "deepseek/deepseek-v3.2" });
72
73
  const outcome = await h.dispatch({ sessionId: "sess-1", skills: ["alpha"] });
73
74
  assert.equal(outcome.status, "dispatched");
74
75
  assert.equal(h.supervisorCalls.length, 1, "必须起且只起一个督导");
@@ -222,7 +222,7 @@ test("statusText / reportText:无数据也不崩,且带上盲区提示", asy
222
222
  const status = await h.evo.statusText();
223
223
  assert.equal(
224
224
  status.includes(
225
- "采集:开(遥测写入 .pi/evolution/telemetry/)|复盘:开(会派生 agent)|评审:开(提案后自动起督导)|采纳:关(auto 提案等人工批准)",
225
+ "采集:开(遥测写入 .pi/evolution/telemetry/)|复盘:开(会派生 agent)|评审:关(提案停在 proposed 等人工)|采纳:关(auto 提案等人工批准)",
226
226
  ),
227
227
  true,
228
228
  );
@@ -257,7 +257,7 @@ test("reportText:按遥测给出曝光/加载/未命中", async () => {
257
257
  );
258
258
  });
259
259
 
260
- test("setEnabled:off 四个全关、on 只开复盘 + 评审(不动采集与自动采纳)", async () => {
260
+ test("setEnabled:off 四个全关、on 只开复盘(不动采集 / 评审 / 采纳)", async () => {
261
261
  const h = harness();
262
262
  const message = await h.evo.setEnabled(false);
263
263
  assert.equal(message.includes("关闭"), true);
@@ -267,8 +267,8 @@ test("setEnabled:off 四个全关、on 只开复盘 + 评审(不动采集与
267
267
 
268
268
  await h.evo.setEnabled(true);
269
269
  const back = JSON.parse(fs.readFileSync(path.join(h.dir, ".pi", "evolution", "config.json"), "utf8"));
270
- // 用户定的语义:on = 复盘 + 评审两开;采集要另外 collect on,自动采纳要另外 apply on
271
- assert.deepEqual([back.enabled, back.autoReview, back.telemetry, back.autoApply], [true, true, false, false]);
270
+ // 用户定的语义(2026-11-08):四个开关各管一段,on 只开自动复盘;评审要另外 review on
271
+ assert.deepEqual([back.enabled, back.autoReview, back.telemetry, back.autoApply], [true, false, false, false]);
272
272
  });
273
273
 
274
274
  test("setFlag:只切一个字段,并把当前四个开关的状态写进回执", async () => {
@@ -309,9 +309,9 @@ test("没有 config.json 时默认全关:不派生、不落遥测", async () =
309
309
  });
310
310
  const status = await evo.statusText();
311
311
  assert.equal(
312
- status.includes("采集:关(不写遥测)|复盘:关(不会派生 agent)|评审:开(提案后自动起督导)|采纳:关(auto 提案等人工批准)"),
312
+ status.includes("采集:关(不写遥测)|复盘:关(不会派生 agent)|评审:关(提案停在 proposed 等人工)|采纳:关(auto 提案等人工批准)"),
313
313
  true,
314
- "默认只开自动评审:enabled 关着时它永远走不到",
314
+ "默认四个全关:采集 / 复盘 / 评审 / 采纳都不动",
315
315
  );
316
316
  evo.recordAdvertised({ sessionId: "s1", cwd: dir, prompt: "x", skills: [skill("a")] });
317
317
  evo.settle({ sessionId: "s1" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-skill-evolve",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "技能进化:采集会话中的技能曝光/加载,异步复盘、生成改进提案并独立评审,附本机 Web 管理面板",
5
5
  "keywords": [
6
6
  "pi-package",