@hupan56/wlkj 3.1.18 → 3.1.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hupan56/wlkj",
3
- "version": "3.1.18",
3
+ "version": "3.1.20",
4
4
  "description": "AI Product R&D Workflow - PRD/Prototype/Search/Task/Report",
5
5
  "bin": {
6
6
  "wlkj": "bin/cli.js"
@@ -24,8 +24,9 @@ User input: $ARGUMENTS
24
24
  **先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
25
25
  ```bash
26
26
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
27
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
27
28
  ```
28
- > 后续脚本统一用 `python "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
29
+ > 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
29
30
 
30
31
  ---
31
32
 
@@ -53,7 +54,7 @@ R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_ro
53
54
  ## 🔒 通用前置(所有段必做)
54
55
 
55
56
  1. **身份**:读 `.qoder/.developer`,缺失 → 停下提示 `/wl-init`
56
- 2. **现状锚点**:`python "$R/.qoder/scripts/orchestration/wlkj.py" context <关键词> --platform <web|app>`(必跑,秒级)
57
+ 2. **现状锚点**:`$PY "$R/.qoder/scripts/orchestration/wlkj.py" context <关键词> --platform <web|app>`(必跑,秒级)
57
58
  3. **历史参考**:扫 `data/docs/prd/` 看已做过的,扫历史 insight 报告看是否聊过
58
59
 
59
60
  ---
@@ -97,9 +98,9 @@ R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_ro
97
98
 
98
99
  ```bash
99
100
  # Web 管理端
100
- python "$R/.qoder/scripts/orchestration/wlkj.py" fill-prototype "<刚才对焦到的业务关键词>" --platform web
101
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" fill-prototype "<刚才对焦到的业务关键词>" --platform web
101
102
  # APP 移动端
102
- python "$R/.qoder/scripts/orchestration/wlkj.py" fill-prototype "<刚才对焦到的业务关键词>" --platform app
103
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" fill-prototype "<刚才对焦到的业务关键词>" --platform app
103
104
  ```
104
105
  > fill-prototype 会按 platform 自动选 prototype-web.html / prototype-app.html 模板,
105
106
  > 用知识图谱里的真实字段/组件把模板填满, 输出到 drafts/。
@@ -15,8 +15,9 @@ User input: $ARGUMENTS
15
15
  **先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
16
16
  ```bash
17
17
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
18
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
18
19
  ```
19
- > 后续脚本统一用 `python "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`;所有仓库内相对路径(workspace/、data/code/)都前置 `"$R/"`。
20
+ > 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`;所有仓库内相对路径(workspace/、data/code/)都前置 `"$R/"`。
20
21
 
21
22
  ## CRITICAL: Data Isolation
22
23
 
@@ -39,8 +40,8 @@ If no developer is set, refuse and say "Run /wl-init first".
39
40
 
40
41
  ```bash
41
42
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
42
- python "$R/.qoder/scripts/orchestration/wlkj.py" report-snapshot "$R" # 日报(今天)
43
- python "$R/.qoder/scripts/orchestration/wlkj.py" report-snapshot "$R" --days 7 # 周报(近7天)
43
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" report-snapshot "$R" # 日报(今天)
44
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" report-snapshot "$R" --days 7 # 周报(近7天)
44
45
  ```
45
46
 
46
47
  一个命令返回 JSON,**5 个数据源已全部按当前开发者过滤**:
@@ -15,8 +15,9 @@ User input: $ARGUMENTS (default: show current status)
15
15
  **先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
16
16
  ```bash
17
17
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
18
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
18
19
  ```
19
- > 后续脚本统一用 `python "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`;仓库内相对路径都前置 `"$R/"`。
20
+ > 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`;仓库内相对路径都前置 `"$R/"`。
20
21
 
21
22
  ## Scopes
22
23
  - (no arg or "current") -> Current sprint status
@@ -69,7 +70,7 @@ Calculate from:
69
70
  | EVA quality trend | 25% | tail data/learning/eval-history.jsonl (avg score_pct, target >=80) |
70
71
  | Index freshness | 20% | data/index/.index-meta.json last_sync (<=7 days) + verify checks |
71
72
  | On-time delivery | 20% | task completion dates |
72
- | Sync health | 15% | python "$R/.qoder/scripts/orchestration/wlkj.py" sync status (ahead/behind/dirty) |
73
+ | Sync health | 15% | $PY "$R/.qoder/scripts/orchestration/wlkj.py" sync status (ahead/behind/dirty) |
73
74
  | Pipeline flow | 10% | PRD->Spec->Code conversion |
74
75
  | Learning growth | 10% | learning/patterns/ entries |
75
76
 
@@ -15,8 +15,9 @@ User input: $ARGUMENTS
15
15
  **先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
16
16
  ```bash
17
17
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
18
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
18
19
  ```
19
- > 后续脚本统一用 `python "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
20
+ > 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
20
21
 
21
22
  ## Step 1: Load Spec
22
23
 
@@ -26,7 +27,7 @@ Read the spec file to understand requirements.
26
27
 
27
28
  ## Step 2: Search Related Code
28
29
 
29
- Run: python "$R/.qoder/scripts/orchestration/wlkj.py" search <keyword>
30
+ Run: $PY "$R/.qoder/scripts/orchestration/wlkj.py" search <keyword>
30
31
  Find existing code that this implementation relates to.
31
32
  Read relevant files for context.
32
33
 
@@ -121,7 +121,8 @@ cap.mcp.call("context_pack", {"keyword": "<功能名>", "platform": "web"})
121
121
 
122
122
  评审输出后,记录到 learning:
123
123
  > 先定位仓库根 `R`(Mac 只有 python3, 两个都试):
124
- > `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.`
124
+ > `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
125
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)`
125
126
  ```bash
126
- python "$R/.qoder/scripts/orchestration/wlkj.py" learn record review_done "{\"target\":\"$feature\",\"result\":\"$pass_or_issues\"}"
127
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" learn record review_done "{\"target\":\"$feature\",\"result\":\"$pass_or_issues\"}"
127
128
  ```
@@ -18,8 +18,9 @@ Usage:
18
18
  **先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
19
19
  ```bash
20
20
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
21
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
21
22
  ```
22
- > `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。后续脚本统一用 `python "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
23
+ > `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
23
24
 
24
25
  ## Engine: init_doctor.py (幂等, 增量, 永不重头再来)
25
26
 
@@ -28,7 +29,7 @@ R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_ro
28
29
 
29
30
  ### Case 1: /wl-init (no arguments)
30
31
  ```bash
31
- python "$R/.qoder/scripts/orchestration/wlkj.py" doctor
32
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" doctor 2>/dev/null || python3 "$R/.qoder/scripts/orchestration/wlkj.py" doctor
32
33
  ```
33
34
  Report the doctor's findings to the user in friendly language.
34
35
  If it found fixable issues, ask: "发现 N 个问题,要我自动修复吗?"
@@ -36,7 +37,7 @@ then run with --fix.
36
37
 
37
38
  ### Case 2/3: /wl-init 小王 [pm]
38
39
  ```bash
39
- python "$R/.qoder/scripts/orchestration/wlkj.py" doctor --fix 小王 [pm]
40
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" doctor 2>/dev/null || python3 "$R/.qoder/scripts/orchestration/wlkj.py" doctor --fix 小王 [pm]
40
41
  ```
41
42
  This single command does ALL of:
42
43
  1. 注册/切换开发者 (.qoder/.developer, key=value 格式) + 个人空间目录
@@ -46,9 +46,10 @@ User input: $ARGUMENTS
46
46
  先定位仓库根(Mac 只有 python3, 两个都试):
47
47
  ``bash
48
48
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
49
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
49
50
  ``
50
51
  ``bash
51
- python "$R/.qoder/scripts/orchestration/wlkj.py" context <业务词> --platform <web|app>
52
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" context <业务词> --platform <web|app>
52
53
  ``
53
54
  - 第 4 段 = 历史 PRD(防重复)
54
55
  - 第 5 段 = 相关 API
@@ -75,7 +76,7 @@ eval 自动跳过 A2(满分从 100 降到 70,照样 PASS);`/wl-design` `
75
76
 
76
77
  ### 质量门禁
77
78
  ``bash
78
- python "$R/.qoder/scripts/orchestration/wlkj.py" eval <prd.md> [原型.html]
79
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" eval <prd.md> [原型.html]
79
80
  ``
80
81
  ≥ 80% 才 PASS。完整模板见 `.qoder/templates/prd-full-template.md`。
81
82
 
@@ -106,7 +107,7 @@ python "$R/.qoder/scripts/orchestration/wlkj.py" eval <prd.md> [原型.html]
106
107
  - 影响范围是否评估
107
108
  - 非功能性需求是否覆盖
108
109
  - ...
109
- 3. 跑 EVA 评分:`python "$R/.qoder/scripts/orchestration/wlkj.py" eval <prd.md>`(wlkj.py eval 内部映射 validation/metrics/eval_prd.py)
110
+ 3. 跑 EVA 评分:`$PY "$R/.qoder/scripts/orchestration/wlkj.py" eval <prd.md>`(wlkj.py eval 内部映射 validation/metrics/eval_prd.py)
110
111
  4. 输出:总分 + 7 项 ✓/✗ + 改进建议
111
112
 
112
113
  ---
@@ -1,47 +1,48 @@
1
- ---
2
- name: wl-req
3
- description: "需求管理: 看需求/看产出/发布"
4
- argument-hint: "[REQ-ID] [发布]"
5
- ---
6
-
7
- # /wl-req 需求生命周期管理
8
-
9
- > 一个需求的所有产出(PRD/原型/任务/规格)聚合在 REQ-ID 容器, 一条命令看全貌。
10
-
11
- ## 用法 (只需记 2 个姿势)
12
-
13
- | 输入 | 做什么 |
14
- |------|--------|
15
- | `/wl-req` | 列出所有需求 (跨草稿/产出/历史桶) |
16
- | `/wl-req REQ-2026-001` | 显示该需求的全部产出 |
17
- | `/wl-req REQ-2026-001 发布` | 草稿→产出→发禅道 (一步到位) |
18
-
19
- ## 实现层
20
-
21
- > 先定位仓库根 `R`(Mac 只有 python3, 两个都试; 失败回退 `.` 即当前工作目录):
22
- > `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.`
23
-
24
- ```bash
25
- # 列需求
26
- python "$R/.qoder/scripts/orchestration/wlkj.py" req
27
-
28
- # 看某需求全貌
29
- python "$R/.qoder/scripts/orchestration/wlkj.py" req REQ-2026-001
30
-
31
- # 发布 (promote + publish)
32
- python "$R/.qoder/scripts/orchestration/wlkj.py" req REQ-2026-001 发布
33
- ```
34
-
35
- ## 结构
36
-
37
- ```
38
- workspace/members/{dev}/
39
- ├── drafts/2026/06/W26/REQ-2026-001/ ← 草稿(私有)
40
- ├── prd.md
41
- │ ├── prototype.html
42
- └── tasks/
43
- ├── outputs/2026/06/W26/REQ-2026-001/ ← 产出(团队可见, 发布后)
44
- │ └── exports/ (docx/pdf)
45
- ```
46
-
47
- 时间桶(YYYY/MM/Ww)内建: 本周=活动区, 历史=过去的桶, 无独立 archive。
1
+ ---
2
+ name: wl-req
3
+ description: "需求管理: 看需求/看产出/发布"
4
+ argument-hint: "[REQ-ID] [发布]"
5
+ ---
6
+
7
+ # /wl-req 需求生命周期管理
8
+
9
+ > 一个需求的所有产出(PRD/原型/任务/规格)聚合在 REQ-ID 容器, 一条命令看全貌。
10
+
11
+ ## 用法 (只需记 2 个姿势)
12
+
13
+ | 输入 | 做什么 |
14
+ |------|--------|
15
+ | `/wl-req` | 列出所有需求 (跨草稿/产出/历史桶) |
16
+ | `/wl-req REQ-2026-001` | 显示该需求的全部产出 |
17
+ | `/wl-req REQ-2026-001 发布` | 草稿→产出→发禅道 (一步到位) |
18
+
19
+ ## 实现层
20
+
21
+ > 先定位仓库根 `R`(Mac 只有 python3, 两个都试; 失败回退 `.` 即当前工作目录):
22
+ > `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
23
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)`
24
+
25
+ ```bash
26
+ # 列需求
27
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" req
28
+
29
+ # 看某需求全貌
30
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" req REQ-2026-001
31
+
32
+ # 发布 (promote + publish)
33
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" req REQ-2026-001 发布
34
+ ```
35
+
36
+ ## 结构
37
+
38
+ ```
39
+ workspace/members/{dev}/
40
+ ├── drafts/2026/06/W26/REQ-2026-001/ ← 草稿(私有)
41
+ │ ├── prd.md
42
+ ├── prototype.html
43
+ │ └── tasks/
44
+ ├── outputs/2026/06/W26/REQ-2026-001/ ← 产出(团队可见, 发布后)
45
+ │ └── exports/ (docx/pdf)
46
+ ```
47
+
48
+ 时间桶(YYYY/MM/Ww)内建: 本周=活动区, 历史=过去的桶, 无独立 archive。
@@ -98,10 +98,11 @@ cap.mcp.call("search_code", {"keyword": "--components"}) # 组件使用
98
98
 
99
99
  **中文文案/报错溯源**(用户查的是中文短语),**唯一合法方式**:
100
100
  > 先定位仓库根 `R`(Mac 只有 python3, 两个都试):
101
- > `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.`
101
+ > `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
102
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)`
102
103
  ```bash
103
104
  # grep-text 走 CLI 降级(不是 MCP 工具)
104
- python "$R/.qoder/scripts/orchestration/wlkj.py" kg grep-text 车辆不存在 --ext java --limit 20
105
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" kg grep-text 车辆不存在 --ext java --limit 20
105
106
  ```
106
107
 
107
108
  ## How to Use Results
@@ -20,8 +20,9 @@ User input: $ARGUMENTS
20
20
  **先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
21
21
  ```bash
22
22
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
23
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
23
24
  ```
24
- > 后续脚本统一用 `python "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
25
+ > 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
25
26
 
26
27
  ---
27
28
 
@@ -163,12 +164,12 @@ ls data/docs/prd/REQ-*.md 2>/dev/null
163
164
  # 先 list_executions() 列候选执行让用户选 → create_task(execution_id=<EID>,
164
165
  # name=<任务名>, assignedTo=<账号>, type=devel/test/design, estimate=<h>, story=<需求ID>)
165
166
  # 3. 同步一份到本地缓存(增强字段层用):
166
- # python "$R/.qoder/scripts/domain/task/task.py" create "<标题>" --priority <P0|P1|P2|P3>
167
+ # $PY "$R/.qoder/scripts/domain/task/task.py" create "<标题>" --priority <P0|P1|P2|P3>
167
168
  ```
168
169
 
169
170
  **本地走法(禅道不可达 / 用户要离线时):**
170
171
  ```bash
171
- python "$R/.qoder/scripts/domain/task/task.py" create "<标题>" --priority <P0|P1|P2|P3>
172
+ $PY "$R/.qoder/scripts/domain/task/task.py" create "<标题>" --priority <P0|P1|P2|P3>
172
173
  ```
173
174
  - `--assignee` 不填则默认当前开发者(产品建的常指派给开发,可加 `--assignee 老李`)。
174
175
  - `--slug` 不填则自动从标题生成(中文标题也能生成,但建议给个英文 slug 如 `--slug login-export`)。
@@ -180,7 +181,7 @@ python "$R/.qoder/scripts/domain/task/task.py" create "<标题>" --priority <P0|
180
181
  2. **待排期池 >3 个任务时**,主动建议:"要不要我跑个 rank 排下优先级?"
181
182
  3. 自动同步(用户永不碰 git):
182
183
  ```bash
183
- python "$R/.qoder/scripts/domain/task/team_sync.py" push
184
+ $PY "$R/.qoder/scripts/domain/task/team_sync.py" push
184
185
  ```
185
186
 
186
187
  ### list —— 看任务(一次取全,别串行)
@@ -196,7 +197,7 @@ qw_mcp_call("list_my_tasks", {"status":"doing"}) ← 只看我进行中的
196
197
 
197
198
  **本地走法(离线缓存 / 禅道不可达):**
198
199
  ```bash
199
- python "$R/.qoder/scripts/domain/task/task.py" list [--mine] [--status <s>] [--ready] [--blocked]
200
+ $PY "$R/.qoder/scripts/domain/task/task.py" list [--mine] [--status <s>] [--ready] [--blocked]
200
201
  ```
201
202
 
202
203
  | flag | 用途 |
@@ -217,14 +218,14 @@ python "$R/.qoder/scripts/domain/task/task.py" list [--mine] [--status <s>] [--r
217
218
  ### show —— 看单个任务详情
218
219
 
219
220
  **禅道走法(QoderWork):** `qw_mcp_call("get_task", {"task_id": <禅道ID>})` ← 含工时预计/消耗/剩余/关联需求
220
- **本地走法:** `python "$R/.qoder/scripts/domain/task/task.py" show <任务名或目录>`
221
+ **本地走法:** `$PY "$R/.qoder/scripts/domain/task/task.py" show <任务名或目录>`
221
222
 
222
223
  任务名支持模糊匹配(脚本内部 `resolve_task_dir` 会解析)。读完把关键字段(状态/优先级/assignee/due/依赖/prd路径)整理给用户。
223
224
 
224
225
  ### start —— 启动任务(移交开发工位的信号)
225
226
 
226
227
  **禅道走法(QoderWork,优先):** `qw_mcp_call("start_task", {"task_id": <禅道ID>, "left": <剩余工时h>})`
227
- **本地走法:** `python "$R/.qoder/scripts/domain/task/task.py" start <任务名>`
228
+ **本地走法:** `$PY "$R/.qoder/scripts/domain/task/task.py" start <任务名>`
228
229
  - 状态 `planning → in_progress`,成为活跃任务(`.current-task`)。
229
230
  - 这是产品→开发的交接点:start 后开发就能 `/wl-code` 了。
230
231
  - **ACL**:只有 creator/assignee/admin 能 start。被拒(返回 4)→ 提示找对应人。
@@ -234,7 +235,7 @@ python "$R/.qoder/scripts/domain/task/task.py" list [--mine] [--status <s>] [--r
234
235
 
235
236
  **禅道走法(QoderWork):** `qw_mcp_call("assign_task", {"task_id": <禅道ID>, "account": <禅道账号>})`
236
237
  - 账号先用 `qw_mcp_call("list_users", {})` 列候选让用户选(**列表勾选式**)。
237
- **本地走法:** `python "$R/.qoder/scripts/domain/task/task.py" reassign <任务名> <新负责人>`
238
+ **本地走法:** `$PY "$R/.qoder/scripts/domain/task/task.py" reassign <任务名> <新负责人>`
238
239
  - 场景:PM 建任务(assignee 默认是自己)后,要转给开发老李做。
239
240
  - 改派后新负责人才能 `start`/`finish`(零信任 ACL 按 assignee 判定)。
240
241
  - **ACL**:只有 **creator/admin** 能改派(assignee 自己不能转手甩锅)。被拒(返回 4)→ 提示找 creator。
@@ -243,13 +244,13 @@ python "$R/.qoder/scripts/domain/task/task.py" list [--mine] [--status <s>] [--r
243
244
 
244
245
  **禅道走法(QoderWork,优先):** `qw_mcp_call("finish_task", {"task_id": <禅道ID>, "consumed": <本次消耗h>, "left": 0})`
245
246
  - 禅道要求填消耗工时,**先问用户"这次花了多少小时?"** 再调。
246
- **本地走法:** `python "$R/.qoder/scripts/domain/task/task.py" finish` → 然后 `team_sync.py push`
247
+ **本地走法:** `$PY "$R/.qoder/scripts/domain/task/task.py" finish` → 然后 `team_sync.py push`
247
248
  - 活跃任务状态 → `completed`,活跃指针清除。
248
249
  - 完成后提示:要不要 `archive` 归档?要不要看下个 `--ready` 的任务?
249
250
 
250
251
  ### archive —— 归档(移到 .qoder/archive/{YYYY-MM}/})
251
252
 
252
- **本地走法:** `python "$R/.qoder/scripts/domain/task/task.py" archive <任务名>`
253
+ **本地走法:** `$PY "$R/.qoder/scripts/domain/task/task.py" archive <任务名>`
253
254
  - 事务化:先 move 成功再改 status,move 失败原任务完好。
254
255
  - **自动清理孤儿依赖**:归档后,其它任务里对它的 `blocked_by/blocks/children/parent` 引用会被扫除(防止僵尸任务永远 blocked)。
255
256
  - 提示用户:归档后任务不再出现在 list 里,但归档目录可翻历史。
@@ -446,14 +447,14 @@ AI: 拆任务(列表勾选式, 跨执行多选):
446
447
 
447
448
  ```bash
448
449
  # 看同步状态(只读:本地哪些任务关联了禅道,哪些待推)
449
- python "$R/.qoder/scripts/domain/task/zentao_sync.py" status
450
+ $PY "$R/.qoder/scripts/domain/task/zentao_sync.py" status
450
451
 
451
452
  # 推送本地任务到禅道(先 dry-run 预览)
452
- python "$R/.qoder/scripts/domain/task/zentao_sync.py" push --execution_id <执行ID> # 预览
453
- python "$R/.qoder/scripts/domain/task/zentao_sync.py" push --execution_id <执行ID> --apply # 真推
453
+ $PY "$R/.qoder/scripts/domain/task/zentao_sync.py" push --execution_id <执行ID> # 预览
454
+ $PY "$R/.qoder/scripts/domain/task/zentao_sync.py" push --execution_id <执行ID> --apply # 真推
454
455
 
455
456
  # 拉取禅道任务到本地(仅 assignedTo=我,队友的拉不进来)
456
- python "$R/.qoder/scripts/domain/task/zentao_sync.py" pull <执行ID> --apply
457
+ $PY "$R/.qoder/scripts/domain/task/zentao_sync.py" pull <执行ID> --apply
457
458
  ```
458
459
 
459
460
  **安全保证(脚本强制,不靠 AI 自觉):**
@@ -473,7 +474,7 @@ python "$R/.qoder/scripts/domain/task/zentao_sync.py" pull <执行ID> --apply
473
474
 
474
475
  ### 一次取全(别逐个问)
475
476
  ```bash
476
- python "$R/.qoder/scripts/domain/task/task.py" list --status planning
477
+ $PY "$R/.qoder/scripts/domain/task/task.py" list --status planning
477
478
  ```
478
479
  拿到所有待排任务,**一次性**评估,不要一个任务问四轮 R/I/C/E。
479
480
 
@@ -504,23 +505,23 @@ python "$R/.qoder/scripts/domain/task/task.py" list --status planning
504
505
 
505
506
  ### 设置截止日期
506
507
  ```bash
507
- python "$R/.qoder/scripts/orchestration/wlkj.py" task set-due <任务名> <YYYY-MM-DD>
508
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" task set-due <任务名> <YYYY-MM-DD>
508
509
  ```
509
510
 
510
511
  ### 依赖关系(谁挡谁)
511
512
  ```bash
512
513
  # A 被 B 阻塞(要等 B 完成)
513
- python "$R/.qoder/scripts/orchestration/wlkj.py" task block <A任务名> <B任务名>
514
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" task block <A任务名> <B任务名>
514
515
  # 解除
515
- python "$R/.qoder/scripts/orchestration/wlkj.py" task unblock <A任务名> <B任务名>
516
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" task unblock <A任务名> <B任务名>
516
517
  ```
517
518
  - **循环依赖自动检测**:脚本会 BFS 检查,发现环就拒绝(返回 1)。
518
519
  - 反向 `blocks` 关系自动维护(A 被 B 阻塞时,B 的 blocks 自动加 A)。
519
520
 
520
521
  ### 看甘特图
521
522
  ```bash
522
- python "$R/.qoder/scripts/domain/task/team_sync.py" push
523
- python "$R/.qoder/scripts/orchestration/wlkj.py" task gantt [--weeks 4]
523
+ $PY "$R/.qoder/scripts/domain/task/team_sync.py" push
524
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" task gantt [--weeks 4]
524
525
  ```
525
526
  - 只排有 `start_date`/`due_date` 的任务。
526
527
  - 没日期的任务 → 提示:"用 `set-due` 给任务加截止日期,甘特图才会显示。"
@@ -532,8 +533,8 @@ python "$R/.qoder/scripts/orchestration/wlkj.py" task gantt [--weeks 4]
532
533
 
533
534
  ```bash
534
535
  # 把大任务 A 拆出子任务 B
535
- python "$R/.qoder/scripts/orchestration/wlkj.py" task add-subtask <A任务名> <B任务名>
536
- python "$R/.qoder/scripts/orchestration/wlkj.py" task remove-subtask <A任务名> <B任务名>
536
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" task add-subtask <A任务名> <B任务名>
537
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" task remove-subtask <A任务名> <B任务名>
537
538
  ```
538
539
  - 父任务记录 `children`,子任务记录 `parent`。
539
540
  - 产品用:把一个大需求拆成"前端/后端/数据"几个子任务,各自指派。
@@ -17,8 +17,9 @@ User input: $ARGUMENTS
17
17
  **先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
18
18
  ```bash
19
19
  R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
20
+ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
20
21
  ```
21
- > 后续脚本统一用 `python "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
22
+ > 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
22
23
 
23
24
  ## 🚦 第一步:路由(看用户输入,立刻决定走哪条线)
24
25
 
@@ -55,7 +56,7 @@ R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_ro
55
56
 
56
57
  **Step 0:recall 查锚点(用相对 URL)。**
57
58
  ```bash
58
- python "$R/.qoder/scripts/orchestration/wlkj.py" test recall --url auth/login
59
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" test recall --url auth/login
59
60
  ```
60
61
  - 有锚点 → 直接填进用例 anchor(零 LLM)
61
62
  - 无锚点(首次)→ **先 navigate + snapshot 拿真实 a11y 树,从里面提取 anchor**,禁止预猜 selector
@@ -76,7 +77,7 @@ python "$R/.qoder/scripts/orchestration/wlkj.py" test recall --url auth/login
76
77
  **Step 2:调脚本,注入数据 + 出执行计划:**
77
78
  ```bash
78
79
  # AI 先把用例 JSON 写文件, 再传路径 (--cases-file, 不截断)
79
- python "$R/.qoder/scripts/orchestration/wlkj.py" test quick \
80
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" test quick \
80
81
  --cases-file <文件路径> \
81
82
  --desc "<用户描述>" --platform <web|app>
82
83
  ```
@@ -87,7 +88,7 @@ python "$R/.qoder/scripts/orchestration/wlkj.py" test quick \
87
88
  脚本只出计划,不自己开浏览器。批量加载 browser_* 工具后按执行计划连发操作。
88
89
  跑完回传结果出报告:
89
90
  ```bash
90
- python "$R/.qoder/scripts/orchestration/wlkj.py" test quick --record '{"Q-1":"pass","Q-2":"fail"}'
91
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" test quick --record '{"Q-1":"pass","Q-2":"fail"}'
91
92
  ```
92
93
 
93
94
  ---
@@ -98,10 +99,10 @@ python "$R/.qoder/scripts/orchestration/wlkj.py" test quick --record '{"Q-1":"pa
98
99
 
99
100
  ```bash
100
101
  cap.mcp.call("list_tasks", {}) # 确认任务
101
- python "$R/.qoder/scripts/orchestration/wlkj.py" test generate <task> # 生成骨架
102
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" test generate <task> # 生成骨架
102
103
  # AI 读任务 PRD「验收标准」补全 steps/expected(真实数据用 {{ask:}})
103
- python "$R/.qoder/scripts/orchestration/wlkj.py" test run <task> # 注入+出执行计划
104
- python "$R/.qoder/scripts/orchestration/wlkj.py" test run <task> --record '{"..":"pass"}' # 回收结果
104
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" test run <task> # 注入+出执行计划
105
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" test run <task> --record '{"..":"pass"}' # 回收结果
105
106
  ```
106
107
 
107
108
  ---