@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.
Files changed (237) hide show
  1. package/bin/cli.js +1435 -1373
  2. package/package.json +1 -1
  3. package/templates/qoder/commands/optional/wl-insight.md +6 -4
  4. package/templates/qoder/commands/optional/wl-report.md +20 -39
  5. package/templates/qoder/commands/optional/wl-status.md +4 -4
  6. package/templates/qoder/commands/wl-code.md +2 -2
  7. package/templates/qoder/commands/wl-design.md +5 -5
  8. package/templates/qoder/commands/wl-init.md +3 -3
  9. package/templates/qoder/commands/wl-prd.md +26 -13
  10. package/templates/qoder/commands/wl-req.md +3 -3
  11. package/templates/qoder/commands/wl-search.md +78 -47
  12. package/templates/qoder/commands/wl-task.md +343 -40
  13. package/templates/qoder/commands/wl-test.md +10 -10
  14. package/templates/qoder/config.yaml +35 -13
  15. package/templates/qoder/hooks/post-tool-use.py +181 -0
  16. package/templates/qoder/hooks/session-start.py +82 -1
  17. package/templates/qoder/hooks/stop-eval.py +207 -0
  18. package/templates/qoder/hooks/user-prompt-submit.py +139 -0
  19. package/templates/qoder/rules/wl-pipeline.md +70 -8
  20. package/templates/qoder/scripts/README.md +78 -115
  21. package/templates/qoder/scripts/capability/__init__.py +26 -0
  22. package/templates/qoder/scripts/capability/__main__.py +72 -0
  23. package/templates/qoder/scripts/capability/adapters/__init__.py +29 -0
  24. package/templates/qoder/scripts/capability/adapters/cli.py +316 -0
  25. package/templates/qoder/scripts/capability/adapters/mcp.py +334 -0
  26. package/templates/qoder/scripts/capability/adapters/qw.py +271 -0
  27. package/templates/qoder/scripts/capability/caps/__init__.py +27 -0
  28. package/templates/qoder/scripts/capability/caps/context.py +36 -0
  29. package/templates/qoder/scripts/capability/caps/cron.py +50 -0
  30. package/templates/qoder/scripts/capability/caps/identity.py +43 -0
  31. package/templates/qoder/scripts/capability/caps/memory.py +71 -0
  32. package/templates/qoder/scripts/capability/caps/notify.py +41 -0
  33. package/templates/qoder/scripts/capability/caps/present.py +48 -0
  34. package/templates/qoder/scripts/capability/caps/repo.py +31 -0
  35. package/templates/qoder/scripts/capability/caps/sandbox.py +43 -0
  36. package/templates/qoder/scripts/capability/chain.py +92 -0
  37. package/templates/qoder/scripts/capability/memory_chain.py +41 -0
  38. package/templates/qoder/scripts/capability/registry.py +246 -0
  39. package/templates/qoder/scripts/capability/registry_mcp.py +250 -0
  40. package/templates/qoder/scripts/capability/smoke_test.py +211 -0
  41. package/templates/qoder/scripts/capability/smoke_test_report.json +94 -0
  42. package/templates/qoder/scripts/{report → deployment/setup}/__init__.py +11 -11
  43. package/templates/qoder/scripts/{setup → deployment/setup}/carriers.py +33 -26
  44. package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
  45. package/templates/qoder/scripts/{setup → deployment/setup}/init_doctor.py +40 -16
  46. package/templates/qoder/scripts/{setup → deployment/setup}/install_qoderwork.py +20 -12
  47. package/templates/qoder/scripts/{setup → deployment/setup}/platform_doctor.py +8 -2
  48. package/templates/qoder/scripts/{setup → deployment/setup}/repo_root.py +113 -112
  49. package/templates/qoder/scripts/{setup → deployment/setup}/setup.py +31 -11
  50. package/templates/qoder/scripts/{setup → deployment/setup}/setup_lanhu.py +13 -7
  51. package/templates/qoder/scripts/domain/__init__.py +0 -0
  52. package/templates/qoder/scripts/domain/design/__init__.py +0 -0
  53. package/templates/qoder/scripts/{report → domain/design}/fill_prototype.py +12 -6
  54. package/templates/qoder/scripts/{report → domain/design}/gen_design_doc.py +8 -2
  55. package/templates/qoder/scripts/{setup → domain/kg}/__init__.py +11 -11
  56. package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
  57. package/templates/qoder/scripts/{kg → domain/kg/build}/build_entity_registry.py +7 -2
  58. package/templates/qoder/scripts/{kg → domain/kg/build}/build_relations.py +7 -2
  59. package/templates/qoder/scripts/{kg → domain/kg/build}/build_style_index.py +13 -7
  60. package/templates/qoder/scripts/{kg → domain/kg/build}/build_workflows.py +7 -2
  61. package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build.py +76 -9
  62. package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build_db.py +7 -2
  63. package/templates/qoder/scripts/{kg → domain/kg/build}/kg_incremental.py +11 -6
  64. package/templates/qoder/scripts/{report → domain/kg/build}/learn_aggregate.py +9 -4
  65. package/templates/qoder/scripts/domain/kg/extract/__init__.py +0 -0
  66. package/templates/qoder/scripts/{common → domain/kg/extract}/extract.py +430 -419
  67. package/templates/qoder/scripts/{common → domain/kg/extract}/test_extract.py +115 -115
  68. package/templates/qoder/scripts/{common → domain/kg/extract}/ts_extract.py +614 -536
  69. package/templates/qoder/scripts/domain/kg/graph/__init__.py +0 -0
  70. package/templates/qoder/scripts/{kg → domain/kg/graph}/kg_link_db.py +7 -2
  71. package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
  72. package/templates/qoder/scripts/{kg → domain/kg}/kg.py +263 -30
  73. package/templates/qoder/scripts/{common → domain/kg}/kg_capabilities.py +182 -182
  74. package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
  75. package/templates/qoder/scripts/{kg → domain/kg/search}/context_pack.py +30 -9
  76. package/templates/qoder/scripts/{kg → domain/kg/search}/enrich_prompt.py +10 -4
  77. package/templates/qoder/scripts/{kg → domain/kg/search}/prefetch.py +33 -8
  78. package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
  79. package/templates/qoder/scripts/{kg → domain/kg/search}/search_index.py +143 -77
  80. package/templates/qoder/scripts/domain/kg/server/__init__.py +0 -0
  81. package/templates/qoder/scripts/domain/kg/server/kgd.py +549 -0
  82. package/templates/qoder/scripts/domain/kg/server/perf_bench.py +197 -0
  83. package/templates/qoder/scripts/domain/kg/storage/__init__.py +0 -0
  84. package/templates/qoder/scripts/{kg → domain/kg/storage}/kg_duckdb.py +38 -14
  85. package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
  86. package/templates/qoder/scripts/{report → domain/learning}/learn.py +8 -3
  87. package/templates/qoder/scripts/{mcp → domain/report}/__init__.py +11 -11
  88. package/templates/qoder/scripts/{report → domain/report}/add_session.py +9 -3
  89. package/templates/qoder/scripts/{report → domain/report}/export.py +10 -5
  90. package/templates/qoder/scripts/{report → domain/report}/report.py +9 -4
  91. package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
  92. package/templates/qoder/scripts/{report → domain/report}/role.py +10 -4
  93. package/templates/qoder/scripts/{report → domain/report}/status.py +112 -9
  94. package/templates/qoder/scripts/domain/report/status_snapshot.py +191 -0
  95. package/templates/qoder/scripts/domain/requirement/__init__.py +0 -0
  96. package/templates/qoder/scripts/{report → domain/requirement}/archive_prd.py +8 -2
  97. package/templates/qoder/scripts/{report → domain/requirement}/req.py +228 -222
  98. package/templates/qoder/scripts/{kg → domain/task}/__init__.py +11 -11
  99. package/templates/qoder/scripts/{task → domain/task}/git_sync.py +40 -21
  100. package/templates/qoder/scripts/{task → domain/task}/syncgate.py +13 -8
  101. package/templates/qoder/scripts/{task → domain/task}/task.py +13 -5
  102. package/templates/qoder/scripts/{task → domain/task}/task_lifecycle.py +606 -596
  103. package/templates/qoder/scripts/{task → domain/task}/task_query.py +162 -161
  104. package/templates/qoder/scripts/{task → domain/task}/task_relations.py +425 -424
  105. package/templates/qoder/scripts/{task → domain/task}/team_sync.py +9 -4
  106. package/templates/qoder/scripts/domain/task/zentao_sync.py +370 -0
  107. package/templates/qoder/scripts/foundation/__init__.py +0 -0
  108. package/templates/qoder/scripts/{common → foundation}/bootstrap.py +10 -10
  109. package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
  110. package/templates/qoder/scripts/{common → foundation/core}/cmd_registry.py +1 -1
  111. package/templates/qoder/scripts/{common → foundation/core}/config.py +1 -1
  112. package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -586
  113. package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
  114. package/templates/qoder/scripts/{common → foundation/data}/contract.py +2 -2
  115. package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
  116. package/templates/qoder/scripts/{common → foundation/data}/result.py +1 -1
  117. package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -404
  118. package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
  119. package/templates/qoder/scripts/{common → foundation/identity}/check_publish.py +103 -98
  120. package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -239
  121. package/templates/qoder/scripts/{common → foundation/identity}/guard.py +2 -2
  122. package/templates/qoder/scripts/{common → foundation/identity}/identity.py +14 -10
  123. package/templates/qoder/scripts/{common → foundation/identity}/roles.py +1 -1
  124. package/templates/qoder/scripts/foundation/integrations/__init__.py +0 -0
  125. package/templates/qoder/scripts/{common → foundation/integrations}/active_task.py +30 -15
  126. package/templates/qoder/scripts/{common → foundation/integrations}/feishu.py +2 -2
  127. package/templates/qoder/scripts/{common → foundation/integrations}/terms.py +3 -3
  128. package/templates/qoder/scripts/foundation/integrations/zentao_client.py +220 -0
  129. package/templates/qoder/scripts/foundation/io/__init__.py +0 -0
  130. package/templates/qoder/scripts/{common → foundation/io}/filelock.py +1 -1
  131. package/templates/qoder/scripts/{common → foundation/io}/reqid.py +1 -1
  132. package/templates/qoder/scripts/foundation/protocol/__init__.py +0 -0
  133. package/templates/qoder/scripts/foundation/protocol/duckdb_conn.py +39 -0
  134. package/templates/qoder/scripts/{common → foundation/protocol}/mcp_base.py +1 -1
  135. package/templates/qoder/scripts/foundation/utils/__init__.py +0 -0
  136. package/templates/qoder/scripts/{common → foundation/utils}/eval_api.py +12 -1
  137. package/templates/qoder/scripts/{common → foundation/utils}/pip_install.py +23 -6
  138. package/templates/qoder/scripts/{common → foundation/utils}/platform_guard.py +1 -1
  139. package/templates/qoder/scripts/orchestration/__init__.py +0 -0
  140. package/templates/qoder/scripts/orchestration/wlkj.py +185 -0
  141. package/templates/qoder/scripts/protocol/__init__.py +0 -0
  142. package/templates/qoder/scripts/protocol/browser/README.md +207 -0
  143. package/templates/qoder/scripts/protocol/browser/SKILL.md +265 -0
  144. package/templates/qoder/scripts/protocol/browser/config.env +9 -0
  145. package/templates/qoder/scripts/protocol/browser/references/cdp-api.md +110 -0
  146. package/templates/qoder/scripts/protocol/browser/references/migration-2.5.3.md +72 -0
  147. package/templates/qoder/scripts/protocol/browser/references/site-patterns/.gitkeep +0 -0
  148. package/templates/qoder/scripts/protocol/browser/scripts/browser-discovery.mjs +138 -0
  149. package/templates/qoder/scripts/protocol/browser/scripts/cdp-proxy.mjs +672 -0
  150. package/templates/qoder/scripts/protocol/browser/scripts/check-deps.mjs +206 -0
  151. package/templates/qoder/scripts/protocol/browser/scripts/find-url.mjs +253 -0
  152. package/templates/qoder/scripts/protocol/browser/scripts/match-site.mjs +46 -0
  153. package/templates/qoder/scripts/protocol/browser/templates/config.env.template +9 -0
  154. package/templates/qoder/scripts/protocol/mcp/__init__.py +11 -0
  155. package/templates/qoder/scripts/protocol/mcp/kg_mcp_server.py +478 -0
  156. package/templates/qoder/scripts/{mcp → protocol/mcp}/lanhu_stdio_wrapper.py +11 -5
  157. package/templates/qoder/scripts/{mcp → protocol/mcp}/mcp_doctor.py +47 -14
  158. package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
  159. package/templates/qoder/scripts/{mcp → protocol/mcp}/mysql_mcp_server.py +181 -67
  160. package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +1920 -0
  161. package/templates/qoder/scripts/protocol/transports/__init__.py +56 -0
  162. package/templates/qoder/scripts/protocol/transports/base.py +87 -0
  163. package/templates/qoder/scripts/protocol/transports/cli.py +132 -0
  164. package/templates/qoder/scripts/protocol/transports/http.py +141 -0
  165. package/templates/qoder/scripts/protocol/transports/stdio.py +293 -0
  166. package/templates/qoder/scripts/run_weekly_update.bat +27 -18
  167. package/templates/qoder/scripts/run_weekly_update.sh +22 -13
  168. package/templates/qoder/scripts/validation/__init__.py +0 -0
  169. package/templates/qoder/scripts/validation/eval/__init__.py +0 -0
  170. package/templates/qoder/scripts/validation/eval/perf-report-2026-06-24.md +139 -0
  171. package/templates/qoder/scripts/validation/eval/qwork_harness.py +617 -0
  172. package/templates/qoder/scripts/validation/eval/report-commands.md +220 -0
  173. package/templates/qoder/scripts/validation/eval/transcript_timing.py +386 -0
  174. package/templates/qoder/scripts/validation/metrics/__init__.py +0 -0
  175. package/templates/qoder/scripts/{report → validation/metrics}/eval_prd.py +17 -10
  176. package/templates/qoder/scripts/validation/metrics/usability_score.py +750 -0
  177. package/templates/qoder/scripts/validation/test/__init__.py +11 -0
  178. package/templates/qoder/scripts/validation/test/assertion_gen.py +551 -0
  179. package/templates/qoder/scripts/{test → validation/test}/autotest.py +64 -4
  180. package/templates/qoder/scripts/{common → validation/test}/autotest_auth.py +1 -1
  181. package/templates/qoder/scripts/{test → validation/test}/autotest_batch.py +16 -3
  182. package/templates/qoder/scripts/{test → validation/test}/autotest_data.py +17 -12
  183. package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
  184. package/templates/qoder/scripts/{test → validation/test}/autotest_run.py +17 -3
  185. package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
  186. package/templates/qoder/scripts/{test → validation/test}/benchmark.py +12 -6
  187. package/templates/qoder/scripts/{test → validation/test}/kg_auto_login.py +8 -2
  188. package/templates/qoder/scripts/{test → validation/test}/kg_test_runner.py +7 -2
  189. package/templates/qoder/scripts/{test → validation/test}/page_probe.py +8 -3
  190. package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
  191. package/templates/qoder/settings.json +30 -0
  192. package/templates/qoder/skills/design-import/SKILL.md +22 -13
  193. package/templates/qoder/skills/design-review/SKILL.md +19 -10
  194. package/templates/qoder/skills/prd-generator/SKILL.md +22 -18
  195. package/templates/qoder/skills/prd-review/SKILL.md +6 -4
  196. package/templates/qoder/skills/prototype-generator/SKILL.md +63 -14
  197. package/templates/qoder/skills/spec-coder/SKILL.md +22 -13
  198. package/templates/qoder/skills/spec-generator/SKILL.md +22 -10
  199. package/templates/qoder/skills/test-generator/SKILL.md +7 -5
  200. package/templates/qoder/skills/wl-code/SKILL.md +23 -11
  201. package/templates/qoder/skills/wl-commit/SKILL.md +9 -8
  202. package/templates/qoder/skills/wl-design/SKILL.md +5 -3
  203. package/templates/qoder/skills/wl-init/SKILL.md +6 -6
  204. package/templates/qoder/skills/wl-insight/SKILL.md +23 -10
  205. package/templates/qoder/skills/wl-prd-full/SKILL.md +57 -6
  206. package/templates/qoder/skills/wl-prd-quick/SKILL.md +3 -3
  207. package/templates/qoder/skills/wl-prd-review/SKILL.md +16 -4
  208. package/templates/qoder/skills/wl-report/SKILL.md +25 -23
  209. package/templates/qoder/skills/wl-search/SKILL.md +149 -78
  210. package/templates/qoder/skills/wl-spec/SKILL.md +7 -5
  211. package/templates/qoder/skills/wl-status/SKILL.md +48 -16
  212. package/templates/qoder/skills/wl-task/SKILL.md +92 -10
  213. package/templates/qoder/skills/wl-test/SKILL.md +75 -29
  214. package/templates/qoder/templates/prd-full-template.md +7 -0
  215. package/templates/root/AGENTS.md +275 -236
  216. package/templates/root/requirements.txt +3 -0
  217. package/templates/root//344/275/277/347/224/250/350/257/264/346/230/216.md +3 -3
  218. package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +2 -2
  219. package/templates/.qoder/.runtime/ctx-cache-5660152f1d6dd819.md +0 -23
  220. package/templates/.qoder/.runtime/ctx-cache-afdce0dac06b25b0.md +0 -23
  221. package/templates/.qoder/.runtime/search-cache-eae7644e7b122f35.txt +0 -1
  222. package/templates/.qoder/learning/eval-history.jsonl +0 -28
  223. package/templates/data/index/wiki-index.json +0 -8
  224. package/templates/qoder/nul +0 -4
  225. package/templates/qoder/scripts/kg/extract.py +0 -398
  226. package/templates/qoder/scripts/kg/kg_semantic.py +0 -156
  227. package/templates/qoder/scripts/mcp/kg_mcp_server.py +0 -606
  228. package/templates/qoder/scripts/mcp/mcp_launcher.py +0 -442
  229. package/templates/qoder/scripts/mcp/zentao_mcp_server.py +0 -384
  230. package/templates/qoder/scripts/task/__init__.py +0 -11
  231. package/templates/qoder/scripts/test/__init__.py +0 -11
  232. package/templates/qoder/scripts/wlkj.py +0 -116
  233. /package/templates/qoder/scripts/{common → deployment}/__init__.py +0 -0
  234. /package/templates/qoder/scripts/{common → domain/kg/graph}/graph_traverse.py +0 -0
  235. /package/templates/qoder/scripts/{common → domain/kg/server}/repowiki.py +0 -0
  236. /package/templates/qoder/scripts/{common → foundation/io}/atomicio.py +0 -0
  237. /package/templates/qoder/scripts/{test → validation/test}/secure-ls.js +0 -0
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """user-prompt-submit.py - UserPromptSubmit hook: /wl-prd-* 必须先问平台 (代码硬墙)
4
+
5
+ 吸收宿主确定性 hook 能力: 把 CRITICAL RULE #1 "先问平台" 从"靠 LLM 自觉"
6
+ 升级为"宿主在用户提交时拦截"。AI 想忘都忘不了。
7
+
8
+ 历史教训 (REFACTOR_PROGRESS M4): 旧版 UserPromptSubmit hook 因"激进注入上下文"被删。
9
+ 本次只做一件事 —— 命中 /wl-prd-* 且无平台词时 exit 2 阻断, 不注入任何 stdout 文本,
10
+ 保持非侵入式。未命中 / 自然语言一律放行 (exit 0)。
11
+
12
+ 阻断契约 (照搬 platform_guard.py, Qoder 镜像 Claude Code hook 体系):
13
+ - exit 0 = 放行
14
+ - exit 2 = 阻断, stderr 作为反馈展示给 Agent/用户, 停住等用户答平台
15
+
16
+ stdin 字段名: 官方未公开, 此处兼容多种可能 (prompt / user_input / message / text),
17
+ 首字段命中即用。若都取不到 → 保守放行 (绝不误阻断)。
18
+ """
19
+ import json
20
+ import os
21
+ import re
22
+ import sys
23
+
24
+ if sys.platform == 'win32':
25
+ try:
26
+ sys.stdout.reconfigure(encoding='utf-8')
27
+ sys.stderr.reconfigure(encoding='utf-8')
28
+ except Exception:
29
+ pass
30
+
31
+ NL = chr(10)
32
+ BASE = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
33
+ HOOK_ERRORS_LOG = os.path.join(BASE, '.qoder', '.runtime', 'hook-errors.log')
34
+
35
+ # 命中 /wl-prd-* 的正则 (full/quick/review 等子命令都覆盖)
36
+ PRD_CMD_RE = re.compile(r'/wl-prd-', re.IGNORECASE)
37
+ # 平台已声明词 (任一出现即视为已问平台, 放行)
38
+ PLATFORM_WORDS = ('web', 'app', 'pc', 'h5', '管理端', '移动端', '两端', 'fywl-ui', 'carmg', '两端都要')
39
+ # 明确"正在问平台"的措辞 (避免 AI 把问平台的话本身当成已选)
40
+ ASKING_PHRASES = ('请选择', '哪个平台', '请选择 (1/2/3)', '选 (1/2/3)')
41
+
42
+
43
+ def _read_prompt():
44
+ """从 stdin 读用户输入文本。兼容多种字段名 + 纯文本兜底。取不到返回 None。"""
45
+ raw = None
46
+ try:
47
+ if not sys.stdin.isatty():
48
+ raw = sys.stdin.read()
49
+ except Exception:
50
+ return None
51
+ if not raw:
52
+ return None
53
+ raw = raw.strip()
54
+ # 1. 尝试 JSON (宿主喂的结构化输入)
55
+ try:
56
+ data = json.loads(raw)
57
+ if isinstance(data, dict):
58
+ for key in ('prompt', 'user_input', 'message', 'text', 'content', 'input'):
59
+ v = data.get(key)
60
+ if isinstance(v, str) and v.strip():
61
+ return v
62
+ # 嵌套 messages[-1].content 等
63
+ msgs = data.get('messages')
64
+ if isinstance(msgs, list) and msgs:
65
+ last = msgs[-1]
66
+ if isinstance(last, dict):
67
+ c = last.get('content') or last.get('text')
68
+ if isinstance(c, str):
69
+ return c
70
+ except (ValueError, TypeError):
71
+ pass
72
+ # 2. 纯文本兜底
73
+ return raw if raw else None
74
+
75
+
76
+ def _should_block(prompt_text):
77
+ """是否阻断: 命中 /wl-prd-* 且无平台词 且 不是在问平台本身。"""
78
+ if not prompt_text:
79
+ return False
80
+ if not PRD_CMD_RE.search(prompt_text):
81
+ return False
82
+ low = prompt_text.lower()
83
+ # AI 正在问平台 (这段 prompt 是 AI 发的提问) → 不拦, 让它继续问
84
+ if any(p in prompt_text for p in ASKING_PHRASES):
85
+ return False
86
+ # 已含平台词 → 放行
87
+ if any(w.lower() in low for w in PLATFORM_WORDS):
88
+ return False
89
+ return True
90
+
91
+
92
+ def _record_violation():
93
+ """best-effort 上报一次 rule_violation (不阻塞拦截本身)。注意避开 learn import 断链。"""
94
+ try:
95
+ learn_dir = os.path.join(BASE, '.qoder', 'scripts', 'domain', 'learning')
96
+ if learn_dir not in sys.path:
97
+ sys.path.insert(0, learn_dir)
98
+ # bootstrap foundation 路径
99
+ foundation_dir = os.path.join(BASE, '.qoder', 'scripts', 'foundation')
100
+ if foundation_dir not in sys.path:
101
+ sys.path.insert(0, foundation_dir)
102
+ from learn import record_feedback # noqa
103
+ record_feedback('rule_violation', {
104
+ 'rule': 'ask_platform_first',
105
+ 'skill': 'wl-prd (UserPromptSubmit hook)',
106
+ 'detail': '用户提交 /wl-prd-* 未含平台词, hook 已阻断',
107
+ })
108
+ except Exception:
109
+ pass
110
+
111
+
112
+ def main():
113
+ try:
114
+ prompt = _read_prompt()
115
+ if _should_block(prompt):
116
+ _record_violation()
117
+ sys.stderr.write(
118
+ '【平台硬墙】/wl-prd-* 必须先问平台 (Web管理端 / APP移动端 / 两端都要)。\n'
119
+ '参考 AGENTS.md CRITICAL RULE #1: 先问平台, 不自动判断, 不跳过。\n'
120
+ '已记录一次规则违规。请先回答平台选择, 再继续。\n')
121
+ sys.exit(2) # 阻断
122
+ sys.exit(0) # 放行
123
+ except SystemExit:
124
+ raise
125
+ except Exception as e:
126
+ # 铁律: hook 崩溃绝不阻塞会话 → 保守放行 + 落盘日志
127
+ try:
128
+ os.makedirs(os.path.dirname(HOOK_ERRORS_LOG), exist_ok=True)
129
+ with open(HOOK_ERRORS_LOG, 'a', encoding='utf-8') as f:
130
+ from datetime import datetime
131
+ f.write('[{}] user-prompt-submit: {}\n'.format(
132
+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'), str(e)[:200]))
133
+ except Exception:
134
+ pass
135
+ sys.exit(0)
136
+
137
+
138
+ if __name__ == '__main__':
139
+ main()
@@ -53,6 +53,26 @@ test -f .qoder/.developer && echo "已初始化" || echo "未初始化"
53
53
  注意:用户说"同步/保存产出"通常指 team_sync(push),不是 git commit;
54
54
  用户说"提交/commit 代码"才是 wl-commit。
55
55
 
56
+ ## 规则 0.5:数据库查询必须先问环境(安全红线,问了就停)
57
+
58
+ AI 检测到需要查询**真实数据库**(调用 `mcp__qoder-mysql` 的 query_schema / query_data /
59
+ query_distinct / list_databases / list_tables 等)时,**绝不能直接发查询**,必须:
60
+
61
+ 1. **先调 `mcp__qoder-mysql__list_envs()`** 取环境列表;
62
+ 2. **把可选环境列给用户,问"要查哪个环境"**,然后**停下等用户选**;
63
+ 3. 用户选定后,后续查询都带 `env=<用户选的标签>`。
64
+
65
+ 环境由 `.qoder/config.yaml` 的 `mysql.environments` 定义,标签可自定义
66
+ (test/pre/prod 或 qa/staging…)。**禁止自行假定环境**,即便用户没明说,
67
+ 也要先问——这是为了杜绝误连生产库。
68
+
69
+ 查询结果自带环境声明(由 MCP 注入):
70
+ - 测试环境 → 数据是样本,不代表线上分布
71
+ - 生产环境 → 🔴 真实数据,仅供核对字段含义/格式,**禁止作为业务结论外传**
72
+
73
+ > 同一轮对话里用户已选过环境、追问同一库,可不再重复问。
74
+ > 默认环境见 `mysql.default_env`(通常 test),但"首次仍问"是硬约束。
75
+
56
76
  ## 规则 1:PRD/原型需求必须先问平台(问了就停,不许边问边干)
57
77
 
58
78
  用户提出 PRD、原型、需求分析类请求时,第一步永远是问(绝不自动判断):
@@ -73,8 +93,8 @@ test -f .qoder/.developer && echo "已初始化" || echo "未初始化"
73
93
  ## 规则 2:查代码索引优先,索引找不到才准 grep(又快又准的取数顺序)
74
94
 
75
95
  ```bash
76
- python .qoder/scripts/kg/kg.py context <业务关键词> --platform <web|app> [--role pm|design|dev|test] # 一次取全(首选, 秒级)
77
- python .qoder/scripts/kg/search_index.py <关键词> --platform <web|app> # 单项搜索
96
+ python .qoder/scripts/orchestration/wlkj.py kg context <业务关键词> --platform <web|app> [--role pm|design|dev|test] # 一次取全(首选, 秒级)
97
+ python .qoder/scripts/orchestration/wlkj.py search <关键词> --platform <web|app> # 单项搜索
78
98
  ```
79
99
  kg.py context(= context_pack)一条命令返回:相关代码文件 + 同类页面示例 + 字段规格 +
80
100
  相关 PRD + 设计 Token + 图标参考 + 模板路径。kg.py 还有 12 个兄弟能力
@@ -83,9 +103,34 @@ kg.py context(= context_pack)一条命令返回:相关代码文件 + 同
83
103
  **取数顺序(强制,违反 = 慢 + 凭空写 PRD):**
84
104
  1. **先用索引**:任何 /wl-* 命令查代码,**第一步永远是 kg.py context**(查预建图谱,秒级,不碰文件系统)。绝大多数需求一次就够。
85
105
  2. **索引够用就停**:context 列出了相关文件/字段/API → 只用 Read 读那 1-2 个 .vue,**不要再用 Grep/Glob 去文件系统扫**。
86
- 3. **索引真找不到才 grep 兜底**:只有当 kg.py/search_index 明确返回"无匹配"或缺了某个具体点时,才回退到 Grep/Glob 直搜 —— 且**只搜 context 指向的范围**,不准对 data/code/(8973+ 文件)或整个 qoderAll 仓全库扫。
106
+ 3. **中文文案/报错溯源用 grep-text**:用户查的是中文短语(报错文案"车辆不存在"、字段标签"项目车号"、业务词),kg.py 的代码标识符索引天然查不到。**这时只能用 `kg.py grep-text <中文短语>`**(单进程 Python,限定 data/code,限定扩展名,秒回,不弹窗)。
107
+ 4. **🚫 硬性禁令(违反 = QoderWork 卡死 + 疯狂弹 cmd 窗口)**:
108
+ - **禁止**用 `findstr /s`、`grep -r`、`rg` 递归扫整个 data/code(8973+ 文件)或 qoderAll 仓
109
+ - **禁止**用 `os.walk` / `os.system` / `subprocess` 全盘递归搜文件
110
+ - **禁止**在 Bash 里手写 Python `-c "import os; for ... os.walk(...)"` 全库遍历
111
+ - 兜底搜索**唯一合法方式** = `kg.py grep-text`(已内置单进程、范围限定、命中上限)
112
+ - Grep/Glob 工具**只准搜 context/grep-text 已定位到的具体文件或单一小目录**,不准全库扫
113
+
114
+ **为什么这条是红线**:QoderWork 自带 Agent 默认会用 Grep/Glob 直搜文件系统,它不懂"业务源码在 data/code/ 镜像里",会搜整个 qoderAll 仓然后报"无匹配",被迫凭空编字段/API。更糟的是 AI 兜底去跑 `findstr /s` 全盘扫描 → Windows 对 8973 文件递归 = 卡死 + 疯狂弹子进程窗口,用户只能强杀。**Agent 只准用来**:①读 context 列出的具体文件(Read)②**在 /wl-insight 里**做 web 调研(对标/竞品)和多视角探索脑暴。**绝不用 Agent 去"发现/搜索"代码——那是 kg.py 的活。** 注意:探索类 Agent 调研已集中到 `/wl-insight`,`/wl-prd-full` 不再派 Agent 做 web 搜索/脑暴。
115
+
116
+ ## 规则 2.5:工具调用能并发就并发(性能命门,串行 = 慢)
117
+
118
+ **串行执行是工作流慢的最大元凶。** 每次工具调用都要等返回(图谱查询 2-3 秒、读文件 1 秒、
119
+ 命令行 3-5 秒),10 个串行步骤 = 白等 30-50 秒。MCP 工具调用**支持同一回合并发**,必须利用:
87
120
 
88
- **为什么这条是红线**:QoderWork 自带 Agent 默认会用 Grep/Glob 直搜文件系统,它不懂"业务源码在 data/code/ 镜像里",会搜整个 qoderAll 仓然后报"无匹配",被迫凭空编字段/API。**Agent 只准用来**:①读 context 列出的具体文件(Read)②**在 /wl-insight 里**做 web 调研(对标/竞品)和多视角探索脑暴。**绝不用 Agent 去"发现/搜索"代码——那是 kg.py 的活。** 注意:探索类 Agent 调研已集中到 `/wl-insight`,`/wl-prd-full` 不再派 Agent 做 web 搜索/脑暴。
121
+ **并发规则(全 /wl-* 命令强制):**
122
+ 1. **多个独立的 search/Read → 同一 assistant 回合一起发**,不要"发一个、等返回、再发下个"。
123
+ 确定要读 3 个文件后,一个回合同时发 3 个 Read。
124
+ 2. **多个独立搜索可并发**:要搜 `OSS` + `upload` 两个关键词,一次发 2 个 search_code。
125
+ 3. **只有"后步依赖前步结果"才串行**:先 search 拿路径才能 Read(必须串行);但路径已知后,
126
+ 多个 Read 必须**并发**。
127
+ 4. **一轮思考塞满**:能同回合发的工具调用全发出去,等它们一起回来,别"一回合一个"。
128
+
129
+ **反例(禁止)**:search A → 等 → Read X → 等 → search B → 等 → Read Y → 等 ...
130
+ **正例(正确)**:[search A + search B] 并发 → 等 → [Read X + Read Y + Read Z] 并发 → 答
131
+
132
+ > 这是工作流比原生慢的根因——原生 AI 本能地并发,工作流却被"逐步执行"的文档节奏带成了串行。
133
+ > 把串行变并发,同样工作量耗时可砍到 1/3。MCP server(kg/mysql/zentao)都支持 JSON-RPC 并发请求。
89
134
 
90
135
  ## 规则 3:原型风格必须来自真源(含图标)
91
136
 
@@ -128,19 +173,19 @@ PM /wl-prd-full → AI 出初稿 PRD + 原型
128
173
  ## 规则 4:PRD 必须套团队模板 + 过 EVA 门禁
129
174
 
130
175
  - 完整需求用 .qoder/templates/prd-full-template.md,零星需求用 prd-quick-template.md
131
- - 发布前:`python .qoder/scripts/report/eval_prd.py <prd> [原型]` 必须 PASS (≥80%)
176
+ - 发布前:`python .qoder/scripts/orchestration/wlkj.py eval <prd> [原型]` 必须 PASS (≥80%)
132
177
  - 发现确认采用批量方式(一个编号列表一轮确认),不要逐条问
133
178
 
134
179
  ## 规则 5:用户永不接触 git
135
180
 
136
- - 产出保存/发布后自动执行 `python .qoder/scripts/task/team_sync.py push`
137
- - 拉取团队最新:`python .qoder/scripts/task/team_sync.py pull`
181
+ - 产出保存/发布后自动执行 `python .qoder/scripts/orchestration/wlkj.py sync push`
182
+ - 拉取团队最新:`python .qoder/scripts/orchestration/wlkj.py sync pull`
138
183
  - 出现 SYNC_CONFLICT 由 AI 按提示自行解决,绝不让用户跑 git 命令
139
184
 
140
185
  ## 规则 6:环境问题找 doctor
141
186
 
142
187
  任何"索引不对/搜不到/环境坏了"类问题:
143
- `python .qoder/scripts/setup/init_doctor.py`(加 --fix 自动修复,幂等增量,不会重头构建)
188
+ `python .qoder/scripts/orchestration/wlkj.py doctor`(加 --fix 自动修复,幂等增量,不会重头构建)
144
189
 
145
190
  ## 规则 7:Repo Wiki 是补充知识源
146
191
 
@@ -188,3 +233,20 @@ PM /wl-prd-full → AI 出初稿 PRD + 原型
188
233
  > 环境/域名在 config.yaml `autotest:` 配,`--url` 可临时覆盖。
189
234
 
190
235
  用户用自然语言表达即可,AI 负责映射到命令和脚本。
236
+
237
+ ---
238
+
239
+ ## 工作流可用性自检(吸收宿主能力:会话上下文注入)
240
+
241
+ 会话开头 `<qoder-context>` 里的 **Workflow Usability** 段是宿主 SessionStart hook
242
+ 自动注入的"近7天红灯"(一次过审率/规则违反率不达标)。**见到红灯时遵守:**
243
+
244
+ 1. **红灯 = 工作流某环节没跑起来**,不是忽略它继续干活。
245
+ 2. 一次过审率低(<60%):写 PRD 前先读 `data/learning/patterns/prd-patterns.md` 避坑。
246
+ 3. 规则违反率高(>10%):`/wl-prd-*` 启动**必须先问平台**(铁律1),不问就是新增违规。
247
+ 4. 想看全貌:`python .qoder/scripts/orchestration/wlkj.py usability` 或 `/wl-status health`(健康分含 adoption 维度)。
248
+ 5. 指标定义/公式/阈值:`data/docs/constitution/workflow-usability-metrics.md`。
249
+
250
+ > 这套指标评"工作流用没用起来",与 EVA(评 PRD 质量)分工不同——EVA 卡发布门禁,
251
+ > 可用性指标卡"工具该不该继续投入"。
252
+
@@ -1,139 +1,102 @@
1
- # .qoder/scripts/ — 引擎脚本目录
1
+ # .qoder/scripts/ — 引擎脚本目录 (分层架构)
2
2
 
3
3
  > 引擎代码, 由 `npx @hupan56/wlkj init/update` 生成, **不进团队 git** (Trellis 化)。
4
- > 用户不需要直接碰这些文件 — 通过 `/命令` 和 `npx` 间接调用。
4
+ > 用户不直接碰这些文件 — 通过 `/命令` 和 `npx` 间接调用。
5
5
 
6
- ## 按职责分类 (命名前缀即分类)
6
+ ## 🏗️ 分层架构 (7 层)
7
7
 
8
- ### 🔍 知识图谱 (`kg_*`, 9 个) 代码/数据库图谱
9
- | 脚本 | 用途 |
10
- |------|------|
11
- | `kg.py` | **统一入口** (search/api/impact/feature), AI 和 /wl-search 都走这里 |
12
- | `kg_build_db.py` | 全量构建图谱 (管理员, 周五 cron) |
13
- | `kg_incremental.py` | 增量更新 (只处理 git diff 变更文件) |
14
- | `kg_duckdb.py` | DuckDB 存储层 (实体/边/工作流) |
15
- | `kg_mcp_server.py` | KG MCP server (QoderWork 连接) |
16
- | `kg_build.py` | 构建编排 |
17
- | `kg_link_db.py` | 数据库图谱链接 |
18
- | `kg_semantic.py` | 语义分析 |
19
- | `kg_auto_login.py` | 自动登录 |
20
- | `kg_test_runner.py` | 图谱测试 |
21
-
22
- ### 🏗️ 索引构建 (`build_*`, 4 个)
23
- | 脚本 | 用途 |
24
- |------|------|
25
- | `build_style_index.py` | UI 风格索引 (表格/表单/字段映射) |
26
- | `build_entity_registry.py` | 实体注册 (功能+端点) |
27
- | `build_relations.py` | 关系边 (click→api, api→controller) |
28
- | `build_workflows.py` | 业务流程索引 |
8
+ 子目录化 (v3.0) 后, 脚本按职责分层, 顶层**无散落 .py**, 只有 7 个分层目录:
29
9
 
30
- ### 🩺 诊断检查 (`check_*`, 4 个)
31
- | 脚本 | 用途 |
32
- |------|------|
33
- | `check_mcp.py` | MCP 配置检查 |
34
- | `check_mcp_launch.py` | MCP 启动诊断 (根治黄色) |
35
- | `check_carriers.py` | 规则载体检查 (Qoder 全系列兼容) |
36
- | `check_qoderwork_consistency.py` | QoderWork 一致性 |
10
+ ```
11
+ scripts/
12
+ ├── orchestration/ 编排层 — wlkj.py 统一入口 (载体收敛点)
13
+ ├── foundation/ 基础层 共享库 (被所有层 import)
14
+ ├── domain/ 领域层 业务逻辑 (kg/task/report/...)
15
+ ├── protocol/ 协议层 MCP server / 传输适配
16
+ ├── capability/ 能力层 链式能力编排 / 冒烟测试
17
+ ├── validation/ 验证层 — 测试 / 评测 / 基准
18
+ └── deployment/ 部署层 — 安装 / 体检 / 载体同步
19
+ ```
37
20
 
38
- ### 🔎 代码提取 (`extract_*`, 3 个)
39
- | 脚本 | 用途 |
40
- |------|------|
41
- | `extract_routes.py` | 路由提取 |
42
- | `extract_routes_tree.py` | 路由树 |
43
- | `extract_api_params.py` | API 参数提取 |
21
+ ## 🚪 统一入口: `orchestration/wlkj.py` (Facade)
44
22
 
45
- ### 🧪 测试 (`autotest_*`, 3 个)
46
- | 脚本 | 用途 |
47
- |------|------|
48
- | `autotest.py` | 自动测试入口 |
49
- | `autotest_batch.py` | 批量测试 |
50
- | `autotest_run.py` | 单次执行 |
23
+ **所有 Qoder 载体 (commands/skills/rules) 的脚本调用都走这个入口**, 由 DISPATCH 表路由到
24
+ 分层路径。这样 scripts/ 重组目录时只改 DISPATCH 一处, 载体不受影响。
51
25
 
52
- ### 🚀 初始化与身份 (`init_*`/`setup`/`role`/`identity`)
53
- | 脚本 | 用途 |
54
- |------|------|
55
- | `setup.py` | **一键就绪** (npx init 调的主体) |
56
- | `init_doctor.py` | 环境体检 + 自愈 + 身份注册 |
57
- | `install_qoderwork.py` | QoderWork 技能/MCP 安装 |
58
- | `role.py` | 角色管理 |
59
- | `repo_root.py` | 仓库根探测 |
26
+ ```bash
27
+ python .qoder/scripts/orchestration/wlkj.py <命令> [参数...]
28
+ # 例: wlkj.py kg search 保险 | wlkj.py task list | wlkj.py doctor --fix
29
+ ```
60
30
 
61
- ### 🔄 同步与任务
62
- | 脚本 | 用途 |
63
- |------|------|
64
- | `team_sync.py` | **团队同步** (pull/push, /wl-task finish 调) |
65
- | `git_sync.py` | 源码仓库同步 + PRD 归档 |
66
- | `task.py` | **任务系统** (create/list/start/finish) |
67
- | `syncgate.py` | 提交前零信任门禁 |
68
- | `sync_carriers.py` | 规则载体同步 |
31
+ 完整命令表见 `wlkj.py` 的 DISPATCH (kg/search/context/task/sync/req/eval/learn/status/report/test/doctor 等 36 条)。
32
+ 脚本内部互调 (Python 进程间) 直接用分层路径, 不绕 wlkj (避免 subprocess 嵌套)。
69
33
 
70
- ### 📊 评测与报告
71
- | 脚本 | 用途 |
72
- |------|------|
73
- | `eval_prd.py` | **PRD 质量门禁** (EVA, >=80% 才发布) |
74
- | `report.py` | 日报/周报生成 |
75
- | `status.py` | 项目状态 |
76
- | `benchmark.py` | 性能基准 |
34
+ ## 各层职责 + 关键脚本
77
35
 
78
- ### 🔧 上下文与搜索
36
+ ### 🎼 orchestration/ — 编排
79
37
  | 脚本 | 用途 |
80
38
  |------|------|
81
- | `search_index.py` | **代码搜索** (/wl-search) |
82
- | `context_pack.py` | **一键上下文** (/wl-code, /wl-prd 用) |
83
- | `enrich_prompt.py` | prompt 增强 |
84
- | `fill_prototype.py` | 原型填充 |
39
+ | `wlkj.py` | **统一调度入口**, DISPATCH 透明转发到各层脚本 |
85
40
 
86
- ### 🎨 设计与原型
87
- | 脚本 | 用途 |
41
+ ### 🧱 foundation/ — 基础 (共享库, 不含业务)
42
+ | 模块 | 用途 |
88
43
  |------|------|
89
- | `gen_design_doc.py` | 设计文档生成 |
90
- | `setup_lanhu.py` | 蓝湖配置 |
91
- | `lanhu_stdio_wrapper.py` | 蓝湖 MCP wrapper |
92
-
93
- ### 🔌 MCP 服务 (`*_mcp_server.py`, 4 )
44
+ | `bootstrap.py` | sys.path 自举 (子目录化后定位 scripts/ 根) |
45
+ | `core/paths.py` | **路径管理** (PROJECT_ROOT / get_repo_root / get_developer) |
46
+ | `identity/` | 身份 (identity.py / developer.py / roles.py 角色章节) |
47
+ | `io/` | 原子 IO (atomicio.py) / 文件锁 (filelock.py) |
48
+ | `protocol/mcp_base.py` | MCP server 基类 (@tool 装饰器 + 元类注册) |
49
+ | `integrations/` | 术语扩展 (terms.py) / 禅道客户端 (zentao_client.py, 单一真源) |
50
+ | `utils/eval_api.py` | 评测 API |
51
+
52
+ ### 🎯 domain/ — 领域 (业务逻辑)
53
+ | 子包 | 关键脚本 | 用途 |
54
+ |------|---------|------|
55
+ | `kg/` | `kg.py` (**图谱统一入口**, 13+ 能力) | 知识图谱 |
56
+ | `kg/search/` | search_index.py / context_pack.py / prefetch.py | 代码搜索 / 一键上下文 |
57
+ | `kg/build/` | kg_build.py / kg_build_db.py / kg_incremental.py / build_style_index.py | 图谱构建 |
58
+ | `kg/graph/` | kg_semantic.py / kg_link_db.py | 语义 / 数据库图谱链接 |
59
+ | `kg/storage/` | kg_duckdb.py | DuckDB 存储层 |
60
+ | `kg/server/` | kgd.py (常驻服务) / perf_bench.py | 语义加速服务 |
61
+ | `task/` | task.py (**任务系统**) / team_sync.py / git_sync.py / zentao_sync.py / syncgate.py | 任务 + 同步 |
62
+ | `requirement/` | req.py / archive_prd.py | 需求生命周期 |
63
+ | `report/` | report.py / status.py / role.py / export.py / *_snapshot.py | 报告 / 状态 |
64
+ | `design/` | fill_prototype.py / gen_design_doc.py | 原型填充 / 设计文档 |
65
+ | `learning/` | learn.py | 学习飞轮 (埋点) |
66
+
67
+ ### 🔌 protocol/ — 协议
68
+ | 子包 | 脚本 | 用途 |
69
+ |------|------|------|
70
+ | `mcp/` | mcp_launcher.py (**统一启动器**) / kg_mcp_server.py / mysql_mcp_server.py / zentao_mcp_server.py / lanhu_stdio_wrapper.py / mcp_doctor.py | 4 个自有 MCP server |
71
+ | `transports/` | cli.py | CLI 传输适配 |
72
+
73
+ ### 🧩 capability/ — 能力编排
94
74
  | 脚本 | 用途 |
95
75
  |------|------|
96
- | `mcp_launcher.py` | **MCP 统一启动器** (根治黄色) |
97
- | `kg_mcp_server.py` | 知识图谱 MCP |
98
- | `mysql_mcp_server.py` | MySQL MCP (只读) |
99
- | `zentao_mcp_server.py` | 禅道 MCP |
76
+ | `chain.py` / `memory_chain.py` | 链式能力编排 |
77
+ | `adapters/` (cli.py / qw.py / mcp.py) | 能力适配器 (CLI/QoderWork/MCP) |
100
78
 
101
- ### 📚 学习与知识沉淀
102
- | 脚本 | 用途 |
103
- |------|------|
104
- | `learn.py` | **learning 引擎** (埋点/反馈) |
105
- | `learn_aggregate.py` | 学习聚合 |
79
+ ### 🧪 validation/ — 验证
80
+ | 子包 | 关键脚本 | 用途 |
81
+ |------|---------|------|
82
+ | `test/` | autotest.py / smoke_all_commands.py / benchmark.py / kg_test_runner.py | 自动测试 / 冒烟 / 基准 |
83
+ | `metrics/` | eval_prd.py / usability_score.py | **PRD 质量门禁** (EVA, ≥80%) + **工作流可用性** (采纳+流程) |
84
+ | `eval/` | 性能评测报告 | |
106
85
 
107
- ### 🛠️ 其它工具
86
+ ### 🚀 deployment/ — 部署
108
87
  | 脚本 | 用途 |
109
88
  |------|------|
110
- | `page_probe.py` | 页面探测 (浏览器测试) |
111
- | `platform_doctor.py` | 平台体检 |
112
- | `archive_prd.py` | PRD 归档 |
113
- | `export.py` | 导出 |
114
- | `add_session.py` | 会话管理 |
115
-
116
- ### 📦 `common/` — 共享库 (被上述脚本 import)
117
- | 模块 | 用途 |
118
- |------|------|
119
- | `paths.py` | **路径管理** (PROJECT_ROOT 探测, cwd 优先) |
120
- | `developer.py` / `identity.py` | 身份 |
121
- | `filelock.py` | 文件锁 (防并发) |
122
- | `atomicio.py` | 原子 IO (防损坏) |
123
- | `search_engine.py` | 搜索引擎 |
124
- | `graph_traverse.py` | 图谱遍历 |
125
- | `eval_api.py` | 评测 API |
126
- | `terms.py` | 术语扩展 |
127
- | `feishu.py` | 飞书通知 |
128
- | `pip_install.py` | pip 镜像兜底 |
129
- | `platform_guard.py` | 平台守卫 |
130
- | `repowiki.py` | 仓库 Wiki |
131
- | `utf8.py` | UTF-8 工具 |
89
+ | `setup.py` | **一键就绪** (npx init 调的主体) |
90
+ | `init_doctor.py` | 环境体检 + 自愈 + 身份注册 |
91
+ | `install_qoderwork.py` | QoderWork 技能/MCP 安装 |
92
+ | `carriers.py` | **载体一致性** (check/check-paths/sync/all, 4 载体对齐) |
93
+ | `repo_root.py` | 仓库根探测 (QoderWork 桌面端用) |
94
+ | `setup_lanhu.py` / `platform_doctor.py` | 蓝湖配置 / 平台体检 |
132
95
 
133
96
  ## 设计原则
134
97
 
135
- 1. **命名即分类**: `kg_*` / `build_*` / `check_*` / `extract_*` / `autotest_*` 前缀 = 隐式分组
136
- 2. **统一入口**: `kg.py` 是图谱统一入口, `task.py` 是任务统一入口 (不是 60 个并列入口)
137
- 3. **common/ 共享**: 通用逻辑抽到 common/, 不重复
138
- 4. **幂等**: 所有脚本可重复跑, 不重头再来 ( init_doctor 的增量保证)
139
- 5. **降级不崩**: 缺依赖/缺数据时优雅降级, 绝不 sys.exit 崩溃 (见 mcp_launcher)
98
+ 1. **分层即分类**: 物理目录 = 职责分层 (foundation/domain/protocol/...), 取代旧的命名前缀
99
+ 2. **单一入口**: `orchestration/wlkj.py` 是载体层唯一收敛点; `domain/kg/kg.py` 是图谱入口; `domain/task/task.py` 是任务入口
100
+ 3. **foundation/ 共享**: 通用逻辑抽到 foundation/, 领域无关 (路径/身份/IO/协议基类)
101
+ 4. **载体与引擎解耦**: 载体 (commands/skills) 只认 wlkj.py 一个路径, 引擎目录重组不波及载体
102
+ 5. **降级不崩**: 缺依赖/缺数据时优雅降级, 绝不 sys.exit 崩溃 (见 protocol/mcp/mcp_launcher.py)
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ nexus —— 宿主能力抽象层(Capability Nexus)。
4
+
5
+ 工作流不问宿主是谁,只问它有什么能力。
6
+ QoderWork / ZCode / Codex / ClaudeCode 有 memory / cron / mcp 就用,
7
+ 没有就静默回退(Null Object),绝不报错。
8
+
9
+ 主轴: 能力契约(Capability Protocol)+ MCP 优先 + 职责链(Provider Chain)
10
+
11
+ 用法:
12
+ from capability import resolve
13
+ cap = resolve()
14
+ cap.mcp.call("list_executions", {...}) # L1 已有 MCP(禅道/知识图谱...)
15
+ cap.memory.remember("本周", "73/74/75") # L2 职责链(MCP→QW→文件→NoOp)
16
+
17
+ 诊断:
18
+ python .qoder/scripts/capability # 打印当前宿主 + 各能力状态
19
+
20
+ 设计文档: .qoder/data/docs/architecture/nexus-capability-layer.md
21
+ """
22
+ from .registry import resolve, detect_host, Nexus, HOST_TABLE
23
+
24
+ __all__ = ["resolve", "detect_host", "Nexus", "HOST_TABLE"]
25
+
26
+ __version__ = "0.1.0"
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ nexus CLI 入口 —— 诊断当前宿主能力。
5
+
6
+ 用法:
7
+ python .qoder/scripts/capability # 打印宿主 + 各能力 available
8
+ python -m nexus # 等价(需 scripts 在 sys.path)
9
+
10
+ 输出 JSON,便于人或脚本消费。
11
+ """
12
+ import json
13
+ import os
14
+ import sys
15
+
16
+
17
+ def _ensure_scripts_on_path():
18
+ """确保父目录 scripts/ 在 sys.path,使 nexus 包可被 import。"""
19
+ here = os.path.dirname(os.path.abspath(__file__))
20
+ scripts_dir = os.path.dirname(here)
21
+ if scripts_dir not in sys.path:
22
+ sys.path.insert(0, scripts_dir)
23
+
24
+
25
+ def main() -> int:
26
+ _ensure_scripts_on_path()
27
+ from capability.registry import resolve
28
+
29
+ cap = resolve()
30
+ desc = cap.describe()
31
+
32
+ # MCP server 详情
33
+ mcp_desc = cap.mcp.describe() if hasattr(cap.mcp, "describe") else {}
34
+
35
+ # memory 职责链详情
36
+ memory_chain = []
37
+ if hasattr(cap.memory, "providers_status"):
38
+ memory_chain = cap.memory.providers_status()
39
+ desc["memory_chain"] = memory_chain
40
+
41
+ # 格式化输出
42
+ print("宿主: %s" % desc.get("host", "?"))
43
+ print()
44
+ print("能力:")
45
+ for name, avail in desc.get("capabilities", {}).items():
46
+ icon = "✅" if avail else "❌"
47
+ print(" %s %s" % (icon, name))
48
+
49
+ if mcp_desc.get("servers"):
50
+ print()
51
+ print("MCP servers (tools=%d):" % mcp_desc.get("total_tools", 0))
52
+ for name, info in mcp_desc["servers"].items():
53
+ icon = "✅" if info.get("available") else "❌"
54
+ pid = " pid=%s" % info["spawn_pid"] if info.get("spawn_pid") else ""
55
+ latency = " latency=%sms" % info["latency_ms"] if info.get("latency_ms") is not None else ""
56
+ print(" %s %s: tools=%d%s%s" % (
57
+ icon, name, info.get("tools_indexed", 0), latency, pid))
58
+
59
+ if memory_chain:
60
+ print()
61
+ print("Memory 职责链:")
62
+ for p in memory_chain:
63
+ hit = " ← ACTIVE" if p.get("hit") else ""
64
+ print(" %s: available=%s%s" % (p["provider"], p["available"], hit))
65
+
66
+ print()
67
+ print(json.dumps(desc, ensure_ascii=False, indent=2))
68
+ return 0
69
+
70
+
71
+ if __name__ == "__main__":
72
+ sys.exit(main())
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ nexus.adapters —— 各宿主/降级路径的 Cap 实现。
4
+
5
+ 设计模式: Adapter + Bridge(Cap 抽象 × 宿主实现 正交)
6
+
7
+ 新增宿主(扩展场景 D)= 新建一个文件(如 devin.py)实现其提供的 Cap,
8
+ 在 registry 的 _resolve_xxx 里按宿主名装配。
9
+ 核心 Facade、工作流代码零改动。
10
+
11
+ 文件:
12
+ mcp.py —— L1 MCP 统一入口(复用禅道/知识图谱等已有 MCP)+ McpMemoryProvider(未来)
13
+ qw.py —— QoderWork 原生能力
14
+ cli.py —— 纯文件降级(核心能力兜底,无宿主依赖)
15
+ """
16
+ from .mcp import McpCap, McpMemoryProvider
17
+ from .qw import QwMemoryCap, is_qoderwork
18
+ from .cli import (
19
+ FileRepoCap,
20
+ FileIdentityCap,
21
+ FileContextCap,
22
+ FileMemoryCap,
23
+ )
24
+
25
+ __all__ = [
26
+ "McpCap", "McpMemoryProvider",
27
+ "QwMemoryCap", "is_qoderwork",
28
+ "FileRepoCap", "FileIdentityCap", "FileContextCap", "FileMemoryCap",
29
+ ]