@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 +11 -0
- package/package.json +1 -1
- package/templates/qoder/commands/wl-prd.md +43 -10
- package/templates/qoder/hooks/inject-workflow-state.py +14 -0
- package/templates/qoder/hooks/session-start.py +17 -0
- package/templates/qoder/scripts/git_sync.py +313 -641
- package/templates/qoder/scripts/syncgate.py +9 -0
- package/templates/qoder/scripts/team_sync.py +15 -5
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
|
@@ -37,21 +37,54 @@ WAIT for the answer. Platform determines everything downstream:
|
|
|
37
37
|
|
|
38
38
|
| 用户怎么说 | 模式 | 做什么 | 出 PRD? | 出原型? |
|
|
39
39
|
|-----------|------|--------|---------|---------|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
| "头脑风暴"
|
|
43
|
-
| "规划"
|
|
44
|
-
| "快速""
|
|
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
|
-
- **不知道怎么做** →
|
|
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
|
-
|
|
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
|
|