@hupan56/wlkj 2.4.1 → 2.4.3
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
|
@@ -59,6 +59,12 @@ the chosen platform, the user requirement, and the current developer name.
|
|
|
59
59
|
For simple requirements you may run the mode workflow inline instead of
|
|
60
60
|
dispatching — the steps are the same.
|
|
61
61
|
|
|
62
|
+
### 模式不确定时的兜底(必须遵守)
|
|
63
|
+
- 若用户意图跟 ≥2 个模式都沾边(如既像"分析"又像"规划")→ **先问用户**:
|
|
64
|
+
"这个需求我理解为 [X 模式],对吗?还是你想要 [Y/Z]?"
|
|
65
|
+
- 默认走 Reference 仅当用户明确给出需求描述且无探讨/创新/规划信号时。
|
|
66
|
+
- **宁可多问一句,不要错模式**(错模式的 PRD 是废纸,EVA 门禁只管格式不管方向)。
|
|
67
|
+
|
|
62
68
|
## Storage
|
|
63
69
|
|
|
64
70
|
Draft -> workspace/members/{developer}/drafts/REQ-{ID}-{desc}.md
|
|
@@ -112,6 +112,18 @@ if __name__ == '__main__':
|
|
|
112
112
|
try:
|
|
113
113
|
main()
|
|
114
114
|
except Exception as e:
|
|
115
|
+
# 落盘到日志 (stdout 一次性, 追溯用)
|
|
116
|
+
try:
|
|
117
|
+
from pathlib import Path
|
|
118
|
+
from datetime import datetime
|
|
119
|
+
log_path = Path(__file__).resolve().parents[1] / '.runtime' / 'hook-errors.log'
|
|
120
|
+
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
121
|
+
with open(log_path, 'a', encoding='utf-8') as f:
|
|
122
|
+
f.write('[{}] inject-workflow-state: {}\n'.format(
|
|
123
|
+
datetime.now().strftime('%Y-%m-%d %H:%M:%S'), str(e)[:200]))
|
|
124
|
+
except Exception:
|
|
125
|
+
pass
|
|
115
126
|
print('<qoder-workflow>')
|
|
116
127
|
print('hook error: ' + str(e)[:200])
|
|
128
|
+
print(' (详情见 .qoder/.runtime/hook-errors.log)')
|
|
117
129
|
print('</qoder-workflow>')
|
|
@@ -199,6 +199,18 @@ if __name__ == '__main__':
|
|
|
199
199
|
main()
|
|
200
200
|
except Exception as e:
|
|
201
201
|
# A broken hook must never kill the session - emit minimal context
|
|
202
|
+
# 同时落盘到日志, 方便后续排查 (stdout 一次性, AI 看完就没了)
|
|
203
|
+
try:
|
|
204
|
+
from pathlib import Path
|
|
205
|
+
log_path = Path(__file__).resolve().parents[1] / '.runtime' / 'hook-errors.log'
|
|
206
|
+
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
207
|
+
from datetime import datetime
|
|
208
|
+
with open(log_path, 'a', encoding='utf-8') as f:
|
|
209
|
+
f.write('[{}] session-start: {}\n'.format(
|
|
210
|
+
datetime.now().strftime('%Y-%m-%d %H:%M:%S'), str(e)[:200]))
|
|
211
|
+
except Exception:
|
|
212
|
+
pass # 日志写失败不影响降级
|
|
202
213
|
print('<qoder-context>')
|
|
203
214
|
print('session-start hook error: ' + str(e)[:200])
|
|
215
|
+
print(' (详情见 .qoder/.runtime/hook-errors.log)')
|
|
204
216
|
print('</qoder-context>')
|
|
@@ -215,7 +215,7 @@ def scan_secrets(file_paths: List[str], repo_root: str) -> None:
|
|
|
215
215
|
# 合法平台关键词 (出现在 PRD 内容里即视为已标注)
|
|
216
216
|
_PLATFORM_KEYWORDS = [
|
|
217
217
|
'web', 'pc', '管理端', 'fywl-ui', 'fywl_ui', 'vben', 'ant design',
|
|
218
|
-
'app', 'h5', '移动端', 'carmg', 'vant',
|
|
218
|
+
'app端', 'app移动端', 'h5', '移动端', 'carmg', 'vant', 'mobile',
|
|
219
219
|
'两端', '双端', 'both',
|
|
220
220
|
'后端', 'backend', '无前端',
|
|
221
221
|
]
|
|
@@ -293,6 +293,7 @@ def do_push(message=None, skip_eval=False, skip_secret=False):
|
|
|
293
293
|
dev = get_developer()
|
|
294
294
|
|
|
295
295
|
# === 文件锁: 串行化 push, 避免并发 stage/commit 交叉 ===
|
|
296
|
+
print('[team_sync] 推送产出(PRD/任务/索引), 不含源码. 源码改动用 /wl-commit')
|
|
296
297
|
os.makedirs(os.path.dirname(PUSH_LOCK), exist_ok=True)
|
|
297
298
|
try:
|
|
298
299
|
lock_ctx = FileLock(PUSH_LOCK, timeout=60, stale_seconds=300)
|
|
@@ -392,22 +393,44 @@ def _do_push_locked(message, dev, skip_eval, skip_secret):
|
|
|
392
393
|
|
|
393
394
|
|
|
394
395
|
def do_status():
|
|
396
|
+
# 性能优化: 合并 git 调用 (原 5 次 → 2 次)
|
|
397
|
+
# 一次 git status --branch --porcelain 拿到: 分支名 + ahead/behind + dirty 文件
|
|
398
|
+
r = git('status', '--branch', '--porcelain', '--', *SYNC_SCOPES)
|
|
395
399
|
branch = current_branch()
|
|
396
400
|
print('Branch: {}'.format(branch))
|
|
397
401
|
print('Developer: {}'.format(get_developer() or 'NOT SET'))
|
|
398
402
|
|
|
399
403
|
if not has_remote():
|
|
400
404
|
print('Remote: none (local-only mode)')
|
|
405
|
+
# 仍显示 dirty 文件
|
|
406
|
+
dirty = [l for l in r.stdout.strip().splitlines() if l.strip() and not l.startswith('##')]
|
|
407
|
+
if dirty:
|
|
408
|
+
print('未同步的本地产出: {} 个文件'.format(len(dirty)))
|
|
409
|
+
for l in dirty[:10]:
|
|
410
|
+
print(' ' + l)
|
|
401
411
|
return 0
|
|
402
412
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
413
|
+
# 从 status --branch 输出解析 ahead/behind (避免单独 fetch+rev-list)
|
|
414
|
+
for line in r.stdout.splitlines():
|
|
415
|
+
if line.startswith('## ') and '...' in line:
|
|
416
|
+
# 格式: ## master...origin/master [ahead 3, behind 1]
|
|
417
|
+
import re as _re
|
|
418
|
+
ahead_m = _re.search(r'ahead (\d+)', line)
|
|
419
|
+
behind_m = _re.search(r'behind (\d+)', line)
|
|
420
|
+
ahead = ahead_m.group(1) if ahead_m else '0'
|
|
421
|
+
behind = behind_m.group(1) if behind_m else '0'
|
|
422
|
+
print('Ahead (待推送): {}, Behind (待拉取): {}'.format(ahead, behind))
|
|
423
|
+
break
|
|
424
|
+
else:
|
|
425
|
+
# 没解析到 ahead/behind (可能需要 fetch), 回退到 rev-list
|
|
426
|
+
r2 = git('rev-list', '--left-right', '--count', 'origin/{}...HEAD'.format(branch))
|
|
427
|
+
if r2.returncode == 0 and r2.stdout.strip():
|
|
428
|
+
parts = r2.stdout.split()
|
|
429
|
+
if len(parts) == 2:
|
|
430
|
+
behind, ahead = parts
|
|
431
|
+
print('Ahead (待推送): {}, Behind (待拉取): {}'.format(ahead, behind))
|
|
432
|
+
|
|
433
|
+
dirty = [l for l in r.stdout.strip().splitlines() if l.strip() and not l.startswith('##')]
|
|
411
434
|
print('未同步的本地产出: {} 个文件'.format(len(dirty)))
|
|
412
435
|
for l in dirty[:10]:
|
|
413
436
|
print(' ' + l)
|