@hupan56/wlkj 3.0.0 → 3.1.2
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 +1435 -1373
- package/package.json +1 -1
- package/templates/qoder/commands/optional/wl-insight.md +6 -4
- package/templates/qoder/commands/optional/wl-report.md +20 -39
- package/templates/qoder/commands/optional/wl-status.md +4 -4
- package/templates/qoder/commands/wl-code.md +2 -2
- package/templates/qoder/commands/wl-design.md +5 -5
- package/templates/qoder/commands/wl-init.md +3 -3
- package/templates/qoder/commands/wl-prd.md +26 -13
- package/templates/qoder/commands/wl-req.md +3 -3
- package/templates/qoder/commands/wl-search.md +78 -47
- package/templates/qoder/commands/wl-task.md +343 -40
- package/templates/qoder/commands/wl-test.md +10 -10
- package/templates/qoder/config.yaml +35 -13
- package/templates/qoder/hooks/post-tool-use.py +181 -0
- package/templates/qoder/hooks/session-start.py +82 -1
- package/templates/qoder/hooks/stop-eval.py +207 -0
- package/templates/qoder/hooks/user-prompt-submit.py +139 -0
- package/templates/qoder/rules/wl-pipeline.md +70 -8
- package/templates/qoder/scripts/README.md +78 -115
- package/templates/qoder/scripts/capability/__init__.py +26 -0
- package/templates/qoder/scripts/capability/__main__.py +72 -0
- package/templates/qoder/scripts/capability/adapters/__init__.py +29 -0
- package/templates/qoder/scripts/capability/adapters/cli.py +316 -0
- package/templates/qoder/scripts/capability/adapters/mcp.py +334 -0
- package/templates/qoder/scripts/capability/adapters/qw.py +271 -0
- package/templates/qoder/scripts/capability/caps/__init__.py +27 -0
- package/templates/qoder/scripts/capability/caps/context.py +36 -0
- package/templates/qoder/scripts/capability/caps/cron.py +50 -0
- package/templates/qoder/scripts/capability/caps/identity.py +43 -0
- package/templates/qoder/scripts/capability/caps/memory.py +71 -0
- package/templates/qoder/scripts/capability/caps/notify.py +41 -0
- package/templates/qoder/scripts/capability/caps/present.py +48 -0
- package/templates/qoder/scripts/capability/caps/repo.py +31 -0
- package/templates/qoder/scripts/capability/caps/sandbox.py +43 -0
- package/templates/qoder/scripts/capability/chain.py +92 -0
- package/templates/qoder/scripts/capability/memory_chain.py +41 -0
- package/templates/qoder/scripts/capability/registry.py +246 -0
- package/templates/qoder/scripts/capability/registry_mcp.py +250 -0
- package/templates/qoder/scripts/capability/smoke_test.py +211 -0
- package/templates/qoder/scripts/capability/smoke_test_report.json +94 -0
- package/templates/qoder/scripts/{report → deployment/setup}/__init__.py +11 -11
- package/templates/qoder/scripts/{setup → deployment/setup}/carriers.py +33 -26
- package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
- package/templates/qoder/scripts/{setup → deployment/setup}/init_doctor.py +40 -16
- package/templates/qoder/scripts/{setup → deployment/setup}/install_qoderwork.py +20 -12
- package/templates/qoder/scripts/{setup → deployment/setup}/platform_doctor.py +8 -2
- package/templates/qoder/scripts/{setup → deployment/setup}/repo_root.py +113 -112
- package/templates/qoder/scripts/{setup → deployment/setup}/setup.py +31 -11
- package/templates/qoder/scripts/{setup → deployment/setup}/setup_lanhu.py +13 -7
- package/templates/qoder/scripts/domain/__init__.py +0 -0
- package/templates/qoder/scripts/domain/design/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/design}/fill_prototype.py +12 -6
- package/templates/qoder/scripts/{report → domain/design}/gen_design_doc.py +8 -2
- package/templates/qoder/scripts/{setup → domain/kg}/__init__.py +11 -11
- package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_entity_registry.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_relations.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_style_index.py +13 -7
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_workflows.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build.py +76 -9
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build_db.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_incremental.py +11 -6
- package/templates/qoder/scripts/{report → domain/kg/build}/learn_aggregate.py +9 -4
- package/templates/qoder/scripts/domain/kg/extract/__init__.py +0 -0
- package/templates/qoder/scripts/{common → domain/kg/extract}/extract.py +430 -419
- package/templates/qoder/scripts/{common → domain/kg/extract}/test_extract.py +115 -115
- package/templates/qoder/scripts/{common → domain/kg/extract}/ts_extract.py +614 -536
- package/templates/qoder/scripts/domain/kg/graph/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/graph}/kg_link_db.py +7 -2
- package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
- package/templates/qoder/scripts/{kg → domain/kg}/kg.py +263 -30
- package/templates/qoder/scripts/{common → domain/kg}/kg_capabilities.py +182 -182
- package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/search}/context_pack.py +30 -9
- package/templates/qoder/scripts/{kg → domain/kg/search}/enrich_prompt.py +10 -4
- package/templates/qoder/scripts/{kg → domain/kg/search}/prefetch.py +33 -8
- package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
- package/templates/qoder/scripts/{kg → domain/kg/search}/search_index.py +143 -77
- package/templates/qoder/scripts/domain/kg/server/__init__.py +0 -0
- package/templates/qoder/scripts/domain/kg/server/kgd.py +549 -0
- package/templates/qoder/scripts/domain/kg/server/perf_bench.py +197 -0
- package/templates/qoder/scripts/domain/kg/storage/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/storage}/kg_duckdb.py +38 -14
- package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/learning}/learn.py +8 -3
- package/templates/qoder/scripts/{mcp → domain/report}/__init__.py +11 -11
- package/templates/qoder/scripts/{report → domain/report}/add_session.py +9 -3
- package/templates/qoder/scripts/{report → domain/report}/export.py +10 -5
- package/templates/qoder/scripts/{report → domain/report}/report.py +9 -4
- package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
- package/templates/qoder/scripts/{report → domain/report}/role.py +10 -4
- package/templates/qoder/scripts/{report → domain/report}/status.py +112 -9
- package/templates/qoder/scripts/domain/report/status_snapshot.py +191 -0
- package/templates/qoder/scripts/domain/requirement/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/requirement}/archive_prd.py +8 -2
- package/templates/qoder/scripts/{report → domain/requirement}/req.py +228 -222
- package/templates/qoder/scripts/{kg → domain/task}/__init__.py +11 -11
- package/templates/qoder/scripts/{task → domain/task}/git_sync.py +40 -21
- package/templates/qoder/scripts/{task → domain/task}/syncgate.py +13 -8
- package/templates/qoder/scripts/{task → domain/task}/task.py +13 -5
- package/templates/qoder/scripts/{task → domain/task}/task_lifecycle.py +606 -596
- package/templates/qoder/scripts/{task → domain/task}/task_query.py +162 -161
- package/templates/qoder/scripts/{task → domain/task}/task_relations.py +425 -424
- package/templates/qoder/scripts/{task → domain/task}/team_sync.py +9 -4
- package/templates/qoder/scripts/domain/task/zentao_sync.py +370 -0
- package/templates/qoder/scripts/foundation/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation}/bootstrap.py +10 -10
- package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/core}/cmd_registry.py +1 -1
- package/templates/qoder/scripts/{common → foundation/core}/config.py +1 -1
- package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -586
- package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/data}/contract.py +2 -2
- package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
- package/templates/qoder/scripts/{common → foundation/data}/result.py +1 -1
- package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -404
- package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/identity}/check_publish.py +103 -98
- package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -239
- package/templates/qoder/scripts/{common → foundation/identity}/guard.py +2 -2
- package/templates/qoder/scripts/{common → foundation/identity}/identity.py +14 -10
- package/templates/qoder/scripts/{common → foundation/identity}/roles.py +1 -1
- package/templates/qoder/scripts/foundation/integrations/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/integrations}/active_task.py +30 -15
- package/templates/qoder/scripts/{common → foundation/integrations}/feishu.py +2 -2
- package/templates/qoder/scripts/{common → foundation/integrations}/terms.py +3 -3
- package/templates/qoder/scripts/foundation/integrations/zentao_client.py +220 -0
- package/templates/qoder/scripts/foundation/io/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/io}/filelock.py +1 -1
- package/templates/qoder/scripts/{common → foundation/io}/reqid.py +1 -1
- package/templates/qoder/scripts/foundation/protocol/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/protocol/duckdb_conn.py +39 -0
- package/templates/qoder/scripts/{common → foundation/protocol}/mcp_base.py +1 -1
- package/templates/qoder/scripts/foundation/utils/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/utils}/eval_api.py +12 -1
- package/templates/qoder/scripts/{common → foundation/utils}/pip_install.py +23 -6
- package/templates/qoder/scripts/{common → foundation/utils}/platform_guard.py +1 -1
- package/templates/qoder/scripts/orchestration/__init__.py +0 -0
- package/templates/qoder/scripts/orchestration/wlkj.py +185 -0
- package/templates/qoder/scripts/protocol/__init__.py +0 -0
- package/templates/qoder/scripts/protocol/browser/README.md +207 -0
- package/templates/qoder/scripts/protocol/browser/SKILL.md +265 -0
- package/templates/qoder/scripts/protocol/browser/config.env +9 -0
- package/templates/qoder/scripts/protocol/browser/references/cdp-api.md +110 -0
- package/templates/qoder/scripts/protocol/browser/references/migration-2.5.3.md +72 -0
- package/templates/qoder/scripts/protocol/browser/references/site-patterns/.gitkeep +0 -0
- package/templates/qoder/scripts/protocol/browser/scripts/browser-discovery.mjs +138 -0
- package/templates/qoder/scripts/protocol/browser/scripts/cdp-proxy.mjs +672 -0
- package/templates/qoder/scripts/protocol/browser/scripts/check-deps.mjs +206 -0
- package/templates/qoder/scripts/protocol/browser/scripts/find-url.mjs +253 -0
- package/templates/qoder/scripts/protocol/browser/scripts/match-site.mjs +46 -0
- package/templates/qoder/scripts/protocol/browser/templates/config.env.template +9 -0
- package/templates/qoder/scripts/protocol/mcp/__init__.py +11 -0
- package/templates/qoder/scripts/protocol/mcp/kg_mcp_server.py +478 -0
- package/templates/qoder/scripts/{mcp → protocol/mcp}/lanhu_stdio_wrapper.py +11 -5
- package/templates/qoder/scripts/{mcp → protocol/mcp}/mcp_doctor.py +47 -14
- package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
- package/templates/qoder/scripts/{mcp → protocol/mcp}/mysql_mcp_server.py +181 -67
- package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +1920 -0
- package/templates/qoder/scripts/protocol/transports/__init__.py +56 -0
- package/templates/qoder/scripts/protocol/transports/base.py +87 -0
- package/templates/qoder/scripts/protocol/transports/cli.py +132 -0
- package/templates/qoder/scripts/protocol/transports/http.py +141 -0
- package/templates/qoder/scripts/protocol/transports/stdio.py +293 -0
- package/templates/qoder/scripts/run_weekly_update.bat +27 -18
- package/templates/qoder/scripts/run_weekly_update.sh +22 -13
- package/templates/qoder/scripts/validation/__init__.py +0 -0
- package/templates/qoder/scripts/validation/eval/__init__.py +0 -0
- package/templates/qoder/scripts/validation/eval/perf-report-2026-06-24.md +139 -0
- package/templates/qoder/scripts/validation/eval/qwork_harness.py +617 -0
- package/templates/qoder/scripts/validation/eval/report-commands.md +220 -0
- package/templates/qoder/scripts/validation/eval/transcript_timing.py +386 -0
- package/templates/qoder/scripts/validation/metrics/__init__.py +0 -0
- package/templates/qoder/scripts/{report → validation/metrics}/eval_prd.py +17 -10
- package/templates/qoder/scripts/validation/metrics/usability_score.py +750 -0
- package/templates/qoder/scripts/validation/test/__init__.py +11 -0
- package/templates/qoder/scripts/validation/test/assertion_gen.py +551 -0
- package/templates/qoder/scripts/{test → validation/test}/autotest.py +64 -4
- package/templates/qoder/scripts/{common → validation/test}/autotest_auth.py +1 -1
- package/templates/qoder/scripts/{test → validation/test}/autotest_batch.py +16 -3
- package/templates/qoder/scripts/{test → validation/test}/autotest_data.py +17 -12
- package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
- package/templates/qoder/scripts/{test → validation/test}/autotest_run.py +17 -3
- package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
- package/templates/qoder/scripts/{test → validation/test}/benchmark.py +12 -6
- package/templates/qoder/scripts/{test → validation/test}/kg_auto_login.py +8 -2
- package/templates/qoder/scripts/{test → validation/test}/kg_test_runner.py +7 -2
- package/templates/qoder/scripts/{test → validation/test}/page_probe.py +8 -3
- package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
- package/templates/qoder/settings.json +30 -0
- package/templates/qoder/skills/design-import/SKILL.md +22 -13
- package/templates/qoder/skills/design-review/SKILL.md +19 -10
- package/templates/qoder/skills/prd-generator/SKILL.md +22 -18
- package/templates/qoder/skills/prd-review/SKILL.md +6 -4
- package/templates/qoder/skills/prototype-generator/SKILL.md +63 -14
- package/templates/qoder/skills/spec-coder/SKILL.md +22 -13
- package/templates/qoder/skills/spec-generator/SKILL.md +22 -10
- package/templates/qoder/skills/test-generator/SKILL.md +7 -5
- package/templates/qoder/skills/wl-code/SKILL.md +23 -11
- package/templates/qoder/skills/wl-commit/SKILL.md +9 -8
- package/templates/qoder/skills/wl-design/SKILL.md +5 -3
- package/templates/qoder/skills/wl-init/SKILL.md +6 -6
- package/templates/qoder/skills/wl-insight/SKILL.md +23 -10
- package/templates/qoder/skills/wl-prd-full/SKILL.md +57 -6
- package/templates/qoder/skills/wl-prd-quick/SKILL.md +3 -3
- package/templates/qoder/skills/wl-prd-review/SKILL.md +16 -4
- package/templates/qoder/skills/wl-report/SKILL.md +25 -23
- package/templates/qoder/skills/wl-search/SKILL.md +149 -78
- package/templates/qoder/skills/wl-spec/SKILL.md +7 -5
- package/templates/qoder/skills/wl-status/SKILL.md +48 -16
- package/templates/qoder/skills/wl-task/SKILL.md +92 -10
- package/templates/qoder/skills/wl-test/SKILL.md +75 -29
- package/templates/qoder/templates/prd-full-template.md +7 -0
- package/templates/root/AGENTS.md +275 -236
- package/templates/root/requirements.txt +3 -0
- package/templates/root//344/275/277/347/224/250/350/257/264/346/230/216.md +3 -3
- package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +2 -2
- package/templates/.qoder/.runtime/ctx-cache-5660152f1d6dd819.md +0 -23
- package/templates/.qoder/.runtime/ctx-cache-afdce0dac06b25b0.md +0 -23
- package/templates/.qoder/.runtime/search-cache-eae7644e7b122f35.txt +0 -1
- package/templates/.qoder/learning/eval-history.jsonl +0 -28
- package/templates/data/index/wiki-index.json +0 -8
- package/templates/qoder/nul +0 -4
- package/templates/qoder/scripts/kg/extract.py +0 -398
- package/templates/qoder/scripts/kg/kg_semantic.py +0 -156
- package/templates/qoder/scripts/mcp/kg_mcp_server.py +0 -606
- package/templates/qoder/scripts/mcp/mcp_launcher.py +0 -442
- package/templates/qoder/scripts/mcp/zentao_mcp_server.py +0 -384
- package/templates/qoder/scripts/task/__init__.py +0 -11
- package/templates/qoder/scripts/test/__init__.py +0 -11
- package/templates/qoder/scripts/wlkj.py +0 -116
- /package/templates/qoder/scripts/{common → deployment}/__init__.py +0 -0
- /package/templates/qoder/scripts/{common → domain/kg/graph}/graph_traverse.py +0 -0
- /package/templates/qoder/scripts/{common → domain/kg/server}/repowiki.py +0 -0
- /package/templates/qoder/scripts/{common → foundation/io}/atomicio.py +0 -0
- /package/templates/qoder/scripts/{test → validation/test}/secure-ls.js +0 -0
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
3
3
|
import os as _o, sys as _s
|
|
4
|
-
|
|
4
|
+
_f = _o.path.abspath(__file__)
|
|
5
|
+
for _ in range(10):
|
|
6
|
+
_f = _o.path.dirname(_f)
|
|
7
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
8
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
9
|
+
break
|
|
5
10
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
6
11
|
from bootstrap import setup; setup()
|
|
7
12
|
|
|
@@ -41,11 +46,11 @@ if sys.platform == 'win32':
|
|
|
41
46
|
_THIS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
42
47
|
if _THIS_DIR not in sys.path:
|
|
43
48
|
sys.path.insert(0, _THIS_DIR)
|
|
44
|
-
_COMMON = os.path.join(_THIS_DIR, '
|
|
49
|
+
_COMMON = os.path.join(_THIS_DIR, 'foundation')
|
|
45
50
|
if _COMMON not in sys.path:
|
|
46
51
|
sys.path.insert(0, _COMMON)
|
|
47
52
|
|
|
48
|
-
from
|
|
53
|
+
from foundation.core.paths import get_repo_root # noqa: E402
|
|
49
54
|
|
|
50
55
|
|
|
51
56
|
# ============================================================
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
from foundation.core.paths import get_repo_root
|
|
2
|
+
#!/usr/bin/env python3
|
|
3
|
+
"""
|
|
4
|
+
smoke_all_commands.py — 全角色 × 全命令底层脚本健康度实测
|
|
5
|
+
|
|
6
|
+
目的: 验证本轮"思考链短/调用少/不降性能"优化后, 每个 /wl-* 命令依赖的底层脚本
|
|
7
|
+
仍然健康可用 + 记录耗时/调用次数, 供优化前后对比。
|
|
8
|
+
|
|
9
|
+
为什么测"底层脚本"而非"完整 AI 命令链":
|
|
10
|
+
完整命令链要真实 AI 多轮交互, 无法脚本化。但每个命令的健康度 = 它调用的底层
|
|
11
|
+
脚本(context_pack/prefetch/report_snapshot/status_snapshot/task/grep-text)能否
|
|
12
|
+
跑通。这些跑通 = 命令链能执行的前提。耗时也直接反映"不降性能"。
|
|
13
|
+
|
|
14
|
+
按角色分组 (AGENTS.md 的 5 角色), 每角色跑其核心命令的底层脚本。
|
|
15
|
+
输出: 每命令 [PASS/FAIL] + 耗时 + 调用次数, 汇总成表。
|
|
16
|
+
|
|
17
|
+
用法:
|
|
18
|
+
python smoke_all_commands.py # 跑全部
|
|
19
|
+
python smoke_all_commands.py --quick # 只跑快命令(跳过慢的 git 扫描)
|
|
20
|
+
"""
|
|
21
|
+
import os
|
|
22
|
+
import subprocess
|
|
23
|
+
import sys
|
|
24
|
+
import time
|
|
25
|
+
from datetime import datetime
|
|
26
|
+
|
|
27
|
+
REPO = get_repo_root()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _run(label, script_args, timeout=90):
|
|
31
|
+
"""跑一个底层脚本, 返回 (pass, ms, calls, note)。calls 固定=1(本脚本设计为单次聚合)。"""
|
|
32
|
+
t0 = time.time()
|
|
33
|
+
try:
|
|
34
|
+
r = subprocess.run(
|
|
35
|
+
[sys.executable] + script_args, cwd=REPO, capture_output=True,
|
|
36
|
+
text=True, timeout=timeout, encoding="utf-8", errors="replace")
|
|
37
|
+
ms = int((time.time() - t0) * 1000)
|
|
38
|
+
ok = r.returncode == 0 and bool(r.stdout.strip())
|
|
39
|
+
note = "" if ok else (r.stderr.strip()[:120] or f"exit={r.returncode},empty out")
|
|
40
|
+
return (label, ok, ms, 1, note)
|
|
41
|
+
except subprocess.TimeoutExpired:
|
|
42
|
+
return (label, False, int((time.time() - t0) * 1000), 1, "TIMEOUT")
|
|
43
|
+
except Exception as e:
|
|
44
|
+
return (label, False, int((time.time() - t0) * 1000), 1, str(e)[:120])
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _kg(subcmd_args):
|
|
48
|
+
return _run_args(".qoder/scripts/domain/kg/kg.py", subcmd_args)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _run_args(script_rel, subcmd_args):
|
|
52
|
+
return [os.path.join(REPO, script_rel)] + subcmd_args
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ── 每角色的命令 → 底层脚本映射 ──
|
|
56
|
+
# (角色, 命令, 描述, 脚本调用列表)
|
|
57
|
+
CHECKS = [
|
|
58
|
+
# PM 角色 (/wl-prd 合并了原 full/quick/review 三档, 这里覆盖两档路由)
|
|
59
|
+
("pm", "wl-prd", "prefetch 多词取全(完整档)",
|
|
60
|
+
lambda: _run("prefetch", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
61
|
+
["prefetch", "考勤导入校验", "--platform", "web"]))),
|
|
62
|
+
("pm", "wl-prd", "prefetch 取全(快速档)",
|
|
63
|
+
lambda: _run("prefetch-quick", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
64
|
+
["prefetch", "保险统计", "--platform", "web"]))),
|
|
65
|
+
("pm", "wl-insight", "context 取全",
|
|
66
|
+
lambda: _run("context", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
67
|
+
["context", "考勤", "--platform", "web"]))),
|
|
68
|
+
("pm", "wl-task", "task list",
|
|
69
|
+
lambda: _run("task-list", _run_args(".qoder/scripts/domain/task/task.py", ["list"]))),
|
|
70
|
+
|
|
71
|
+
# Design 角色
|
|
72
|
+
("design", "wl-design", "context 取全(扫描)",
|
|
73
|
+
lambda: _run("context-design", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
74
|
+
["context", "保险", "--platform", "web", "--role", "design"]))),
|
|
75
|
+
|
|
76
|
+
# Dev 角色
|
|
77
|
+
("dev", "wl-code", "context 取全(代码视角)",
|
|
78
|
+
lambda: _run("context-dev", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
79
|
+
["context", "考勤", "--platform", "web", "--role", "dev"]))),
|
|
80
|
+
("dev", "wl-commit", "git status(只读)", None),
|
|
81
|
+
# test 角色
|
|
82
|
+
("test", "wl-test", "context 取全(test视角)",
|
|
83
|
+
lambda: _run("context-test", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
84
|
+
["context", "登录", "--platform", "app", "--role", "test"]))),
|
|
85
|
+
|
|
86
|
+
# Admin 角色
|
|
87
|
+
("admin", "wl-status", "status_snapshot 聚合",
|
|
88
|
+
lambda: _run("status-snapshot",
|
|
89
|
+
_run_args(".qoder/scripts/domain/report/status_snapshot.py", [REPO]))),
|
|
90
|
+
("admin", "wl-report", "report_snapshot 聚合",
|
|
91
|
+
lambda: _run("report-snapshot",
|
|
92
|
+
_run_args(".qoder/scripts/domain/report/report_snapshot.py", [REPO]))),
|
|
93
|
+
("admin", "wl-init", "init_doctor",
|
|
94
|
+
lambda: _run("init-doctor",
|
|
95
|
+
_run_args(".qoder/scripts/deployment/setup/init_doctor.py", []))),
|
|
96
|
+
|
|
97
|
+
# 全员通用
|
|
98
|
+
("all", "wl-search", "context(代码类)",
|
|
99
|
+
lambda: _run("search-context", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
100
|
+
["context", "保险", "--platform", "web"]))),
|
|
101
|
+
("all", "wl-search", "grep-text(中文文案)",
|
|
102
|
+
lambda: _run("grep-text", _run_args(".qoder/scripts/domain/kg/kg.py",
|
|
103
|
+
["grep-text", "车辆不存在"]))),
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def main():
|
|
108
|
+
quick = "--quick" in sys.argv
|
|
109
|
+
print("=" * 70)
|
|
110
|
+
print(f" 全角色 × 全命令 底层脚本实测 ({datetime.now():%Y-%m-%d %H:%M})")
|
|
111
|
+
print("=" * 70)
|
|
112
|
+
|
|
113
|
+
results = []
|
|
114
|
+
cur_role = None
|
|
115
|
+
for role, cmd, desc, fn in CHECKS:
|
|
116
|
+
if quick and cmd in ("wl-init",): # init_doctor 较慢
|
|
117
|
+
continue
|
|
118
|
+
if role != cur_role:
|
|
119
|
+
cur_role = role
|
|
120
|
+
print(f"\n── {role.upper()} ──")
|
|
121
|
+
# wl-commit 特殊处理: 直接跑 git status
|
|
122
|
+
if cmd == "wl-commit":
|
|
123
|
+
r = _run_git_status()
|
|
124
|
+
elif fn is None:
|
|
125
|
+
continue
|
|
126
|
+
else:
|
|
127
|
+
r = fn()
|
|
128
|
+
results.append((role, cmd, desc, *r))
|
|
129
|
+
label, ok, ms, calls, note = r
|
|
130
|
+
mark = "✓" if ok else "✗"
|
|
131
|
+
line = f" {mark} {cmd:14s} {desc:24s} {ms:6d}ms {calls}调用"
|
|
132
|
+
if note:
|
|
133
|
+
line += f" ⚠ {note[:50]}"
|
|
134
|
+
print(line)
|
|
135
|
+
|
|
136
|
+
# 汇总: results 元组 = (role, cmd, desc, label, ok, ms, calls, note)
|
|
137
|
+
# ok 在索引 4, ms 在 5, calls 在 6, note 在 7
|
|
138
|
+
passed = sum(1 for r in results if r[4])
|
|
139
|
+
total = len(results)
|
|
140
|
+
fails = [r for r in results if not r[4]]
|
|
141
|
+
avg_ms = sum(r[5] for r in results) // total if total else 0
|
|
142
|
+
total_calls = sum(r[6] for r in results)
|
|
143
|
+
print("\n" + "=" * 70)
|
|
144
|
+
print(f" 汇总: {passed}/{total} PASS | 平均 {avg_ms}ms | 总调用 {total_calls} 次")
|
|
145
|
+
if fails:
|
|
146
|
+
print(f" ⚠ {len(fails)} 个失败:")
|
|
147
|
+
for r in fails:
|
|
148
|
+
print(f" {r[1]} ({r[2]}): {r[7]}")
|
|
149
|
+
else:
|
|
150
|
+
print(" ✓ 全部健康, 命令链可执行")
|
|
151
|
+
print("=" * 70)
|
|
152
|
+
return 0 if not fails else 1
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _run_git_status():
|
|
156
|
+
"""wl-commit Step1 合并后的 git 命令: status + diff HEAD --stat 一条。"""
|
|
157
|
+
t0 = time.time()
|
|
158
|
+
try:
|
|
159
|
+
r = subprocess.run("git status && git diff HEAD --stat",
|
|
160
|
+
cwd=REPO, capture_output=True, text=True, timeout=10,
|
|
161
|
+
encoding="utf-8", errors="replace", shell=True)
|
|
162
|
+
ms = int((time.time() - t0) * 1000)
|
|
163
|
+
ok = r.returncode == 0
|
|
164
|
+
return ("git-status", ok, ms, 1, "" if ok else r.stderr[:80])
|
|
165
|
+
except Exception as e:
|
|
166
|
+
return ("git-status", False, int((time.time() - t0) * 1000), 1, str(e)[:80])
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
sys.exit(main())
|
|
@@ -39,6 +39,36 @@
|
|
|
39
39
|
}
|
|
40
40
|
]
|
|
41
41
|
}
|
|
42
|
+
],
|
|
43
|
+
"UserPromptSubmit": [
|
|
44
|
+
{
|
|
45
|
+
"matcher": "*",
|
|
46
|
+
"hooks": [
|
|
47
|
+
{
|
|
48
|
+
"command": "python .qoder/hooks/user-prompt-submit.py || python3 .qoder/hooks/user-prompt-submit.py"
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"PostToolUse": [
|
|
54
|
+
{
|
|
55
|
+
"matcher": "*",
|
|
56
|
+
"hooks": [
|
|
57
|
+
{
|
|
58
|
+
"command": "python .qoder/hooks/post-tool-use.py || python3 .qoder/hooks/post-tool-use.py"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"Stop": [
|
|
64
|
+
{
|
|
65
|
+
"matcher": "*",
|
|
66
|
+
"hooks": [
|
|
67
|
+
{
|
|
68
|
+
"command": "python .qoder/hooks/stop-eval.py || python3 .qoder/hooks/stop-eval.py"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
42
72
|
]
|
|
43
73
|
}
|
|
44
74
|
}
|
|
@@ -11,11 +11,11 @@ trigger: "user invokes /wl-* command explicitly"
|
|
|
11
11
|
```bash
|
|
12
12
|
R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
13
13
|
```
|
|
14
|
-
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python
|
|
14
|
+
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python "$R/.qoder/scripts/orchestration/wlkj.py" install-qw`。
|
|
15
15
|
|
|
16
16
|
# Design Import Skill(设计师专用)
|
|
17
17
|
|
|
18
|
-
> 🚫 **边界铁律:蓝湖工具(`
|
|
18
|
+
> 🚫 **边界铁律:蓝湖工具(`MCP 工具 (`)只能在本 skill(即 `/wl-design 预览`)内部调用。**
|
|
19
19
|
> 用户直接说"查蓝湖""读一下这个蓝湖链接"而没走录入命令时,**不要裸调蓝湖**——先确认意图,
|
|
20
20
|
> 引导到 `/wl-design 预览 <蓝湖链接>`。工作流是非侵入式的,所有能力必须经命令/工序站触发,
|
|
21
21
|
> 不能脱离流程裸调工具(否则不可控、不可审计)。
|
|
@@ -24,10 +24,19 @@ R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
|
24
24
|
存到 `data/style/`,进入知识图谱。从此同需求的 AI 原型优先锚定这份 spec,
|
|
25
25
|
不再跟设计师的稿打架。
|
|
26
26
|
|
|
27
|
+
## 🔌 MCP 工具可用性(双轨)
|
|
28
|
+
|
|
29
|
+
本 skill 用到的知识图谱 MCP 工具(`MCP 工具 (` / `MCP 工具 (`)**自动路由(有 MCP 走 MCP,无 MCP 走 CLI)**。
|
|
30
|
+
|
|
31
|
+
- **QoderWork**:直接调 MCP 工具(更快更准);Step 3 存储到知识图谱也走 MCP。
|
|
32
|
+
- **Qoder IDE/Quest/CLI(无 MCP)**:用 `python "$R/.qoder/scripts/orchestration/wlkj.py" search` 降级查样式;存储到知识图谱步骤跳过(spec.json 照常生成,本地可用)。
|
|
33
|
+
|
|
27
34
|
## ⚙️ 自取上下文(QoderWork 无 hook 注入,必须自读)
|
|
28
35
|
|
|
29
|
-
-
|
|
30
|
-
|
|
36
|
+
- **当前身份**:当前设计师名(产出归属)。读法:先 `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.` 定位仓库根,
|
|
37
|
+
再 `python "$R/.qoder/scripts/foundation/core/paths.py" whoami`(输出开发者名;空=未初始化)。
|
|
38
|
+
⚠️ 勿用裸相对路径 `.qoder/.developer`(QoderWork 桌面端 cwd 不在仓库根,会读不到而误报未初始化)。
|
|
39
|
+
- **活动任务**:若存在,spec 命名带上任务关键词。读法 `python "$R/.qoder/scripts/foundation/core/paths.py" current-task`(输出任务路径;空=无活动任务)。
|
|
31
40
|
- 平台必须明确(Web/APP/Both);如未指定,先问
|
|
32
41
|
|
|
33
42
|
**已录入清单**(设计师问"我录过哪些"时):
|
|
@@ -51,7 +60,7 @@ ls "$R/data/style/"*-design-spec.json 2>/dev/null # 列所有 spec
|
|
|
51
60
|
|
|
52
61
|
**A-1. 探测蓝湖可用性(失败就静默降级)**
|
|
53
62
|
```
|
|
54
|
-
调
|
|
63
|
+
调 cap.mcp.call("get_designs", {"url": "<链接>"})
|
|
55
64
|
```
|
|
56
65
|
- 返回设计图列表 → 继续 A-2
|
|
57
66
|
- 报"连接失败"/工具不存在/418(cookie 失效)→ **立刻降级**:告诉用户"蓝湖没起/cookie 失效,改用截图口述",然后走方式 B,**不许卡住**
|
|
@@ -60,7 +69,7 @@ ls "$R/data/style/"*-design-spec.json 2>/dev/null # 列所有 spec
|
|
|
60
69
|
|
|
61
70
|
**A-2. 选设计图(图多时帮用户缩小范围)**
|
|
62
71
|
```
|
|
63
|
-
调
|
|
72
|
+
调 cap.mcp.call("get_designs", {"url": "<链接>"}) → 返回 {designs:[{name, width, height, ...}], sectors:[...], total_designs}
|
|
64
73
|
```
|
|
65
74
|
- **图少(≤15 张)**:直接列全部图名,问"录入哪张?"(**问了就停**)
|
|
66
75
|
- **图多(>15 张)**:别一次倒几百张,先帮缩小:
|
|
@@ -71,9 +80,9 @@ ls "$R/data/style/"*-design-spec.json 2>/dev/null # 列所有 spec
|
|
|
71
80
|
|
|
72
81
|
**A-3. 读标注 + 切图**
|
|
73
82
|
```
|
|
74
|
-
调
|
|
83
|
+
调 cap.mcp.call("get_ai_analyze_design_result", {"url": "<链接>", "design_names": "[<选中的图名>]"})
|
|
75
84
|
→ 返回: HTML/CSS 标注 (rgba 值、width、padding、font...) + 还原指引
|
|
76
|
-
调
|
|
85
|
+
调 cap.mcp.call("get_design_slices", {"url": "<链接>", "design_name": "<图名>", "include_metadata": "true"})
|
|
77
86
|
→ 返回: {slices:[{name, size, download_url, svg_url, scale_urls:{1x,2x,3x}}]}
|
|
78
87
|
```
|
|
79
88
|
- CSS 标注 → 填 `design_tokens`/`layout`/`components`
|
|
@@ -97,7 +106,7 @@ ls "$R/data/style/"*-design-spec.json 2>/dev/null # 列所有 spec
|
|
|
97
106
|
> 蓝湖 MCP 是 STDIO 模式:开 QoderWork 自动起、关自动停,**无需手动 start**。
|
|
98
107
|
> cookie 按角色隔离在 `workspace/members/{当前用户}/.secrets/lanhu.env`(不进 git)——
|
|
99
108
|
> wrapper(lanhu_stdio_wrapper.py)读当前 `.developer` 角色的 cookie 拉起服务,UI 角色有改稿权限、PM/开发只读。
|
|
100
|
-
> 没配的话跑 `python "$R/.qoder/scripts/
|
|
109
|
+
> 没配的话跑 `python "$R/.qoder/scripts/orchestration/wlkj.py" setup-lanhu`;换角色改 `.developer` + 配新角色 cookie 后重启 QoderWork。
|
|
101
110
|
|
|
102
111
|
**方式 B:截图 + 口述**
|
|
103
112
|
设计师发一张 Figma/Axure 截图,口述关键设计决策:
|
|
@@ -178,7 +187,7 @@ ls "$R/data/style/"*-design-spec.json 2>/dev/null # 列所有 spec
|
|
|
178
187
|
|
|
179
188
|
spec.json 落盘后埋点,供 /wl-status 统计设计录入活跃度:
|
|
180
189
|
```bash
|
|
181
|
-
python "$R/.qoder/scripts/
|
|
190
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" learn record design_import "{\"requirement\": \"<需求名>\", \"platform\": \"<web|app>\", \"source\": \"<蓝湖|截图|导出>\"}"
|
|
182
191
|
```
|
|
183
192
|
> 失败静默忽略。
|
|
184
193
|
|
|
@@ -202,7 +211,7 @@ python "$R/.qoder/scripts/report/learn.py" record design_import "{\"requirement\
|
|
|
202
211
|
|
|
203
212
|
## 铁律
|
|
204
213
|
|
|
205
|
-
- **有蓝湖 MCP 时优先用它直读**:设计师发蓝湖链接,AI 调 `
|
|
214
|
+
- **有蓝湖 MCP 时优先用它直读**:设计师发蓝湖链接,AI 调 `MCP 工具 (` 提取精确参数,
|
|
206
215
|
不要让设计师截图口述(截图口述是蓝湖不可用时的降级方案)
|
|
207
216
|
- **绝不编造 token**:设计师没说的值,留空或标"待确认",不要自己猜
|
|
208
217
|
- **图标必须来自真源**:即使设计师用了 emoji 示意,录入时也要替换成系统真源
|
|
@@ -213,9 +222,9 @@ python "$R/.qoder/scripts/report/learn.py" record design_import "{\"requirement\
|
|
|
213
222
|
|
|
214
223
|
设计师录入 spec 前,可以先问 AI 系统现状,让 spec 更贴合系统:
|
|
215
224
|
|
|
216
|
-
- **"这个功能模块现在有哪些页面?"** → AI 调 `
|
|
225
|
+
- **"这个功能模块现在有哪些页面?"** → AI 调 `cap.mcp.call("feature_overview", {"feature": "资产管理"})`
|
|
217
226
|
返回该模块所有页面 + API + 按钮,设计师知道改哪些、加哪些
|
|
218
|
-
- **"这个模块的业务流程是什么?"** → AI 调 `
|
|
227
|
+
- **"这个模块的业务流程是什么?"** → AI 调 `cap.mcp.call("get_workflow", {"module": "资产"})`
|
|
219
228
|
返回操作链(查询→新增→审批→...),spec 里的交互流程跟系统一致
|
|
220
229
|
- **"系统里这个模块的按钮都叫什么?"** → 看 DESIGN.md 的 "Real Button Texts" 段
|
|
221
230
|
或 entity-registry.json,spec 里的按钮文案跟系统统一
|
|
@@ -11,16 +11,25 @@ trigger: "user invokes /wl-* command explicitly"
|
|
|
11
11
|
```bash
|
|
12
12
|
R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
13
13
|
```
|
|
14
|
-
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python
|
|
14
|
+
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python "$R/.qoder/scripts/orchestration/wlkj.py" install-qw`。
|
|
15
15
|
|
|
16
16
|
# Design Review Skill(设计师 + PM 都可用)
|
|
17
17
|
|
|
18
|
-
> 🚫 **边界铁律:蓝湖工具(`
|
|
18
|
+
> 🚫 **边界铁律:蓝湖工具(`MCP 工具 (`)只能在本 skill(即 `/wl-design 评审`)内部调用。**
|
|
19
19
|
> 用户直接说"用蓝湖对比一下"而没走评审命令时,引导到 `/wl-design 评审`。非侵入式,不裸调。
|
|
20
20
|
|
|
21
|
+
## 🔌 MCP 工具可用性(双轨)
|
|
22
|
+
|
|
23
|
+
本 skill 用到的知识图谱 MCP 工具(`MCP 工具 (` / `MCP 工具 (`)**自动路由(有 MCP 走 MCP,无 MCP 走 CLI)**。
|
|
24
|
+
|
|
25
|
+
- **QoderWork**:直接调 MCP 工具(更快更准)。
|
|
26
|
+
- **Qoder IDE/Quest/CLI(无 MCP)**:用 `python "$R/.qoder/scripts/orchestration/wlkj.py" search` 降级(`--style table|form|modal` / `--field <名>` / `--components`);仅 MCP 有的能力(如 feature_overview/get_workflow)跳过或人工评估。
|
|
27
|
+
|
|
21
28
|
## ⚙️ 自取上下文(Quest / QoderWork 无 hook 注入,必须自读)
|
|
22
29
|
|
|
23
|
-
-
|
|
30
|
+
- **当前身份**:当前评审人。读法:先 `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.` 定位仓库根,
|
|
31
|
+
再 `python "$R/.qoder/scripts/foundation/core/paths.py" whoami`(输出开发者名;空=未初始化)。
|
|
32
|
+
⚠️ 勿用裸相对路径 `.qoder/.developer`(QoderWork 桌面端 cwd 不在仓库根,会读不到而误报未初始化)。
|
|
24
33
|
- 设计文件路径由用户指定,或扫 `workspace/members/{dev}/drafts/prototype-*.html`
|
|
25
34
|
- 若 `data/style/{需求名}-design-spec.json` 存在,作为评审基准(优先级最高)
|
|
26
35
|
|
|
@@ -56,15 +65,15 @@ PM 说"评审设计稿",AI 检查设计师的 spec.json 或原型:
|
|
|
56
65
|
- [ ] **🆕 按钮文案是否用了系统真实文案**(对照 DESIGN.md 的 "Real Button Texts" 段或 entity-registry,别用编的"新增/编辑")
|
|
57
66
|
- [ ] **🆕 布局是否跟同功能模块的标杆页面一致**(对照 DESIGN.md 的 "Feature Modules" 段)
|
|
58
67
|
- [ ] **🆕 侧边栏宽度是否 = layout_fingerprint 的值**(fywl-ui 是 160px,不是 200px)
|
|
59
|
-
- [ ] **🆕 若 spec 有 `lanhu_source`:原型配色是否忠于蓝湖原图**(调 `
|
|
68
|
+
- [ ] **🆕 若 spec 有 `lanhu_source`:原型配色是否忠于蓝湖原图**(调 `cap.mcp.call("get_ai_analyze_design_result` 拉蓝湖 CSS,逐项比原型 `:root` 的值是否一致;不一致=还原度问题)
|
|
60
69
|
- [ ] **🆕 若 spec 有 `icons`:原型图标是否用了蓝湖切图**(别退回 emoji 或通用图标)
|
|
61
70
|
|
|
62
71
|
**评审时可调 MCP 工具辅助:**
|
|
63
|
-
- `
|
|
64
|
-
- `
|
|
65
|
-
- **`
|
|
66
|
-
- **`
|
|
67
|
-
- **`
|
|
72
|
+
- `cap.mcp.call("feature_overview", {"feature": "XX"})` → 看这个功能模块的完整画像,对比原型是否遗漏页面/按钮
|
|
73
|
+
- `cap.mcp.call("get_design_system", {"platform": "web"})` → 拿到真实 token/按钮文案/模块标杆做对照
|
|
74
|
+
- **`cap.mcp.call("get_workflow", {"module": "XX"})`** → 查业务操作链(查询→新增→审批→...),检查原型是否覆盖了完整交互流程(而不只是静态页面)
|
|
75
|
+
- **`cap.mcp.call("coverage_matrix", {})`** → 查这个功能有没有测试覆盖,如果原型要改的页面有测试,提醒"改动后需回归测试"
|
|
76
|
+
- **`cap.mcp.call("get_ai_analyze_design_result`** → spec 有 lanhu_source 时,拉蓝湖原图 CSS 做还原度比对(蓝湖不可用则跳过此项,不阻塞)
|
|
68
77
|
|
|
69
78
|
## 输出
|
|
70
79
|
|
|
@@ -75,7 +84,7 @@ PM 说"评审设计稿",AI 检查设计师的 spec.json 或原型:
|
|
|
75
84
|
评审输出报告后,**立即调用 learning 引擎记录本次评审**(让团队学习哪些设计问题最常见):
|
|
76
85
|
|
|
77
86
|
```bash
|
|
78
|
-
python "$R/.qoder/scripts/
|
|
87
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" learn record review_done "{\"target\":\"{被评审的原型或spec}\",\"result\":\"PASS或问题数\",\"issues\":[\"严重问题1\",\"建议1\"]}"
|
|
79
88
|
```
|
|
80
89
|
|
|
81
90
|
> 埋点失败不阻塞评审。数据进个人 journal,管理员聚合到 kg.duckdb 后,可统计"最常出现的设计问题",反哺 design-import 防再犯。
|
|
@@ -11,7 +11,7 @@ trigger: "user invokes /wl-* command explicitly"
|
|
|
11
11
|
```bash
|
|
12
12
|
R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
13
13
|
```
|
|
14
|
-
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python
|
|
14
|
+
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python "$R/.qoder/scripts/orchestration/wlkj.py" install-qw`。
|
|
15
15
|
|
|
16
16
|
# PRD Generator Skill
|
|
17
17
|
|
|
@@ -39,24 +39,28 @@ R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
|
39
39
|
|
|
40
40
|
## 自取上下文(Quest / QoderWork 无 hook,必须自读)
|
|
41
41
|
|
|
42
|
-
-
|
|
43
|
-
|
|
42
|
+
- **当前身份**:当前开发者名。读法:先 `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.` 定位仓库根,
|
|
43
|
+
再 `python "$R/.qoder/scripts/foundation/core/paths.py" whoami`(输出开发者名;空=未初始化)。
|
|
44
|
+
⚠️ 勿用裸相对路径 `.qoder/.developer`(QoderWork 桌面端 cwd 不在仓库根,会读不到而误报未初始化)。
|
|
45
|
+
- **活动任务**:当前活动任务。读法 `python "$R/.qoder/scripts/foundation/core/paths.py" current-task`(输出任务路径;空=无活动任务)。
|
|
44
46
|
- `data/index/.index-meta.json` — 知识图谱新鲜度
|
|
45
47
|
|
|
46
48
|
### 写 PRD 前:一次取全(prefetch 预测 + 批量预取)
|
|
47
49
|
|
|
48
50
|
**写 PRD 第一件事:调 1 次 `prefetch`**(它会预测业务词 + 批量取多词上下文,合并去重):
|
|
49
51
|
```bash
|
|
50
|
-
ROLE=$(python "$R/.qoder/scripts/
|
|
51
|
-
python "$R/.qoder/scripts/
|
|
52
|
+
ROLE=$(python "$R/.qoder/scripts/orchestration/wlkj.py" role 2>/dev/null || echo pm)
|
|
53
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" kg prefetch "<需求描述>" --platform <p>
|
|
52
54
|
```
|
|
53
|
-
或直接:`python
|
|
55
|
+
或直接:`python "$R/.qoder/scripts/orchestration/wlkj.py" prefetch "<需求描述>" --platform <p>`
|
|
54
56
|
|
|
55
57
|
prefetch 一次返回 8 段(含历史PRD/数据库表/真实字段/API/Wiki),等于把多个业务词的查询合并。**prefetch 之后严禁再串行 search/find/grep**(这是轮次爆炸的根因——查一个词不命中就换词再查 6+ 次)。
|
|
56
58
|
|
|
57
59
|
**仅当 prefetch 明确没覆盖到时才补调一次**(极少):
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
> 以下两个 MCP 工具自动路由(有 MCP 走 MCP,无 MCP 走 CLI);Qoder IDE/Quest/CLI 无 MCP 时跳过即可,靠 prefetch 已返回的数据足够。
|
|
61
|
+
|
|
62
|
+
- 字段枚举值:`cap.mcp.call("query_distinct", {"table": "表名", "column": "状态列"})` — prefetch 给了表结构但没给枚举取值,需要时才调
|
|
63
|
+
- 改表影响:`cap.mcp.call("table_impact", {"table": "表名"})` — 评估改动范围时才调
|
|
60
64
|
|
|
61
65
|
## STEP 0: 必须先问平台
|
|
62
66
|
|
|
@@ -110,12 +114,12 @@ prefetch 一次返回 8 段(含历史PRD/数据库表/真实字段/API/Wiki)
|
|
|
110
114
|
**第 1 步|并行取全(同一条消息并发,别串行)**
|
|
111
115
|
```
|
|
112
116
|
同一条消息里并行发:
|
|
113
|
-
①
|
|
114
|
-
② Read
|
|
115
|
-
③ Read 业务草稿
|
|
117
|
+
① kg.py prefetch "<需求描述原句>" --platform <p> ← 多词预测一次取全: 代码+页面+字段+API+样式+历史PRD标题
|
|
118
|
+
② Read 业务草稿(workspace/members/{dev}/drafts/ 下相关草稿)
|
|
116
119
|
(若衔接了 insight 报告:同时 Read 该报告,作为现状背景输入)
|
|
117
120
|
```
|
|
118
|
-
然后只读
|
|
121
|
+
然后只读 prefetch 列出的最相关 1-2 个 Vue 文件。
|
|
122
|
+
> 历史相关 PRD:prefetch 第4段已返回标题列表。**只有要参考某篇历史 PRD 的写法/结构时,才额外 Read 那一篇**,不要每次都读。
|
|
119
123
|
> ⚠️ 探索/调研/对标已归 /wl-insight,第 1 步**不派多 agent、不做 web 搜索**。
|
|
120
124
|
|
|
121
125
|
**第 2 步|轻反思 + 批量确认(核心:基于现状反思,重点是跟用户确认)**
|
|
@@ -138,10 +142,10 @@ prefetch 一次返回 8 段(含历史PRD/数据库表/真实字段/API/Wiki)
|
|
|
138
142
|
```bash
|
|
139
143
|
# 门 1+2: 角色边界(当前角色能否产 prd?) + 契约校验(@contract 头是否合规?)
|
|
140
144
|
# 软提示不阻塞, 越权/无契约头会提示但仍可发布
|
|
141
|
-
python "$R/.qoder/scripts/
|
|
145
|
+
python "$R/.qoder/scripts/foundation/identity/check_publish.py" prd <draft-prd.md>
|
|
142
146
|
|
|
143
147
|
# 门 3: 质量分 (eval_prd 内部也会跑契约校验, 这里是质量评分)
|
|
144
|
-
python "$R/.qoder/scripts/
|
|
148
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" eval <draft-prd.md> <prototype.html>
|
|
145
149
|
```
|
|
146
150
|
- check_publish 越权提示 → 软提示(如 dev 产 prd 会提示"建议产品经理"),不阻塞
|
|
147
151
|
- eval_prd < 80% 不准发布,按报告修到 PASS
|
|
@@ -178,12 +182,12 @@ context_pack 字段段返回"无直接相关字段"时,**字段锁不报错,
|
|
|
178
182
|
| REQ-ID 分配器失败 | 扫最大号+1,文件名带 `-manual`,push 时 team_sync 校验唯一 |
|
|
179
183
|
| team_sync SYNC_CONFLICT | AI 按脚本给的命令自行解决,不让用户碰 git |
|
|
180
184
|
|
|
181
|
-
> 完整降级表(含平台答错、归档失败等)见 `.qoder/commands/wl-prd
|
|
185
|
+
> 完整降级表(含平台答错、归档失败等)见 `.qoder/commands/wl-prd.md` 的「故障降级表」。
|
|
182
186
|
|
|
183
187
|
## 取上下文 — 一次取全(不要逐个搜)
|
|
184
188
|
|
|
185
189
|
```bash
|
|
186
|
-
python "$R/.qoder/scripts/
|
|
190
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" context <关键词> --platform <web|app>
|
|
187
191
|
```
|
|
188
192
|
返回 7 章节(代码+页面+字段+PRD+API+样式+Wiki)。**只读最相关 1-2 个 Vue 文件**。
|
|
189
193
|
|
|
@@ -206,7 +210,7 @@ python "$R/.qoder/scripts/kg/context_pack.py" <关键词> --platform <web|app>
|
|
|
206
210
|
## 原型规则
|
|
207
211
|
|
|
208
212
|
- 从模板开始(`.qoder/templates/prototype-{web|app}.html`),模板已有正确颜色与 mixed-nav 多级菜单骨架
|
|
209
|
-
- 先跑 `python "$R/.qoder/scripts/
|
|
213
|
+
- 先跑 `python "$R/.qoder/scripts/orchestration/wlkj.py" fill-prototype <关键词> --platform <web|app>` 拿 80% 草稿;
|
|
210
214
|
它会按目标项目的 `layout_fingerprint` 自动填示例菜单骨架和真实字段,你只微调 20%
|
|
211
215
|
- 颜色/布局指纹见 fill_prototype 输出的"设计 Token"段(布局模式/主色/侧边栏宽度)
|
|
212
216
|
- **菜单层级**: 若需求描述了侧边栏/菜单结构(如"一级→二级,右侧三四级"),
|
|
@@ -221,7 +225,7 @@ python "$R/.qoder/scripts/kg/context_pack.py" <关键词> --platform <web|app>
|
|
|
221
225
|
PRD 写入 drafts 后,**顺手归档一份**到当前成员的按时间文件夹,方便人翻查"我那天做了啥":
|
|
222
226
|
|
|
223
227
|
```bash
|
|
224
|
-
python "$R/.qoder/scripts/
|
|
228
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" archive-prd <刚生成的PRD文件路径>
|
|
225
229
|
```
|
|
226
230
|
|
|
227
231
|
> 归档产物:`workspace/members/{你的名字}/archive/{YYYY-MM-DD}/REQ-{编号}-{中文标题}.md`
|
|
@@ -11,13 +11,15 @@ trigger: "user invokes /wl-* command explicitly"
|
|
|
11
11
|
```bash
|
|
12
12
|
R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
13
13
|
```
|
|
14
|
-
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python
|
|
14
|
+
> `repo_root.py` 从 `~/.qoderwork/mcp.json` 反推仓库根;失败回退 `.`(IDE/CLI 工作目录即仓库根)。找不到时先跑 `python "$R/.qoder/scripts/orchestration/wlkj.py" install-qw`。
|
|
15
15
|
|
|
16
16
|
# PRD Review Skill
|
|
17
17
|
|
|
18
18
|
## ⚙️ 自取上下文(Quest / QoderWork 无 hook 注入,必须自读)
|
|
19
19
|
|
|
20
|
-
-
|
|
20
|
+
- **当前身份**:当前评审人。读法:先 `R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.` 定位仓库根,
|
|
21
|
+
再 `python "$R/.qoder/scripts/foundation/core/paths.py" whoami`(输出开发者名;空=未初始化)。
|
|
22
|
+
⚠️ 勿用裸相对路径 `.qoder/.developer`(QoderWork 桌面端 cwd 不在仓库根,会读不到而误报未初始化)。
|
|
21
23
|
- `data/index/.index-meta.json` — 图谱新鲜度(影响"现实锚定"能否校验)
|
|
22
24
|
- 评审的 PRD 文件路径由用户指定;若用户没给路径,扫 `data/docs/prd/` 和
|
|
23
25
|
`workspace/members/{dev}/drafts/` 列出最近的 PRD 让用户选
|
|
@@ -40,7 +42,7 @@ R=$(python ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
|
40
42
|
|
|
41
43
|
跑一次 EVA 门禁给出客观分数:
|
|
42
44
|
```bash
|
|
43
|
-
python "$R/.qoder/scripts/
|
|
45
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" eval <PRD路径> [原型HTML路径]
|
|
44
46
|
```
|
|
45
47
|
分数 ≥80% 才能发布。低于 80% 把 EVA 报告的问题合并进上面的清单。
|
|
46
48
|
|
|
@@ -48,6 +50,6 @@ python "$R/.qoder/scripts/report/eval_prd.py" <PRD路径> [原型HTML路径]
|
|
|
48
50
|
|
|
49
51
|
评审出结论(无论 PASS/打回)后埋点,供 /wl-status 统计评审活跃度:
|
|
50
52
|
```bash
|
|
51
|
-
python "$R/.qoder/scripts/
|
|
53
|
+
python "$R/.qoder/scripts/orchestration/wlkj.py" learn record review_done "{\"prd\": \"<PRD文件名>\", \"verdict\": \"<PASS|打回>\", \"score\": <EVA分数或空>}"
|
|
52
54
|
```
|
|
53
55
|
> 失败静默忽略。
|