@hupan56/wlkj 2.4.5 → 2.4.7

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/bin/cli.js CHANGED
@@ -278,6 +278,17 @@ function doUpdate() {
278
278
 
279
279
  console.log(`\nwlkj update${oldVer ? " " + oldVer : ""} -> v${PKG_VERSION}\n`);
280
280
 
281
+ // P1-15: 显式声明 update 绝不触碰的路径
282
+ console.log(" 受保护路径 (绝不覆盖):");
283
+ console.log(" .qoder/config.yaml (团队 git 配置)");
284
+ console.log(" .qoder/settings.json (权限/hook 配置)");
285
+ console.log(" .qoder/.developer (你的身份)");
286
+ console.log(" .qoder/.current-task (当前任务)");
287
+ console.log(" .qoder/.engine-version (版本戳)");
288
+ console.log(" workspace/ (你的全部产出)");
289
+ console.log(" data/ (代码仓库+知识图谱)");
290
+ console.log("");
291
+
281
292
  // === 1. 刷新引擎文件(保护 config.yaml / settings.json)===
282
293
  let copied = 0, protectedN = 0, skipped = 0;
283
294
  if (fs.existsSync(qoderSrc)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hupan56/wlkj",
3
- "version": "2.4.5",
3
+ "version": "2.4.7",
4
4
  "description": "AI Product R&D Workflow - PRD/Prototype/Search/Task/Report",
5
5
  "bin": {
6
6
  "wlkj": "bin/cli.js"
@@ -37,21 +37,54 @@ WAIT for the answer. Platform determines everything downstream:
37
37
 
38
38
  | 用户怎么说 | 模式 | 做什么 | 出 PRD? | 出原型? |
39
39
  |-----------|------|--------|---------|---------|
40
- | 直接说需求(默认) | **Reference** 参考模式 | 参考现有代码+历史PRD,出标准PRD+原型 | | |
41
- | "探讨""聊聊""分析一下""我想做个XX不知道怎么做" | **Discuss** 探讨模式 | 纯讨论:理需求、拆问题、给方案建议,**不出PRD不出原型** | | |
42
- | "头脑风暴""brainstorm" | **Brainstorm** 头脑风暴 | SCAMPER+多agent调研,产出创新方案→PRD+原型 | ✅ | ✅ |
43
- | "规划""plan" | **Planning** 规划模式 | 现状分析+理想态+Gap+MVP路线图→PRD+原型 | ✅ | ✅ |
44
- | "快速""quick""加个字段""小改动" | **Quick** 快速模式 | 快速定位+Mini-PRD+微型原型(只改diff) | ✅ | ✅ |
40
+ | `/wl-prd discuss <需求>` 或 "探讨""聊聊" | **Discuss** 探讨模式 | 纯讨论:理需求、拆问题、给方案建议 | | |
41
+ | `/wl-prd <需求>`(默认)或 `/wl-prd reference <需求>` | **Reference** 参考模式 | 参考现有代码+历史PRD,出标准PRD+原型 | | |
42
+ | `/wl-prd brainstorm <需求>` 或 "头脑风暴" | **Brainstorm** 头脑风暴 | SCAMPER+多agent调研,产出创新方案→PRD+原型 | ✅ | ✅ |
43
+ | `/wl-prd plan <需求>` 或 "规划" | **Planning** 规划模式 | 现状分析+理想态+Gap+MVP路线图→PRD+原型 | ✅ | ✅ |
44
+ | `/wl-prd quick <需求>` 或 "快速""加个字段" | **Quick** 快速模式 | 快速定位+Mini-PRD+微型原型(只改diff) | ✅ | ✅ |
45
+
46
+ ### 模式路由规则(程序级优先)
47
+
48
+ 1. **显式参数优先**:用户输 `/wl-prd quick XX` → 强制 Quick 模式,不推断
49
+ 2. **关键词推断**:用户自然语言带"探讨/聊聊/快速/头脑风暴/规划" → 匹配对应模式
50
+ 3. **默认**:不带关键词 → Reference(参考模式)
51
+ 4. **兜底**:≥2 模式都沾边 → **先问用户**,不要猜
45
52
 
46
53
  ### 什么时候用哪个模式?
47
54
 
48
- - **不知道怎么做** → 探讨模式(先聊清楚再决定要不要出PRD)
49
- - **照着已有的做类似的** → 参考模式(默认)
55
+ - **不知道怎么做** → 探讨(先聊清楚再决定要不要出PRD)
56
+ - **照着已有的做类似的** → 参考(默认)
50
57
  - **想创新/没思路** → 头脑风暴
51
- - **大方向/季度规划** → 规划模式
52
- - **小功能/Bug fix** → 快速模式
58
+ - **大方向/季度规划** → 规划
59
+ - **小功能/Bug fix** → 快速
60
+
61
+ ### Discuss 转 Reference 的标记(审计用)
62
+
63
+ Discuss 结束、用户说"出PRD"时,AI 必须输出:
64
+ ```
65
+ [MODE-SWITCH: discuss→reference]
66
+ ```
67
+ 然后按 Reference 模式流程生成。
53
68
 
54
- > 探讨模式结束后,用户可以说"按这个方向出PRD"→ 自动转参考模式生成。
69
+ ### Quick 模式的特殊处理
70
+
71
+ Quick 模式生成的 PRD **头部必须标注 `mode: quick`**:
72
+ ```markdown
73
+ <!-- mode: quick -->
74
+ # Mini-PRD: {标题}
75
+ ```
76
+ syncgate 的 EVA 门禁检查到 `mode: quick` 时**跳过 A3(字段引用检查)**,
77
+ 因为 Mini-PRD 格式精简,A3 的表格字段检查不适用。
78
+ 其他检查(平台/REQ-ID/秘密)仍然生效。
79
+
80
+ ### Brainstorm 中间文件清理
81
+
82
+ Brainstorm 模式可能生成 `brainstorm-agent-*.md` 中间调研文件。
83
+ 生成最终 PRD 后**必须删除这些中间文件**:
84
+ ```bash
85
+ rm -f workspace/members/*/drafts/brainstorm-agent-*.md
86
+ ```
87
+ team_sync 的 staging allowlist 也会拒绝 `brainstorm-agent-*` 文件名。
55
88
 
56
89
  The agent files define the detailed workflow for each mode. When
57
90
  dispatching a sub-agent, ALWAYS include in the dispatch prompt:
@@ -97,6 +97,20 @@ GUIDE = {
97
97
 
98
98
  def main():
99
99
  tp, st = get_status()
100
+ # Hook-2: 如果任务/状态没变, 输出空 (减少 token 消耗)
101
+ # 用 .runtime/.last-workflow-state 存上次输出, mtime 变了才重新注入
102
+ state_file = os.path.join(BASE, '.qoder', '.runtime', '.last-wf-state.txt')
103
+ current_sig = '{}|{}'.format(tp or '', st or '')
104
+ try:
105
+ os.makedirs(os.path.dirname(state_file), exist_ok=True)
106
+ if os.path.isfile(state_file):
107
+ last_sig = open(state_file, 'r', encoding='utf-8').read().strip()
108
+ if last_sig == current_sig:
109
+ return # 状态没变, 不重复注入 (省 token)
110
+ open(state_file, 'w', encoding='utf-8').write(current_sig)
111
+ except OSError:
112
+ pass
113
+
100
114
  g = GUIDE.get(st, 'Status "{}" - check task.json, expected planning/in_progress/completed.'.format(st))
101
115
  parts = []
102
116
  parts.append('<qoder-workflow>')
@@ -76,6 +76,20 @@ def get_team_size():
76
76
 
77
77
  def get_index_info():
78
78
  lines = []
79
+ # Hook-3: 检查 hook 错误日志, 超过 3 条新错误时告警
80
+ try:
81
+ log_path = os.path.join(BASE, '.qoder', '.runtime', 'hook-errors.log')
82
+ if os.path.isfile(log_path):
83
+ with open(log_path, 'r', encoding='utf-8', errors='replace') as f:
84
+ errors = [l for l in f.readlines() if l.strip()]
85
+ # 只看最近 24h 的错误
86
+ recent = errors[-10:] # 取最后 10 行检查
87
+ if len(recent) >= 3:
88
+ lines.append('[WARN] hook 最近频繁失败 (%d 条错误), 详情见 .qoder/.runtime/hook-errors.log' % len(recent))
89
+ lines.append(' 跑 python .qoder/scripts/init_doctor.py --fix 排查')
90
+ except OSError:
91
+ pass
92
+
79
93
  lines.append('## Knowledge Index')
80
94
  lines.append('Use search script (DO NOT read large JSON files directly):')
81
95
  lines.append(' python .qoder/scripts/search_index.py <keyword> [--platform web|app]')
@@ -191,6 +205,9 @@ def main():
191
205
  parts.append(style_info)
192
206
 
193
207
  parts.append('</qoder-context>')
208
+ # Hook-1: 健康标记 — AI 能感知 hook 是否真的跑了
209
+ # QoderWork/Quest 里看不到 [hook-ok] 就知道 hook 没生效, 要自取上下文
210
+ parts.append('<!-- [hook-ok] session-start hook ran successfully -->')
194
211
  print(NL.join(parts))
195
212
 
196
213