@hupan56/wlkj 3.3.12 → 3.3.14

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 (103) hide show
  1. package/bin/cli.js +1 -23
  2. package/package.json +29 -29
  3. package/templates/qoder/agents/design-agent.md +20 -0
  4. package/templates/qoder/agents/spec-generator.md +21 -0
  5. package/templates/qoder/commands/optional/wl-spec.md +2 -12
  6. package/templates/qoder/commands/optional/wl-status.md +0 -8
  7. package/templates/qoder/commands/wl-code.md +0 -8
  8. package/templates/qoder/commands/wl-commit.md +1 -11
  9. package/templates/qoder/commands/wl-init.md +129 -129
  10. package/templates/qoder/commands/wl-prd.md +0 -24
  11. package/templates/qoder/commands/wl-search.md +11 -26
  12. package/templates/qoder/commands/wl-task.md +1 -11
  13. package/templates/qoder/commands/wl-test.md +0 -8
  14. package/templates/qoder/config.yaml +8 -3
  15. package/templates/qoder/hooks/session-start.py +365 -384
  16. package/templates/qoder/hooks/stop-eval.py +254 -383
  17. package/templates/qoder/scripts/capability/adapters/mcp.py +314 -322
  18. package/templates/qoder/scripts/capability/registry.py +248 -245
  19. package/templates/qoder/scripts/capability/registry_mcp.py +4 -10
  20. package/templates/qoder/scripts/capability/smoke_test_report.json.new +94 -0
  21. package/templates/qoder/scripts/deployment/setup/init_doctor.py +2 -6
  22. package/templates/qoder/scripts/deployment/setup/install_qoderwork.py +14 -0
  23. package/templates/qoder/scripts/deployment/setup/setup.py +2 -16
  24. package/templates/qoder/scripts/domain/integration/return_to_platform.py +2 -4
  25. package/templates/qoder/scripts/domain/integration/spec_upload.py +4 -4
  26. package/templates/qoder/scripts/domain/kg/build/build_entity_registry.py +12 -12
  27. package/templates/qoder/scripts/domain/kg/build/build_relations.py +12 -12
  28. package/templates/qoder/scripts/domain/kg/extract/asset/__init__.py +10 -0
  29. package/templates/qoder/scripts/domain/kg/extract/asset/asset_tree.py +57 -0
  30. package/templates/qoder/scripts/domain/kg/extract/asset/discussion_importer.py +62 -0
  31. package/templates/qoder/scripts/domain/kg/extract/asset/prd_importer.py +146 -0
  32. package/templates/qoder/scripts/domain/kg/extract/asset/prototype_importer.py +64 -0
  33. package/templates/qoder/scripts/domain/kg/extract/asset/returns_importer.py +52 -0
  34. package/templates/qoder/scripts/domain/kg/extract/build_goal3.py +104 -0
  35. package/templates/qoder/scripts/domain/kg/extract/build_goal4.py +55 -0
  36. package/templates/qoder/scripts/domain/kg/extract/build_goal5.py +95 -0
  37. package/templates/qoder/scripts/domain/kg/extract/db/__init__.py +8 -0
  38. package/templates/qoder/scripts/domain/kg/extract/db/data_profile.py +22 -0
  39. package/templates/qoder/scripts/domain/kg/extract/db/fk_extractor.py +55 -0
  40. package/templates/qoder/scripts/domain/kg/extract/db/schema_extractor.py +90 -0
  41. package/templates/qoder/scripts/domain/kg/extract/inference/__init__.py +9 -0
  42. package/templates/qoder/scripts/domain/kg/extract/inference/community_summarizer.py +206 -0
  43. package/templates/qoder/scripts/domain/kg/extract/inference/embed_builder.py +132 -0
  44. package/templates/qoder/scripts/domain/kg/extract/inference/naming_matcher.py +80 -0
  45. package/templates/qoder/scripts/domain/kg/extract/inference/promote.py +59 -0
  46. package/templates/qoder/scripts/domain/kg/extract/inference/recompute.py +93 -0
  47. package/templates/qoder/scripts/domain/kg/extract/inference/weak_link.py +421 -0
  48. package/templates/qoder/scripts/domain/kg/extract/mybatis/__init__.py +9 -0
  49. package/templates/qoder/scripts/domain/kg/extract/mybatis/all.py +79 -0
  50. package/templates/qoder/scripts/domain/kg/extract/mybatis/mapper_parser.py +99 -0
  51. package/templates/qoder/scripts/domain/kg/extract/mybatis/relation_builder.py +69 -0
  52. package/templates/qoder/scripts/domain/kg/extract/mybatis/sql_extractor.py +78 -0
  53. package/templates/qoder/scripts/domain/kg/extract/prd/__init__.py +8 -0
  54. package/templates/qoder/scripts/domain/kg/extract/prd/prd_chunk_embed.py +105 -0
  55. package/templates/qoder/scripts/domain/kg/extract/prd/prd_llm_extract.py +153 -0
  56. package/templates/qoder/scripts/domain/kg/extract/prd/req_anchor.py +120 -0
  57. package/templates/qoder/scripts/domain/kg/graph/kg_link_db.py +235 -0
  58. package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +5 -41
  59. package/templates/qoder/scripts/domain/kg/kg.py +0 -14
  60. package/templates/qoder/scripts/domain/kg/search/enrich_prompt.py +238 -0
  61. package/templates/qoder/scripts/domain/kg/server/perf_bench.py +197 -0
  62. package/templates/qoder/scripts/domain/kg/switch_project.py +2 -2
  63. package/templates/qoder/scripts/domain/kg/sync_repowiki.py +109 -0
  64. package/templates/qoder/scripts/domain/task/wlkj_panel.py +1348 -1503
  65. package/templates/qoder/scripts/engine/poller.py +219 -0
  66. package/templates/qoder/scripts/foundation/bootstrap.py +145 -145
  67. package/templates/qoder/scripts/orchestration/wlkj.py +189 -306
  68. package/templates/qoder/settings.json +0 -8
  69. package/templates/qoder/skills/wl-spec/SKILL.md +1 -1
  70. package/templates/qoder/commands/wl-data.md +0 -46
  71. package/templates/qoder/commands/wl-fix.md +0 -47
  72. package/templates/qoder/commands/wl-knowledge.md +0 -41
  73. package/templates/qoder/commands/wl-review.md +0 -49
  74. package/templates/qoder/contracts/insight.md +0 -55
  75. package/templates/qoder/hooks/pre-tool-use-commit.py +0 -124
  76. package/templates/qoder/scripts/foundation/io/context_cache.py +0 -94
  77. package/templates/qoder/scripts/tool_guide.md +0 -70
  78. package/templates/qoder/scripts/validation/eval/alignment_matrix.py +0 -176
  79. package/templates/qoder/scripts/validation/eval/bf2_content_fidelity.py +0 -110
  80. package/templates/qoder/scripts/validation/eval/bf2_llmjudge.py +0 -104
  81. package/templates/qoder/scripts/validation/eval/bf_score.py +0 -218
  82. package/templates/qoder/scripts/validation/eval/code_flywheel.py +0 -150
  83. package/templates/qoder/scripts/validation/eval/dispatcher_ab.py +0 -156
  84. package/templates/qoder/scripts/validation/eval/dispatcher_ab_2026-07-21.json +0 -23
  85. package/templates/qoder/scripts/validation/eval/feature_fidelity_flywheel.py +0 -143
  86. package/templates/qoder/scripts/validation/eval/gradient_matrix.py +0 -261
  87. package/templates/qoder/scripts/validation/eval/gradient_matrix_baseline_2026-07-21.json +0 -33
  88. package/templates/qoder/scripts/validation/eval/metrics_dashboard.py +0 -105
  89. package/templates/qoder/scripts/validation/eval/multi_turn_flywheel.py +0 -118
  90. package/templates/qoder/scripts/validation/eval/prd_fidelity_flywheel.py +0 -128
  91. package/templates/qoder/scripts/validation/eval/prd_flywheel.py +0 -148
  92. package/templates/qoder/scripts/validation/eval/prototype_fidelity_flywheel.py +0 -166
  93. package/templates/qoder/scripts/validation/eval/recall_flywheel.py +0 -148
  94. package/templates/qoder/scripts/validation/eval/robustness_flywheel.py +0 -139
  95. package/templates/qoder/scripts/validation/eval/speed_accuracy_flywheel.py +0 -188
  96. package/templates/qoder/scripts/validation/eval/task_flywheel.py +0 -124
  97. package/templates/qoder/scripts/validation/eval/token_flywheel.py +0 -88
  98. package/templates/qoder/scripts/validation/metrics/eval_code_ac.py +0 -177
  99. package/templates/qoder/scripts/validation/metrics/lint_cases.py +0 -170
  100. package/templates/qoder/scripts/validation/test/test_context_cache.py +0 -78
  101. package/templates/qoder/scripts/validation/test/test_lint_cases.py +0 -60
  102. package/templates/qoder/scripts/validation/test/test_pre_tool_use_commit.py +0 -70
  103. package/templates/workspace/specs/REQ-TEST-CTX/.context-cache.json +0 -1
@@ -1,306 +1,189 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # Windows 控制台 UTF-8 修复(ctypes 直调 Windows API,非子shell chcp)
4
- import sys as _s
5
- if _s.platform == 'win32':
6
- import ctypes as _ct, io as _io
7
- try:
8
- _ct.windll.kernel32.SetConsoleOutputCP(65001)
9
- _ct.windll.kernel32.SetConsoleCP(65001)
10
- _s.stdout = _io.TextIOWrapper(_s.stdout.buffer, encoding='utf-8', errors='replace')
11
- _s.stderr = _io.TextIOWrapper(_s.stderr.buffer, encoding='utf-8', errors='replace')
12
- except Exception:
13
- pass
14
- """
15
- wlkj.py - 工作流顶层调度器 (Facade 统一入口)
16
-
17
- 角色: 所有 Qoder 载体 (commands/skills/rules 里写的脚本调用) 统一走本入口,
18
- 由 DISPATCH 表路由到 scripts/ 下分层子目录的真实脚本。这样:
19
- - 载体文件只认一个路径 (orchestration/wlkj.py); scripts/ 重组目录时
20
- 只需改 DISPATCH 一处, 载体文件不受影响 (根治"目录一重组就断链")
21
- - 脚本内部互调 (Python 进程间) 仍直接用分层路径, 不绕本入口 (避免 subprocess 嵌套)。
22
-
23
- 用法:
24
- python .qoder/scripts/orchestration/wlkj.py kg search 保险 --platform web
25
- python .qoder/scripts/orchestration/wlkj.py task list
26
- python .qoder/scripts/orchestration/wlkj.py doctor --fix
27
- python .qoder/scripts/orchestration/wlkj.py search 考勤
28
- python .qoder/scripts/orchestration/wlkj.py status
29
-
30
- 分组 (逻辑导航, 非物理目录):
31
- kg/* 知识图谱 (kg.py 的子命令直接透传)
32
- task 任务系统
33
- search 代码搜索
34
- doctor 环境体检
35
- status 项目状态
36
- sync 团队同步
37
- ...
38
-
39
- 设计:
40
- - 透明转发: 不改变任何子脚本的行为, 只是把 argv 转过去
41
- - 单一真源: 脚本物理路径只在 DISPATCH 出现一次, 载体层不写死路径
42
- - 零维护: 加新命令只需在 DISPATCH 表加一行
43
- """
44
-
45
- import os
46
- import subprocess
47
- import sys
48
-
49
- # 命令 → 脚本 映射 (加新命令只需在此加一行)
50
- # v3.0: 脚本已分子目录, 路径更新为 子包/脚本
51
- DISPATCH = {
52
- # ── 知识图谱 ──
53
- 'kg': 'domain/kg/kg.py',
54
- 'search': 'domain/kg/search/search_index.py',
55
- 'context': 'domain/kg/search/context_pack.py',
56
- 'prefetch': 'domain/kg/search/prefetch.py',
57
- 'kg-build': 'domain/kg/build/kg_build.py',
58
- 'kg-incremental': 'domain/kg/build/kg_incremental.py',
59
- 'kg-semantic': 'domain/kg/graph/kg_semantic.py',
60
- 'semantic': 'domain/kg/graph/kg_semantic.py',
61
- # MCP 名别名(AI 常把 MCP 工具名当 wlkj.py 命令调 未知命令。归一化后两边名都认)
62
- 'search_code': 'domain/kg/search/search_index.py',
63
- 'search_api': 'domain/kg/search/search_index.py',
64
- 'search_prds': 'domain/kg/search/search_index.py',
65
- 'search_field': 'domain/kg/search/search_index.py',
66
- 'search_style': 'domain/kg/search/search_index.py',
67
- 'rag_search': 'domain/kg/graph/kg_semantic.py',
68
- 'ask_corpus': 'domain/kg/graph/kg_semantic.py',
69
- 'context_pack': 'domain/kg/search/context_pack.py',
70
- 'context_360': 'domain/kg/search/context_pack.py',
71
- 'get_impact': 'domain/kg/search/search_index.py',
72
- 'style': 'domain/kg/build/build_style_index.py',
73
- # ── 任务 / 同步 ──
74
- 'task': 'domain/task/task.py',
75
- 'sync': 'domain/task/team_sync.py',
76
- 'team-sync': 'domain/task/team_sync.py',
77
- 'git-sync': 'domain/task/git_sync.py',
78
- 'zentao-sync': 'domain/task/zentao_sync.py',
79
- # ── 需求 / PRD ──
80
- 'req': 'domain/requirement/req.py',
81
- 'archive-prd': 'domain/requirement/archive_prd.py',
82
- # ── 回流平台 (引擎产出 → 平台 AI回流Tab) ──
83
- # 用法: wlkj.py return prd <路径> <标题> | return prototype <路径> <功能名> [--platform web]
84
- 'return': 'domain/integration/return_to_platform.py',
85
- 'spec-upload': 'domain/integration/spec_upload.py',
86
- # ── 设计 ──
87
- 'fill-prototype': 'domain/design/fill_prototype.py',
88
- 'design-doc': 'domain/design/gen_design_doc.py',
89
- # ── 评估 / 学习 (飞轮) ──
90
- 'eval': 'validation/metrics/eval_prd.py',
91
- 'eva': 'validation/metrics/eval_prd.py',
92
- 'usability': 'validation/metrics/usability_score.py',
93
- 'learn': 'domain/learning/learn.py',
94
- 'learn-aggregate': 'domain/kg/build/learn_aggregate.py',
95
- # ── 报告 / 状态 ──
96
- 'status': 'domain/report/status.py',
97
- 'status-snapshot': 'domain/report/status_snapshot.py',
98
- 'report': 'domain/report/report.py',
99
- 'report-snapshot': 'domain/report/report_snapshot.py',
100
- 'session': 'domain/report/add_session.py',
101
- 'add-session': 'domain/report/add_session.py',
102
- 'role': 'domain/report/role.py',
103
- 'export': 'domain/report/export.py',
104
- # ── 测试 ──
105
- 'test': 'validation/test/autotest.py',
106
- 'autotest': 'validation/test/autotest.py',
107
- 'autotest-batch': 'validation/test/autotest_batch.py',
108
- 'benchmark': 'validation/test/benchmark.py',
109
- # ── 环境 / 初始化 ──
110
- 'switch-project': 'domain/kg/switch_project.py',
111
- 'doctor': 'deployment/setup/init_doctor.py',
112
- 'init': 'deployment/setup/setup.py',
113
- 'install-qw': 'deployment/setup/install_qoderwork.py',
114
- 'setup-lanhu': 'deployment/setup/setup_lanhu.py',
115
- }
116
-
117
-
118
-
119
-
120
- def _find_script_by_name(scripts_root, name):
121
- """未知命令时, 当作脚本名在 scripts/ 下递归查找。
122
- 支撑 'wlkj.py <脚本名>' 万能跑 (cli.js 的 run 命令底层依赖)
123
- 返回绝对路径或 None。"""
124
- import glob
125
- if not name.endswith('.py'):
126
- name = name + '.py'
127
- # 递归找 scripts/**/name
128
- pattern = os.path.join(scripts_root, '**', name)
129
- hits = glob.glob(pattern, recursive=True)
130
- return hits[0] if hits else None
131
-
132
- def _usage():
133
- lines = [
134
- 'wlkj.py — 工作流顶层调度器',
135
- '',
136
- '用法: python .qoder/scripts/orchestration/wlkj.py <命令> [参数...]',
137
- '',
138
- '命令分组 (转发到对应脚本):',
139
- ' 知识图谱: kg <子命令> (kg.py, 13+ 能力)',
140
- ' search <词> (search_index.py)',
141
- ' context <词> (context_pack.py)',
142
- ' kg-build (全量构建图谱)',
143
- ' kg-incremental (增量构建, 定时任务用)',
144
- ' 任务: task <子命令> (task.py, create/list/start/finish)',
145
- ' 同步: sync pull|push (team_sync.py)',
146
- ' 需求: req <子命令> (req.py, 需求生命周期)',
147
- ' archive-prd (PRD 归档)',
148
- ' 回流平台: return prd|prototype <文件> <标题> [--platform web] (PRD/原型回流到平台 AI回流Tab)',
149
- ' 设计: fill-prototype <tpl> (真实数据预填原型)',
150
- ' design-doc (生成 DESIGN.md)',
151
- ' 评估/学习: eval <prd.md> (eval_prd.py, EVA 评分)',
152
- ' usability [--days N] (usability_score.py, 工作流可用性: 采纳+流程)',
153
- ' learn record/status (个人埋点)',
154
- ' learn-aggregate (团队聚合 → kg.duckdb)',
155
- ' 状态/报告: status (status.py, 健康度)',
156
- ' report daily|weekly (report.py)',
157
- ' export <格式> (export.py)',
158
- ' 测试: test <子命令> (autotest.py)',
159
- ' autotest-batch <f> (批量串测)',
160
- ' benchmark (性能基线)',
161
- ' 体检: doctor [--fix] (init_doctor.py)',
162
- '',
163
- '示例:',
164
- ' wlkj.py kg search 保险 --platform web',
165
- ' wlkj.py task create "登录优化"',
166
- ' wlkj.py doctor --fix',
167
- ' wlkj.py learn record prd_accepted \'{"req_id":"REQ-001","score":87}\'',
168
- '',
169
- '注: 所有 Qoder 载体 (命令/skills/rules) 统一走本入口; 脚本物理位置见 DISPATCH 表。',
170
- ]
171
- return '\n'.join(lines)
172
-
173
-
174
- def _ctx_cache_cmd(rest, scripts_root):
175
- """wlkj.py ctx-cache <REQ-ID> <query> [--platform web|app] — 按 REQ 缓存 context_pack 结果(T1.3)。
176
- HIT 回放缓存(省一次 KG/MCP 往返);MISS context_pack 捕获 stdout 写缓存再回放。
177
- wlkj.py ctx-cache <REQ-ID> --clear — 清该 REQ 缓存(PRD/spec 改动后失效)。
178
- 任何异常 fail-open 降级直拉(缓存坏了不影响主流程)。
179
- """
180
- do_clear = "--clear" in rest
181
- rest = [a for a in rest if a != "--clear"]
182
-
183
- req_id = None
184
- query_parts, passthrough = [], []
185
- i = 0
186
- while i < len(rest):
187
- a = rest[i]
188
- if a == "--platform" and i + 1 < len(rest):
189
- passthrough.extend([a, rest[i + 1]]); i += 2; continue
190
- if a.startswith("-"):
191
- passthrough.append(a); i += 1; continue
192
- if req_id is None:
193
- req_id = a; i += 1; continue
194
- query_parts.append(a); i += 1
195
- query = " ".join(query_parts).strip()
196
- if not req_id or (not query and not do_clear):
197
- sys.stderr.write("用法: wlkj.py ctx-cache <REQ-ID> <query> [--platform web|app] | ctx-cache <REQ-ID> --clear\n")
198
- return 1
199
-
200
- cc = None
201
- try:
202
- if scripts_root not in sys.path:
203
- sys.path.insert(0, scripts_root)
204
- from foundation.io import context_cache as _cc # noqa
205
- cc = _cc
206
- except Exception as e:
207
- sys.stderr.write("[cache] 模块导入失败, 降级直拉: %s\n" % str(e)[:80])
208
-
209
- # --clear: 清该 REQ 缓存
210
- if do_clear:
211
- if cc is None:
212
- sys.stderr.write("[cache] 模块不可用, 无法 clear\n"); return 1
213
- cc.invalidate(req_id)
214
- sys.stderr.write("[cache] CLEARED req=%s\n" % req_id)
215
- return 0
216
-
217
- if cc is not None:
218
- try:
219
- cached = cc.get(req_id, query)
220
- if cached is not None:
221
- sys.stdout.write(cached if cached.endswith("\n") else cached + "\n")
222
- sys.stderr.write("[cache] HIT req=%s q=%s (省一次 context_pack 往返)\n" % (req_id, query[:30]))
223
- return 0
224
- except Exception as e:
225
- sys.stderr.write("[cache] get 失败, 降级直拉: %s\n" % str(e)[:80])
226
-
227
- # MISS / 降级:跑 context_pack,捕获 stdout,写缓存,回放
228
- script_path = os.path.join(scripts_root, DISPATCH["context"])
229
- r = subprocess.run([sys.executable, script_path, query] + passthrough, capture_output=True)
230
- sys.stderr.write(r.stderr.decode(errors="replace"))
231
- out = r.stdout.decode(errors="replace")
232
- sys.stdout.write(out)
233
- if out.strip() and cc is not None:
234
- try:
235
- cc.put(req_id, query, out)
236
- sys.stderr.write("[cache] MISS+PUT req=%s q=%s\n" % (req_id, query[:30]))
237
- except Exception as e:
238
- sys.stderr.write("[cache] put 失败(不影响本次输出): %s\n" % str(e)[:80])
239
- return r.returncode
240
-
241
-
242
- def _bf_score_cmd(rest, scripts_root):
243
- """wlkj.py bf-score <prd|proto|code|search> <产物文件> [--feature 主题] — 业务保真打分(T1/FW12)。
244
- 转发 bf_score.py 对真命令产出文件打 BF 分(PRD→BF1/2, 原型→BF3/4, code/search→BF5/6)。
245
- bf_score.py 跑在云容器(接真 db_tables/design_system/真PRD);本地无业务数据时降级提示。"""
246
- script = os.path.join(scripts_root, "validation", "eval", "bf_score.py")
247
- if not os.path.isfile(script):
248
- sys.stderr.write("[bf-score] bf_score.py 不在,跳过\n")
249
- return 1
250
- r = subprocess.run([sys.executable, script] + rest)
251
- return r.returncode
252
-
253
-
254
- # 带 custom 逻辑的命令(在 DISPATCH 透明转发前拦截)
255
- SPECIAL = {
256
- 'ctx-cache': _ctx_cache_cmd,
257
- 'context-cache': _ctx_cache_cmd,
258
- 'bf-score': _bf_score_cmd,
259
- 'bfscore': _bf_score_cmd,
260
- }
261
-
262
-
263
- def main():
264
- argv = sys.argv[1:]
265
- if not argv or argv[0] in ('-h', '--help', 'help'):
266
- print(_usage())
267
- return 0
268
-
269
- cmd = argv[0]
270
- rest = argv[1:]
271
-
272
- # scripts/ 根 = __file__ 的上两级 (orchestration/ -> scripts/)
273
- scripts_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
274
-
275
- # T1.3 带 custom 逻辑的命令(如 ctx-cache 缓存)在透明转发前拦截
276
- if cmd in SPECIAL:
277
- return SPECIAL[cmd](rest, scripts_root)
278
-
279
- script = DISPATCH.get(cmd)
280
- if not script:
281
- # Fallback: 当作脚本名在 scripts/ 下递归找 (支撑 'wlkj.py run <脚本>')
282
- # 这样 cli.js 的 'run' 和直接 'wlkj.py xxx.py' 都能走单一入口, 不需另维护路径表
283
- hit = _find_script_by_name(scripts_root, cmd)
284
- if hit:
285
- script_path = hit
286
- r = subprocess.run([sys.executable, script_path] + rest)
287
- return r.returncode
288
- sys.stderr.write('未知命令: %s\n' % cmd)
289
- sys.stderr.write('可用命令: %s\n' % ', '.join(sorted(DISPATCH.keys())))
290
- sys.stderr.write('提示: 也可用 wlkj.py <脚本名.py> 递归查找脚本\n')
291
- return 1
292
-
293
- # scripts/ 根 = __file__ 的上两级 (orchestration/ → scripts/)
294
- scripts_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
295
- script_path = os.path.join(scripts_root, script)
296
- if not os.path.isfile(script_path):
297
- sys.stderr.write('脚本不存在: %s\n' % script_path)
298
- return 1
299
-
300
- # 透明转发: 用当前 python 跑目标脚本, 透传所有参数和 exit code
301
- r = subprocess.run([sys.executable, script_path] + rest)
302
- return r.returncode
303
-
304
-
305
- if __name__ == '__main__':
306
- sys.exit(main())
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ wlkj.py - 工作流顶层调度器 (Facade 统一入口)
5
+
6
+ 角色: 所有 Qoder 载体 (commands/skills/rules 里写的脚本调用) 统一走本入口,
7
+ 由 DISPATCH 表路由到 scripts/ 下分层子目录的真实脚本。这样:
8
+ - 载体文件只认一个路径 (orchestration/wlkj.py); scripts/ 重组目录时
9
+ 只需改 DISPATCH 一处, 载体文件不受影响 (根治"目录一重组就断链")
10
+ - 脚本内部互调 (Python 进程间) 仍直接用分层路径, 不绕本入口 (避免 subprocess 嵌套)
11
+
12
+ 用法:
13
+ python .qoder/scripts/orchestration/wlkj.py kg search 保险 --platform web
14
+ python .qoder/scripts/orchestration/wlkj.py task list
15
+ python .qoder/scripts/orchestration/wlkj.py doctor --fix
16
+ python .qoder/scripts/orchestration/wlkj.py search 考勤
17
+ python .qoder/scripts/orchestration/wlkj.py status
18
+
19
+ 分组 (逻辑导航, 非物理目录):
20
+ kg/* 知识图谱 (kg.py 的子命令直接透传)
21
+ task 任务系统
22
+ search 代码搜索
23
+ doctor 环境体检
24
+ status 项目状态
25
+ sync 团队同步
26
+ ...
27
+
28
+ 设计:
29
+ - 透明转发: 不改变任何子脚本的行为, 只是把 argv 转过去
30
+ - 单一真源: 脚本物理路径只在 DISPATCH 出现一次, 载体层不写死路径
31
+ - 零维护: 加新命令只需在 DISPATCH 表加一行
32
+ """
33
+
34
+ import os
35
+ import subprocess
36
+ import sys
37
+
38
+ # 命令 → 脚本 映射 (加新命令只需在此加一行)
39
+ # v3.0: 脚本已分子目录, 路径更新为 子包/脚本
40
+ DISPATCH = {
41
+ # ── 知识图谱 ──
42
+ 'kg': 'domain/kg/kg.py',
43
+ 'search': 'domain/kg/search/search_index.py',
44
+ 'context': 'domain/kg/search/context_pack.py',
45
+ 'prefetch': 'domain/kg/search/prefetch.py',
46
+ 'kg-build': 'domain/kg/build/kg_build.py',
47
+ 'kg-incremental': 'domain/kg/build/kg_incremental.py',
48
+ 'kg-semantic': 'domain/kg/graph/kg_semantic.py',
49
+ 'semantic': 'domain/kg/graph/kg_semantic.py',
50
+ 'style': 'domain/kg/build/build_style_index.py',
51
+ # ── 任务 / 同步 ──
52
+ 'task': 'domain/task/task.py',
53
+ 'sync': 'domain/task/team_sync.py',
54
+ 'team-sync': 'domain/task/team_sync.py',
55
+ 'git-sync': 'domain/task/git_sync.py',
56
+ 'zentao-sync': 'domain/task/zentao_sync.py',
57
+ # ── 需求 / PRD ──
58
+ 'req': 'domain/requirement/req.py',
59
+ 'archive-prd': 'domain/requirement/archive_prd.py',
60
+ # ── 回流平台 (引擎产出 → 平台 AI回流Tab) ──
61
+ # 用法: wlkj.py return prd <路径> <标题> | return prototype <路径> <功能名> [--platform web]
62
+ 'return': 'domain/integration/return_to_platform.py',
63
+ # ── 设计 ──
64
+ 'fill-prototype': 'domain/design/fill_prototype.py',
65
+ 'design-doc': 'domain/design/gen_design_doc.py',
66
+ # ── 评估 / 学习 (飞轮) ──
67
+ 'eval': 'validation/metrics/eval_prd.py',
68
+ 'eva': 'validation/metrics/eval_prd.py',
69
+ 'usability': 'validation/metrics/usability_score.py',
70
+ 'learn': 'domain/learning/learn.py',
71
+ 'learn-aggregate': 'domain/kg/build/learn_aggregate.py',
72
+ # ── 报告 / 状态 ──
73
+ 'status': 'domain/report/status.py',
74
+ 'status-snapshot': 'domain/report/status_snapshot.py',
75
+ 'report': 'domain/report/report.py',
76
+ 'report-snapshot': 'domain/report/report_snapshot.py',
77
+ 'session': 'domain/report/add_session.py',
78
+ 'add-session': 'domain/report/add_session.py',
79
+ 'role': 'domain/report/role.py',
80
+ 'export': 'domain/report/export.py',
81
+ # ── 测试 ──
82
+ 'test': 'validation/test/autotest.py',
83
+ 'autotest': 'validation/test/autotest.py',
84
+ 'autotest-batch': 'validation/test/autotest_batch.py',
85
+ 'benchmark': 'validation/test/benchmark.py',
86
+ # ── 环境 / 初始化 ──
87
+ 'doctor': 'deployment/setup/init_doctor.py',
88
+ 'init': 'deployment/setup/setup.py',
89
+ 'install-qw': 'deployment/setup/install_qoderwork.py',
90
+ 'setup-lanhu': 'deployment/setup/setup_lanhu.py',
91
+ }
92
+
93
+
94
+
95
+
96
+ def _find_script_by_name(scripts_root, name):
97
+ """未知命令时, 当作脚本名在 scripts/ 下递归查找。
98
+ 支撑 'wlkj.py <脚本名>' 万能跑 (cli.js 的 run 命令底层依赖)。
99
+ 返回绝对路径或 None。"""
100
+ import glob
101
+ if not name.endswith('.py'):
102
+ name = name + '.py'
103
+ # 递归找 scripts/**/name
104
+ pattern = os.path.join(scripts_root, '**', name)
105
+ hits = glob.glob(pattern, recursive=True)
106
+ return hits[0] if hits else None
107
+
108
+ def _usage():
109
+ lines = [
110
+ 'wlkj.py — 工作流顶层调度器',
111
+ '',
112
+ '用法: python .qoder/scripts/orchestration/wlkj.py <命令> [参数...]',
113
+ '',
114
+ '命令分组 (转发到对应脚本):',
115
+ ' 知识图谱: kg <子命令> (kg.py, 13+ 能力)',
116
+ ' search <词> (search_index.py)',
117
+ ' context <词> (context_pack.py)',
118
+ ' kg-build (全量构建图谱)',
119
+ ' kg-incremental (增量构建, 定时任务用)',
120
+ ' 任务: task <子命令> (task.py, create/list/start/finish)',
121
+ ' 同步: sync pull|push (team_sync.py)',
122
+ ' 需求: req <子命令> (req.py, 需求生命周期)',
123
+ ' archive-prd (PRD 归档)',
124
+ ' 回流平台: return prd|prototype <文件> <标题> [--platform web] (PRD/原型回流到平台 AI回流Tab)',
125
+ ' 设计: fill-prototype <tpl> (真实数据预填原型)',
126
+ ' design-doc (生成 DESIGN.md)',
127
+ ' 评估/学习: eval <prd.md> (eval_prd.py, EVA 评分)',
128
+ ' usability [--days N] (usability_score.py, 工作流可用性: 采纳+流程)',
129
+ ' learn record/status (个人埋点)',
130
+ ' learn-aggregate (团队聚合 kg.duckdb)',
131
+ ' 状态/报告: status (status.py, 健康度)',
132
+ ' report daily|weekly (report.py)',
133
+ ' export <格式> (export.py)',
134
+ ' 测试: test <子命令> (autotest.py)',
135
+ ' autotest-batch <f> (批量串测)',
136
+ ' benchmark (性能基线)',
137
+ ' 体检: doctor [--fix] (init_doctor.py)',
138
+ '',
139
+ '示例:',
140
+ ' wlkj.py kg search 保险 --platform web',
141
+ ' wlkj.py task create "登录优化"',
142
+ ' wlkj.py doctor --fix',
143
+ ' wlkj.py learn record prd_accepted \'{"req_id":"REQ-001","score":87}\'',
144
+ '',
145
+ '注: 所有 Qoder 载体 (命令/skills/rules) 统一走本入口; 脚本物理位置见 DISPATCH 表。',
146
+ ]
147
+ return '\n'.join(lines)
148
+
149
+
150
+ def main():
151
+ argv = sys.argv[1:]
152
+ if not argv or argv[0] in ('-h', '--help', 'help'):
153
+ print(_usage())
154
+ return 0
155
+
156
+ cmd = argv[0]
157
+ rest = argv[1:]
158
+
159
+ # scripts/ 根 = __file__ 的上两级 (orchestration/ -> scripts/)
160
+ scripts_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
161
+
162
+ script = DISPATCH.get(cmd)
163
+ if not script:
164
+ # Fallback: 当作脚本名在 scripts/ 下递归找 (支撑 'wlkj.py run <脚本>')
165
+ # 这样 cli.js 的 'run' 和直接 'wlkj.py xxx.py' 都能走单一入口, 不需另维护路径表
166
+ hit = _find_script_by_name(scripts_root, cmd)
167
+ if hit:
168
+ script_path = hit
169
+ r = subprocess.run([sys.executable, script_path] + rest)
170
+ return r.returncode
171
+ sys.stderr.write('未知命令: %s\n' % cmd)
172
+ sys.stderr.write('可用命令: %s\n' % ', '.join(sorted(DISPATCH.keys())))
173
+ sys.stderr.write('提示: 也可用 wlkj.py <脚本名.py> 递归查找脚本\n')
174
+ return 1
175
+
176
+ # scripts/ = __file__ 的上两级 (orchestration/ → scripts/)
177
+ scripts_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
178
+ script_path = os.path.join(scripts_root, script)
179
+ if not os.path.isfile(script_path):
180
+ sys.stderr.write('脚本不存在: %s\n' % script_path)
181
+ return 1
182
+
183
+ # 透明转发: 用当前 python 跑目标脚本, 透传所有参数和 exit code
184
+ r = subprocess.run([sys.executable, script_path] + rest)
185
+ return r.returncode
186
+
187
+
188
+ if __name__ == '__main__':
189
+ sys.exit(main())
@@ -76,14 +76,6 @@
76
76
  "command": "python .qoder/hooks/pre-tool-use.py || python3 .qoder/hooks/pre-tool-use.py"
77
77
  }
78
78
  ]
79
- },
80
- {
81
- "matcher": "Bash",
82
- "hooks": [
83
- {
84
- "command": "python .qoder/hooks/pre-tool-use-commit.py || python3 .qoder/hooks/pre-tool-use-commit.py"
85
- }
86
- ]
87
79
  }
88
80
  ],
89
81
  "PostToolUse": [
@@ -18,7 +18,7 @@ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
18
18
 
19
19
  > 这是 `/wl-spec` 命令的 skill 入口。让 QoderWork 的 `/` 列表也能用 `/wl-spec`。
20
20
  > 完整规则见功能型 skill `.qoder/skills/spec-generator/SKILL.md`
21
- > 和命令 `.qoder/commands/optional/wl-spec.md`。
21
+ > 和命令 `.qoder/commands/wl-spec.md`。
22
22
  > **模块契约**(输入/输出/校验):`.qoder/contracts/spec.md`
23
23
 
24
24
  ## ⚙️ 自取上下文(Quest / QoderWork 无 hook 注入,必须自读)
@@ -1,46 +0,0 @@
1
- ---
2
- name: wl-data
3
- description: "数据分析: 自然语言→语义层声明metric→接地SQL→保形门禁→执行渲染。不裸NL2SQL盲猜。"
4
- argument-hint: "[自然语言数据问题] 如:统计各公司资产原值"
5
- auto-approve: true
6
- allowed-tools: [Read, Glob, Grep, Bash, Write, Edit]
7
- ---
8
-
9
- # /wl-data - 数据分析工序站
10
-
11
- User input: $ARGUMENTS
12
-
13
- > **问库不乱猜,声明 metric 优先于裸 SQL。** 对齐 dbt 语义层 + conformal 保形门禁。
14
-
15
- ## 🔧 工具优先级(宿主能力 × 知识层分工)
16
- | 步骤 | 用谁 | 原因 |
17
- |------|------|------|
18
- | 选表选列 | **MCP schema_link** | 确定性概念→真表+列(dbt级,非LLM猜) |
19
- | join 路径 | **MCP semantic/mapper_joins** | Dijkstra 最高置信 join 路径(RAT-SQL对齐) |
20
- | NL→metric | **MCP nl2ontology** | 语义层路由:NL→声明metric→grounded SQL(非裸NL2SQL) |
21
- | 保形门禁 | **MCP gate_check** | conformal coverage≥1-α,低置信拒答 |
22
- | 执行+渲染 | **Qoder AI** | 执行 SQL + 渲染业务答案 |
23
-
24
- ## 🧠 流程(确定性语义层 + 保形)
25
- 1. **schema linking**:`schema_link(concept=<问题>)` → 真表+列+join候选
26
- 2. **语义层路由**:`nl2ontology(question=<问题>)` → 命中声明 metric(如 asset_total_cost)→ grounded SQL;未命中走 LLM NL2SQL(只用 schema_link 选表列,禁全表 schema_text 注入=负贡献)
27
- 3. **保形门禁**:`gate_check(sql, confidence, risk_strategy=v2, alpha=0.1)` → pass/abstain;abstain 诚实拒答(不硬编)
28
- 4. **执行+渲染**:执行 SQL(只读)→ Qoder AI 渲染业务答案(表/图)
29
-
30
- ## 🚨 铁律
31
- 1. **声明优先**:NL 命中声明 metric → 用其 grounded SQL(确定性);未命中才 LLM 生成
32
- 2. **schema_text 禁注入**:全表 schema 注入 prompt 是负贡献(实测 L1 38→63 是禁 schema 后),只用 schema_link 选表列
33
- 3. **保形拒答**:置信度 < 阈值诚实 abstain,不硬编答案(selective 价值:pass 集准 vs abstain 集)
34
- 4. **只读执行**:SQL 只 SELECT,禁 DDL/DML(data/security.py 白名单 + executor READ ONLY)
35
-
36
- ## 📊 对齐
37
- - dbt Semantic Layer(声明 metric)/ MetricFlow(多跳 join)/ conformal prediction(保形 coverage)
38
- - 平台 workflow_sim WL_WL_DATA_GRAPH(schema_link→LINK→ONTO→SQLGEN→GATE→ANSWER)
39
-
40
-
41
- ## 🚨 接地铁律(防幻觉/保真,Qoder AI 必须遵守)
42
-
43
- 1. **溯源**:引用代码符号/表名/接口用**真实原名**(如 `CostApplyController`、`base_asset`),非中文描述——只引 MCP 工具(rag_search/schema_link/context_360/get_impact 等)召回的真实符号,提升可溯源性
44
- 2. **禁编**:不编造未在召回里出现的类名/表名/字段/接口;召回不足时标"待确认(知识层未召回)",**诚实优于编造**
45
- 3. **接地(数据表)**:涉及数据表/字段时,先调 MCP `schema_link`/`query_schema` 取真表真列;未召回真表禁编 t_xxx 表名+字段充数
46
- 4. **完整**:产物详尽展开(每节实质内容,不一行带过)
@@ -1,47 +0,0 @@
1
- ---
2
- name: wl-fix
3
- description: "修bug: 症状→根因(不治标)→爆炸半径(防回归)→最小侵入修复。"
4
- argument-hint: "[bug症状/报错] 如:保险导出报空指针"
5
- auto-approve: true
6
- allowed-tools: [Read, Glob, Grep, Bash, Write, Edit]
7
- ---
8
-
9
- # /wl-fix - bug 修复工序站
10
-
11
- User input: $ARGUMENTS
12
-
13
- > **治根因不治标,先量爆炸半径防回归。**
14
-
15
- ## 🔧 工具优先级
16
- | 步骤 | 用谁 | 原因 |
17
- |------|------|------|
18
- | 定位缺陷站点 | **MCP search_code** | 精确符号定位(疑似缺陷文件/符号) |
19
- | 相似bug模式 | **MCP rag_search** | 历史相似缺陷/修复(kind=code) |
20
- | 变更史 | **MCP code_history** | regression 根因(该文件历史变更) |
21
- | 爆炸半径 | **MCP get_impact** | 改一处影响谁(upstream/downstream) |
22
- | 修复方案 | **Qoder AI** | 综合→最小侵入修复 |
23
-
24
- ## 🧠 流程
25
- 1. **定位**:`search_code(query=<症状>, focus=symbol)` → 疑似缺陷符号(带 repo 前缀,避 CTRL 双格式坑)
26
- 2. **相似模式**:`rag_search(query=<症状>, kind=code)` → 相似 bug/历史修复
27
- 3. **根因假设**:derive → suspected_location + root_cause + evidence + confidence(<0.5 回扩词重搜)
28
- 4. **爆炸半径**:`get_impact(entity=<suspected_location>, depth=2)` → 影响面(防回归)
29
- 5. **修复方案**:Qoder AI 综合 → 最小侵入修复 + 回归防护
30
-
31
- ## 🚨 铁律
32
- 1. **根因非症状**:区分表面报错点 vs 真根因,不治标
33
- 2. **爆炸半径**:改前必 get_impact,影响大→人工确认
34
- 3. **最小侵入**:修复尽量小,附带回归测试建议
35
- 4. **置信度诚实**:confidence<0.5 标"根因不确定,建议人工核实"
36
-
37
- ## 📊 对齐
38
- - 平台 workflow_sim WL_WL_FIX_GRAPH(search_code→rag→derive根因→get_impact→synth修复)
39
- - _UNDERUTILIZED_PRE 补 code_history 节点(regression 根因)
40
-
41
-
42
- ## 🚨 接地铁律(防幻觉/保真,Qoder AI 必须遵守)
43
-
44
- 1. **溯源**:引用代码符号/表名/接口用**真实原名**(如 `CostApplyController`、`base_asset`),非中文描述——只引 MCP 工具(rag_search/schema_link/context_360/get_impact 等)召回的真实符号,提升可溯源性
45
- 2. **禁编**:不编造未在召回里出现的类名/表名/字段/接口;召回不足时标"待确认(知识层未召回)",**诚实优于编造**
46
- 3. **接地(数据表)**:涉及数据表/字段时,先调 MCP `schema_link`/`query_schema` 取真表真列;未召回真表禁编 t_xxx 表名+字段充数
47
- 4. **完整**:产物详尽展开(每节实质内容,不一行带过)