pi-skill-evolve 0.1.7 → 0.1.9

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.
@@ -21,7 +21,7 @@ import {
21
21
  telemetryOffWhileEnabled,
22
22
  } from "../flags.ts";
23
23
  import type { WebView } from "./data.ts";
24
- import { RANGE_KEYS, RANGE_LABEL, STATUS_OPTIONS, type ListFilter, type ViewPage } from "./filter.ts";
24
+ import { RANGE_KEYS, RANGE_LABEL, type ListFilter, type ViewPage } from "./filter.ts";
25
25
  import { listHref, type ListExtras } from "./list-query.ts";
26
26
  import { escapeHtml, formatStamp, formatTimeSeconds } from "./text.ts";
27
27
  import type { WebControls } from "./activity.ts";
@@ -106,15 +106,7 @@ ${run}</div>
106
106
  ${warn}${backlog}`;
107
107
  }
108
108
 
109
- /** 状态下拉:先「全部」,再固定七个状态(顺序与 STATUS_OPTIONS 一致,别在渲染层重排) */
110
- function statusSelect(current: string): string {
111
- const options = [`<option value="">全部状态</option>`];
112
- for (const status of STATUS_OPTIONS) {
113
- options.push(`<option value="${status}"${status === current ? " selected" : ""}>${status}</option>`);
114
- }
115
- return options.join("");
116
- }
117
-
109
+ /** 时间下拉:只有「看多久内」需要人手动换,状态与技能已在 tab 与技能页面各自解决了 */
118
110
  function rangeSelect(current: string): string {
119
111
  return RANGE_KEYS.map(
120
112
  (key) => `<option value="${key}"${key === current ? " selected" : ""}>${RANGE_LABEL[key]}</option>`,
@@ -122,16 +114,16 @@ function rangeSelect(current: string): string {
122
114
  }
123
115
 
124
116
  /**
125
- * 筛选表单:hidden view 保证 GET 提交后还在同一页;「重置」链回不带筛选的本页。
126
- * `open` / `live` 也一并带上:筛选不该顺手把「展开分组」「自动刷新」这两个开关清掉。
117
+ * 筛选表单:只留「时间」一个条件。
118
+ * 技能:每个列表页的行里已经有技能列,技能页可以按技能点进来,再摆一个模糊搜索框没人知道该填什么;
119
+ * 状态:顶部 tab 本身就是按状态分的(待处理 / 待审批 / 已采纳 / 已处理 / 复盘报告),重复选毫无意义。
120
+ * 两个参数(skill / status)仍由 `parseListQuery` 支持,旧链接与代码内部跳转不会断,只是不再出输入框。
127
121
  */
128
122
  export function renderFilterForm(view: WebView, filter: ListFilter, extras: ListExtras): string {
129
123
  const keep = extraInputs(extras);
130
124
  return `<form class="filter" method="get">
131
125
  <input type="hidden" name="view" value="${view}">
132
- ${keep}<label>技能 <input type="text" name="skill" value="${escapeHtml(filter.skill)}" placeholder="全部技能" size="16"></label>
133
- <label>状态 <select name="status">${statusSelect(filter.status)}</select></label>
134
- <label>时间 <select name="range">${rangeSelect(filter.range)}</select></label>
126
+ ${keep}<label>时间 <select name="range">${rangeSelect(filter.range)}</select></label>
135
127
  <button type="submit">筛选</button>
136
128
  <a class="btn" href="${escapeHtml(listHref(view, filter, 1, extras))}">重置</a>
137
129
  </form>`;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * 筛选栏的验收测试(用户 2026-11-08:「这个搜索框的技能和状态不用了吧, 技能不知道用来搜索什么,
3
+ * 状态应该在顶部 tab 包含了吧」)。
4
+ *
5
+ * 口径:
6
+ * 1. 表单**只剩「时间」**一个条件——技能看不出该填什么、状态与顶部 tab 重复,两个都撤掉;
7
+ * 2. 撤掉的是**输入控件**,不是参数:`?skill=` / `?status=` 仍由 `parseListQuery` 解析,
8
+ * 技能页点进来、旧书签、代码内部跳转都不会断;
9
+ * 3. 表单仍是 GET + 保留 `view`,否则一提交就跳出当前页。
10
+ *
11
+ * 纪律:纯字符串断言,不碰文件系统、不起服务。
12
+ */
13
+ import { test } from "node:test";
14
+ import assert from "node:assert/strict";
15
+
16
+ import { parseListQuery } from "../lib/web/filter.ts";
17
+ import { renderFilterForm } from "../lib/web/render-controls.ts";
18
+
19
+ const FILTER = parseListQuery(new URLSearchParams(""));
20
+ const EXTRAS = { live: false, open: "all", only: false } as never;
21
+
22
+ function form(): string {
23
+ return renderFilterForm("pending", FILTER, EXTRAS);
24
+ }
25
+
26
+ test("筛选栏不再有技能输入框与状态下拉", () => {
27
+ const html = form();
28
+ assert.ok(!html.includes('name="skill"'), "技能搜索框已撤掉");
29
+ assert.ok(!html.includes('name="status"'), "状态下拉已撤掉(顶部 tab 就是状态)");
30
+ assert.ok(!html.includes("全部状态"));
31
+ assert.ok(!html.includes("全部技能"));
32
+ });
33
+
34
+ test("时间筛选还在,且三个档位齐全", () => {
35
+ const html = form();
36
+ assert.ok(html.includes('name="range"'));
37
+ for (const label of ["最近 7 天", "最近 30 天", "全部时间"]) {
38
+ assert.ok(html.includes(`>${label}<`), `缺时间档位:${label}`);
39
+ }
40
+ });
41
+
42
+ test("表单仍是 GET,且保留 view", () => {
43
+ const html = form();
44
+ assert.ok(html.includes('method="get"'));
45
+ assert.ok(html.includes('<input type="hidden" name="view" value="pending">'));
46
+ });
47
+
48
+ test("参数没被删:URL 里的 skill / status 仍然生效", () => {
49
+ const parsed = parseListQuery(new URLSearchParams("skill=deploy-test&status=stale&range=30d"));
50
+ assert.equal(parsed.skill, "deploy-test");
51
+ assert.equal(parsed.status, "stale");
52
+ assert.equal(parsed.range, "30d");
53
+ });
54
+
55
+ test("技能页跳过来的链接照旧能带 skill 参数(只是不再有输入框)", () => {
56
+ const parsed = parseListQuery(new URLSearchParams("skill=ui-verify"));
57
+ const html = renderFilterForm("reports", parsed, EXTRAS);
58
+ assert.ok(!html.includes('name="skill"'));
59
+ assert.equal(parsed.skill, "ui-verify", "筛选逻辑要能吃到链接里的技能");
60
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-skill-evolve",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "技能进化:采集会话中的技能曝光/加载,异步复盘、生成改进提案并独立评审,附本机 Web 管理面板",
5
5
  "keywords": [
6
6
  "pi-package",