@hupan56/wlkj 3.2.0 → 3.3.1
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 +117 -0
- package/package.json +2 -2
- package/templates/.qoder/.runtime/hook-errors.log +4 -0
- package/templates/qoder/commands/optional/wl-insight.md +276 -276
- package/templates/qoder/commands/optional/wl-report.md +1 -1
- package/templates/qoder/commands/optional/wl-spec.md +13 -1
- package/templates/qoder/commands/optional/wl-status.md +14 -1
- package/templates/qoder/commands/wl-code.md +111 -4
- package/templates/qoder/commands/wl-commit.md +12 -1
- package/templates/qoder/commands/wl-design.md +69 -5
- package/templates/qoder/commands/wl-init.md +129 -102
- package/templates/qoder/commands/wl-prd.md +162 -6
- package/templates/qoder/commands/wl-search.md +106 -20
- package/templates/qoder/commands/wl-task.md +617 -613
- package/templates/qoder/commands/wl-test.md +20 -1
- package/templates/qoder/contracts/spec.md +4 -0
- package/templates/qoder/hooks/post-tool-use.py +71 -0
- package/templates/qoder/hooks/pre-tool-use.py +136 -0
- package/templates/qoder/hooks/session-start.py +365 -397
- package/templates/qoder/scripts/capability/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/__pycache__/present_html.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/__pycache__/registry.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/__pycache__/registry_mcp.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__init__.py +1 -1
- package/templates/qoder/scripts/capability/adapters/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__pycache__/cli.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__pycache__/mcp.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__pycache__/qw.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/mcp.py +76 -100
- package/templates/qoder/scripts/capability/adapters/qw.py +295 -295
- package/templates/qoder/scripts/capability/caps/__init__.py +5 -5
- package/templates/qoder/scripts/capability/caps/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/context.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/cron.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/identity.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/memory.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/notify.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/present.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/repo.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/sandbox.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/memory.py +1 -1
- package/templates/qoder/scripts/capability/caps/notify.py +64 -0
- package/templates/qoder/scripts/capability/caps/sandbox.py +38 -0
- package/templates/qoder/scripts/capability/present_html.py +68 -0
- package/templates/qoder/scripts/capability/registry.py +27 -25
- package/templates/qoder/scripts/capability/registry_mcp.py +67 -5
- package/templates/qoder/scripts/capability/smoke_test_report.json +34 -20
- package/templates/qoder/scripts/deployment/setup/carriers.py +3 -1
- package/templates/qoder/scripts/deployment/setup/init_doctor.py +10 -3
- package/templates/qoder/scripts/domain/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/integration/__init__.py +0 -0
- package/templates/qoder/scripts/domain/integration/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/integration/__pycache__/return_to_platform.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/integration/return_to_platform.py +395 -0
- package/templates/qoder/scripts/domain/integration/spec_upload.py +208 -0
- package/templates/qoder/scripts/domain/kg/build/kg_build.py +27 -3
- package/templates/qoder/scripts/domain/kg/extract/asset/__init__.py +10 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/asset_tree.py +57 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/discussion_importer.py +62 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/prd_importer.py +146 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/prototype_importer.py +64 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/returns_importer.py +52 -0
- package/templates/qoder/scripts/domain/kg/extract/build_goal3.py +104 -0
- package/templates/qoder/scripts/domain/kg/extract/build_goal4.py +55 -0
- package/templates/qoder/scripts/domain/kg/extract/build_goal5.py +95 -0
- package/templates/qoder/scripts/domain/kg/extract/db/__init__.py +8 -0
- package/templates/qoder/scripts/domain/kg/extract/db/data_profile.py +22 -0
- package/templates/qoder/scripts/domain/kg/extract/db/fk_extractor.py +55 -0
- package/templates/qoder/scripts/domain/kg/extract/db/schema_extractor.py +90 -0
- package/templates/qoder/scripts/domain/kg/extract/extract.py +84 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/__init__.py +9 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/community_summarizer.py +206 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/embed_builder.py +132 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/naming_matcher.py +80 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/promote.py +59 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/recompute.py +93 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/weak_link.py +421 -0
- package/templates/qoder/scripts/domain/kg/extract/java/__init__.py +15 -0
- package/templates/qoder/scripts/domain/kg/extract/java/_parser.py +271 -0
- package/templates/qoder/scripts/domain/kg/extract/java/all.py +145 -0
- package/templates/qoder/scripts/domain/kg/extract/java/build_java_to_pg.py +102 -0
- package/templates/qoder/scripts/domain/kg/extract/java/call_chain.py +49 -0
- package/templates/qoder/scripts/domain/kg/extract/java/class_extractor.py +141 -0
- package/templates/qoder/scripts/domain/kg/extract/java/domain_extractor.py +148 -0
- package/templates/qoder/scripts/domain/kg/extract/java/dubbo_extractor.py +33 -0
- package/templates/qoder/scripts/domain/kg/extract/java/endpoint_extractor.py +36 -0
- package/templates/qoder/scripts/domain/kg/extract/java/javadoc_extractor.py +110 -0
- package/templates/qoder/scripts/domain/kg/extract/java/llm_cn_filler.py +150 -0
- package/templates/qoder/scripts/domain/kg/extract/java/member_extractor.py +157 -0
- package/templates/qoder/scripts/domain/kg/extract/java/mybatisplus_extractor.py +34 -0
- package/templates/qoder/scripts/domain/kg/extract/java/pg_upsert.py +165 -0
- package/templates/qoder/scripts/domain/kg/extract/java/satoken_extractor.py +30 -0
- package/templates/qoder/scripts/domain/kg/extract/java/spring_extractor.py +39 -0
- package/templates/qoder/scripts/domain/kg/extract/java/validation_extractor.py +33 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/__init__.py +9 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/all.py +79 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/mapper_parser.py +99 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/relation_builder.py +69 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/sql_extractor.py +78 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/__init__.py +8 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/prd_chunk_embed.py +105 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/prd_llm_extract.py +153 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/req_anchor.py +120 -0
- package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +4 -2
- package/templates/qoder/scripts/domain/kg/kg.py +42 -5
- package/templates/qoder/scripts/domain/kg/search/_remote.py +187 -0
- package/templates/qoder/scripts/domain/kg/search/context_pack.py +32 -2
- package/templates/qoder/scripts/domain/kg/search/search_index.py +74 -20
- package/templates/qoder/scripts/domain/kg/switch_project.py +158 -0
- package/templates/qoder/scripts/domain/kg/sync_repowiki.py +109 -0
- package/templates/qoder/scripts/domain/task/__pycache__/wlkj_panel.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/task/{zentao_panel.py → wlkj_panel.py} +315 -53
- package/templates/qoder/scripts/engine/poller.py +219 -0
- package/templates/qoder/scripts/foundation/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/core/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/core/__pycache__/paths.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/integrations/active_task.py +2 -1
- package/templates/qoder/scripts/orchestration/wlkj.py +4 -0
- package/templates/qoder/scripts/protocol/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +1 -1
- package/templates/qoder/scripts/protocol/transports/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/base.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/cli.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/http.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/stdio.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/http.py +7 -1
- package/templates/qoder/scripts/validation/metrics/__pycache__/present_board.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/validation/metrics/present_board.py +180 -0
- package/templates/qoder/settings.json +10 -0
- package/templates/root/AGENTS.md +9 -10
|
@@ -13,6 +13,31 @@ User input: $ARGUMENTS
|
|
|
13
13
|
> **写需求 / 评审需求,一个命令搞定。**
|
|
14
14
|
> 模块契约:`.qoder/contracts/prd.md`
|
|
15
15
|
|
|
16
|
+
## 🔧 工具优先级(宿主能力 × 知识层分工)
|
|
17
|
+
| 步骤 | 用谁 | 原因 |
|
|
18
|
+
|------|------|------|
|
|
19
|
+
| 搜文件内容 | **Qoder Grep/Read** | 精确搜代码,原生更快 |
|
|
20
|
+
| 取业务上下文 | **MCP context_pack** | 语义聚合8段(代码+API+字段+Wiki+PRD) |
|
|
21
|
+
| 取团队记忆 | **MCP get_learnings** | 引擎积累的业务规则 |
|
|
22
|
+
| 查真表结构 | **MCP query_schema** | 数据库真实列名 |
|
|
23
|
+
| 生成 PRD 正文 | **Qoder AI** | 宿主 AI 比我们调 qwen-plus 更强 |
|
|
24
|
+
| 写文件 | **Qoder Write** | 原生文件操作 |
|
|
25
|
+
|
|
26
|
+
## 🧠 Planning Agent(完整模式强制前置 · 非建议)
|
|
27
|
+
|
|
28
|
+
> ⚠️ **完整模式必须先 Planning 再生成**(不再是"建议")。
|
|
29
|
+
> Planning 拆出 13 章计划 → 逐章生成有骨架不漏章;跳过 Planning 直接写易漏章节(真实反面:海外考勤 PRD 只写 1 章就交差)。
|
|
30
|
+
|
|
31
|
+
### 强制流程(完整模式取完上下文后第一步)
|
|
32
|
+
1. 取完上下文(context_pack)后,**先出 Planning**:把 13 章拆成计划(每章要点 + 引用哪条 MCP 知识命中)
|
|
33
|
+
2. Planning 通过 → 逐章生成,每章参考 MCP 知识上下文
|
|
34
|
+
3. 全部完成 → 调 MCP submit_return 回流平台
|
|
35
|
+
|
|
36
|
+
### 降级(宿主无 Planning Agent 模式)
|
|
37
|
+
手动按 13 章模板(`templates/prd-full-template.md`)逐章列要点,列完再写正文——等价于手动 Planning,**不跳过拆章这一步**。
|
|
38
|
+
|
|
39
|
+
> 快速模式(6 章)不强制 Planning——章节少,直接 prd-quick agent 3 步出。
|
|
40
|
+
|
|
16
41
|
## 🚦 路由(看第一个词或描述特征)
|
|
17
42
|
|
|
18
43
|
### 🔴 命令优先铁律(最重要,先读)
|
|
@@ -54,6 +79,8 @@ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
|
|
|
54
79
|
|
|
55
80
|
**新模块/新业务/新流程用这个。** 支持衔接 insight:`参考:<报告路径>`
|
|
56
81
|
|
|
82
|
+
> **宿主 sub-agent 激活**:QoderWork 支持 sub-agent 时,完整模式可 dispatch 到 **`prd-reference`** agent(`.qoder/agents/prd-reference.md`)——它承担"现状分析"(定位文件 + 总结现状怎么做/已知限制)+ 参考现有数据生成 PRD+原型,10 点质检内置。dispatch prompt 传 platform + 需求 + 开发者名。生成前先过上方 🧠 Planning 强制前置。不支持 sub-agent 则按下文手动取上下文流程。
|
|
83
|
+
|
|
57
84
|
**铁律:平台必问。** 先问:
|
|
58
85
|
```
|
|
59
86
|
这个需求是针对哪个平台?
|
|
@@ -63,14 +90,62 @@ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
|
|
|
63
90
|
请选择 (1/2/3):
|
|
64
91
|
```
|
|
65
92
|
|
|
66
|
-
### 取上下文(
|
|
93
|
+
### 取上下文(context_pack Fast Path 为主 + rag_search/context_360 兜底 — 语义召回最全,接地写 PRD)
|
|
94
|
+
|
|
95
|
+
**写 PRD 前必做的知识预取:Fast Path 用 context_pack 一次取全(代码+API+字段+风格+相关PRD),替代 rag_search+context_360 两次往返;再叠 ask_corpus(业务流程)+ get_learnings(之前学到的)+ query_schema(真库表结构)。不要只靠 search_code 关键词。**
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from capability import resolve
|
|
99
|
+
cap = resolve()
|
|
100
|
+
# ⓪ req_trace 查同需求历史画像(防重复造轮子):有 REQ-ID 时先查这个需求已有哪些 PRD/代码/表
|
|
101
|
+
if <有 REQ-ID>:
|
|
102
|
+
cap.mcp.call("req_trace", {"req_id": "<REQ-ID>"}) # 返回 PRD+代码+表+测试,避免重复写已有功能
|
|
103
|
+
# ⓪b find_similar_prds 找相似历史需求(防重复造轮子,跨项目):无 REQ-ID 也能查
|
|
104
|
+
# 输入需求描述 → 语义最相似的 top-K 历史需求(commit-mined),看是否已有人做过类似功能
|
|
105
|
+
# 返回 sim_label(高度相似/相关/弱相关)+借鉴的代码实体名;高度相似的先看再决定是否重写
|
|
106
|
+
similar = cap.mcp.call("find_similar_prds", {"query": "<需求描述>", "top_k": 5})
|
|
107
|
+
# 若两条需求高度相似,可 diff_requirements 对比它们 touched_entities 差异(共有/独有代码+Jaccard)
|
|
108
|
+
# ① context_pack Fast Path(1 次往返取全上下文:代码+API+字段+风格+相关PRD)
|
|
109
|
+
# 等价于 rag_search + context_360 合并,轮次减半(原 5 次 → 3 次)
|
|
110
|
+
pack = cap.mcp.call("context_pack", {"query": "<业务词或需求描述>", "project_id": "<项目UUID>"})
|
|
111
|
+
# ①b 召回不够(缺某类/命中为空)时单独补 rag_search 一次(语义召回兜底,fallback)
|
|
112
|
+
if not pack.get("items"):
|
|
113
|
+
rag = cap.mcp.call("rag_search", {"query": "<业务词或需求描述>", "top_k": 10})
|
|
114
|
+
# ①c 仍需某核心业务对象的完整关联(代码+页面+字段+API)时,补 context_360(fallback)
|
|
115
|
+
if <需要某符号的全上下文>:
|
|
116
|
+
ctx = cap.mcp.call("context_360", {"symbol": "<核心业务对象>"})
|
|
117
|
+
# ② 有"业务流程整体怎么运转"的疑问时,补 ask_corpus 拿 GraphRAG 答案
|
|
118
|
+
flow = cap.mcp.call("ask_corpus", {"q": "<业务词>的业务流程是什么", "top_k": 3})
|
|
119
|
+
# ③ get_learnings 查之前学到的业务规则/偏好(反哺:上次踩的坑这次别犯)
|
|
120
|
+
learnings = cap.mcp.call("get_learnings", {"project_id": "<项目UUID>", "limit": 10})
|
|
121
|
+
# ④ query_schema 查真实数据库表结构(引擎自己的 MySQL MCP,拿到的真表回流平台)
|
|
122
|
+
# 推断涉及哪些表(从 pack 命中里找表名),查真结构
|
|
123
|
+
schema = cap.mcp.call("query_schema", {"table": "<表名>"}) # 引擎 qoder-mysql 工具
|
|
124
|
+
# 查到后把真表结构回流平台(learn 写回,平台数据库知识就有了真实数据)
|
|
125
|
+
if schema and schema.get("columns"):
|
|
126
|
+
cap.mcp.call("learn", {"project_id":"<项目UUID>", "category":"rule",
|
|
127
|
+
"pattern": f"数据库表<表名>结构: {json.dumps(schema.get('columns',[]), ensure_ascii=False)[:500]}",
|
|
128
|
+
"source": "wlkj/wl-prd+mysql"})
|
|
129
|
+
# PRD 里的字段表优先用 query_schema 查到的真实列(最接地),其次用 context_pack 召回的代码字段
|
|
130
|
+
```
|
|
131
|
+
# 写 PRD 时参考 learnings 里的规则/偏好/决策,在相关章节体现
|
|
132
|
+
```
|
|
133
|
+
等价 CLI(脚本兜底):
|
|
67
134
|
```bash
|
|
68
135
|
$PY "$R/.qoder/scripts/orchestration/wlkj.py" context <业务词> --platform <web|app>
|
|
69
136
|
```
|
|
70
137
|
- 第 4 段 = 历史 PRD(防重复)
|
|
71
138
|
- 第 5 段 = 相关 API
|
|
72
139
|
- 第 8 段 = 数据库表结构+真实字段
|
|
73
|
-
- 涉及枚举字段时额外调 `cap.mcp.call("query_distinct`
|
|
140
|
+
- 涉及枚举字段时额外调 `cap.mcp.call("query_distinct")`
|
|
141
|
+
|
|
142
|
+
### 🎯 接地铁律(写 PRD 必须遵守)
|
|
143
|
+
|
|
144
|
+
**用 rag_search 召回的知识写 PRD,每条功能/字段都要有 rag_search 命中的来源,不编造。**
|
|
145
|
+
- PRD 里写的每个字段名 → 必须在 rag_search/context_360 结果里能找到(或来自 query_schema 真实表结构)
|
|
146
|
+
- PRD 里写的每个 API → 必须在召回结果里有对应端点
|
|
147
|
+
- 召回不到的字段/API → 标注"新增(待评估)",不要假装已存在
|
|
148
|
+
- 业务流程描述 → 优先采纳 ask_corpus 的 GraphRAG 回答(有全局视角),再用 rag_search 的事实补充
|
|
74
149
|
|
|
75
150
|
### 产出
|
|
76
151
|
- PRD: `workspace/members/{dev}/drafts/REQ-{YYYY}-{NNN}-{标题}.md`(13 章)
|
|
@@ -102,13 +177,27 @@ $PY "$R/.qoder/scripts/orchestration/wlkj.py" eval <prd.md> [原型.html]
|
|
|
102
177
|
|
|
103
178
|
**加字段/加按钮/改文案/加导出等零星需求专用。** 极速,不走 EVA。
|
|
104
179
|
|
|
180
|
+
> **宿主 sub-agent 激活**:QoderWork 支持 sub-agent 时,dispatch 到 **`prd-quick`** agent(`.qoder/agents/prd-quick.md`)——3 步极速(取上下文→生成 PRD+原型→一句话确认),≤5 轮工具调用,跳过 EVA。dispatch prompt 传 platform + 需求 + 开发者名。不支持则按下文手动流程。
|
|
181
|
+
|
|
105
182
|
**平台必问**(同上)。
|
|
106
183
|
|
|
107
|
-
### 取上下文(
|
|
184
|
+
### 取上下文(RAG 语义预取,禁止串行 search)
|
|
185
|
+
|
|
186
|
+
**优先 rag_search(语义召回最全)+ prefetch,不要只靠逐个 search_code 关键词。**
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from capability import resolve
|
|
190
|
+
cap = resolve()
|
|
191
|
+
# ① rag_search 一次语义召回:代码/字段/API/Wiki 全拿到(按相关度排序)
|
|
192
|
+
rag = cap.mcp.call("rag_search", {"query": "<需求描述>", "top_k": 8})
|
|
193
|
+
```
|
|
194
|
+
等价 CLI:
|
|
108
195
|
```bash
|
|
109
196
|
$PY "$R/.qoder/scripts/orchestration/wlkj.py" prefetch "<需求描述>" --platform <p>
|
|
110
197
|
```
|
|
111
|
-
prefetch 一次返回代码/字段/API/Wiki/历史 PRD。**之后不要逐个 search/find/grep 查词**(会变 6+ 次串行往返,轮次爆炸根因)。不够才补调一次。
|
|
198
|
+
prefetch/rag_search 一次返回代码/字段/API/Wiki/历史 PRD。**之后不要逐个 search/find/grep 查词**(会变 6+ 次串行往返,轮次爆炸根因)。不够才补调一次。
|
|
199
|
+
|
|
200
|
+
**接地铁律(同完整模式)**:6 章里写的每个字段/API 必须在 rag_search 召回结果里有来源,召不到的标"新增(待评估)",不编造。
|
|
112
201
|
|
|
113
202
|
### 产出
|
|
114
203
|
- Mini-PRD: `workspace/members/{dev}/drafts/REQ-{YYYY}-{NNN}-{标题}.md`(6 章)
|
|
@@ -126,12 +215,14 @@ prefetch 一次返回代码/字段/API/Wiki/历史 PRD。**之后不要逐个 se
|
|
|
126
215
|
|
|
127
216
|
### 流程
|
|
128
217
|
1. 不给文件 → 列出最近的 PRD 让用户选
|
|
129
|
-
2. 7 项 checklist
|
|
218
|
+
2. 7 项 checklist 评审(★ 宿主支持 Agent 并行时,派 7 个 subagent 各审一项并发跑,合并 ✓/✗;不支持则串行逐项):
|
|
130
219
|
- 验收标准是否可测
|
|
131
220
|
- 字段是否引用了真实数据库字段
|
|
132
221
|
- 影响范围是否评估
|
|
133
222
|
- 非功能性需求是否覆盖
|
|
134
|
-
-
|
|
223
|
+
- 接口/异常是否与现有系统自洽
|
|
224
|
+
- 是否有重复造轮子(查 req_trace / search_prd)
|
|
225
|
+
- 原型与 PRD 是否一致
|
|
135
226
|
3. 跑 EVA 评分:`$PY "$R/.qoder/scripts/orchestration/wlkj.py" eval <prd.md>`(wlkj.py eval 内部映射 validation/metrics/eval_prd.py)
|
|
136
227
|
4. 输出:总分 + 7 项 ✓/✗ + 改进建议
|
|
137
228
|
|
|
@@ -187,5 +278,70 @@ $PY "$R/.qoder/scripts/orchestration/wlkj.py" req <REQ-ID> 发布 \
|
|
|
187
278
|
- 默认先 dry-run 预览,用户确认后再 `--confirm` 真发
|
|
188
279
|
- 真发后禅道建好需求,PRD 末尾自动回写 `<!-- zentao: story=ID -->` 留痕
|
|
189
280
|
|
|
281
|
+
> **禅道 story ID 回流平台**:建完禅道需求后,把 story ID 通过平台 MCP learn 工具写回:
|
|
282
|
+
> ```python
|
|
283
|
+
> cap.mcp.call("learn", {"project_id":"<项目UUID>","category":"decision",
|
|
284
|
+
> "pattern": f"PRD<{标题}> 已发禅道: story=#{story_id} product={product_id}",
|
|
285
|
+
> "source": "wlkj/wl-prd+zentao"})
|
|
286
|
+
> ```
|
|
287
|
+
> 这样平台知道这个 PRD 对应禅道哪个需求(跨系统关联)。
|
|
288
|
+
|
|
190
289
|
> 用户说"不发" → 不勉强,PRD 留本地,后续可随时 `/wl-req <REQ-ID> 发布`。
|
|
191
290
|
> 直连禅道 HTTP(脚本内部),AI 只触发一次,几乎不耗 token。
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 🔄 回流平台(PRD 写完即执行,别漏)
|
|
295
|
+
|
|
296
|
+
**铁律:PRD 落地后必须回流平台**(否则平台 AI回流 Tab 永远空,知识层↔引擎断裂)。
|
|
297
|
+
回流走平台 MCP 写工具(`create_prd` / `submit_return`),失败不影响主流程。
|
|
298
|
+
|
|
299
|
+
PRD 写完后跑这一条(用前面定的 `$PY` / `$R` 变量):
|
|
300
|
+
```bash
|
|
301
|
+
$PY "$R/.qoder/scripts/orchestration/wlkj.py" return prd <PRD文件路径> "<PRD标题>" --platform <web|app>
|
|
302
|
+
```
|
|
303
|
+
- 内部优先调 `cap.mcp.call("create_prd", {title, content_md})` 写 PRD 表 + 首版本;
|
|
304
|
+
- 失败再 `submit_return` 写 returns 待审核;最后 HTTP 兜底(读 mcp_config.json 的 return_endpoint)。
|
|
305
|
+
- 全程 try/except,回流失败 PRD 仍在本地,主流程不阻塞。
|
|
306
|
+
|
|
307
|
+
> 等价的 MCP 直调写法(脚本不可用时的兜底):
|
|
308
|
+
> `cap.mcp.call("create_prd", {"title": "<标题>", "content_md": "<完整PRD正文>", "status": "planning"})`
|
|
309
|
+
> 或 `cap.mcp.call("submit_return", {"title":"...", "return_type":"prd", "source":"/wl-prd", "content_preview":"...", "content_full":"..."})`
|
|
310
|
+
|
|
311
|
+
回流成功后输出一行:`✅ [回流] via=create_prd/submit_return <message>`。
|
|
312
|
+
|
|
313
|
+
## 🧠 学习沉淀(PRD 写完即执行,反哺下次)
|
|
314
|
+
|
|
315
|
+
**铁律:写 PRD 过程中学到的业务规则/决策/用户偏好,必须调 `learn` 写回平台**(平台 learning_patterns 积累,下次引擎受益——越用越聪明)。
|
|
316
|
+
|
|
317
|
+
写完 PRD 后,把学到的关键认知调 learn 写回:
|
|
318
|
+
```python
|
|
319
|
+
cap.mcp.call("learn", {
|
|
320
|
+
"project_id": "<项目UUID>",
|
|
321
|
+
"category": "rule", # rule=业务规则 / preference=用户偏好 / decision=决策 / pitfall=踩坑
|
|
322
|
+
"pattern": "<学到的内容,如:车辆保养需关联驾驶员和车辆,按里程+时间双触发>",
|
|
323
|
+
"source": "wlkj/wl-prd",
|
|
324
|
+
})
|
|
325
|
+
```
|
|
326
|
+
- 每次至少写 1 条(最关键的业务规则或决策)。
|
|
327
|
+
- 多条可多次调用。
|
|
328
|
+
- 全程 try/except,失败不阻塞主流程。
|
|
329
|
+
|
|
330
|
+
输出:`✅ [学习] 沉淀 N 条认知到平台`。
|
|
331
|
+
|
|
332
|
+
## 📊 工作流轨迹回写(若本次是被平台触发的)
|
|
333
|
+
|
|
334
|
+
如果本次 /wl-prd 是平台 trigger 派来的(有 triggerId),执行完后回填轨迹:
|
|
335
|
+
```python
|
|
336
|
+
# 通过 PATCH /api/projects/{pid}/trigger/workflow/{triggerId} 回填
|
|
337
|
+
# body: {status: "success", output_summary: "生成了<标题>PRD", knowledge_used: [...], mcp_tools_called: [...], duration_sec: N}
|
|
338
|
+
```
|
|
339
|
+
- knowledge_used:rag_search/search 命中的关键实体 id 列表
|
|
340
|
+
- mcp_tools_called:本次调过的 MCP 工具名(rag_search/context_360/create_prd/learn 等)
|
|
341
|
+
- 让平台"引擎活动看板"能看到本次执行全貌(取了什么知识→产出什么→学了什么)
|
|
342
|
+
- try/except 不阻塞。
|
|
343
|
+
|
|
344
|
+
## 下一步
|
|
345
|
+
- PRD 定稿 → `/wl-task create <标题>` 落成任务(带 REQ-ID 衔接)+ 发禅道
|
|
346
|
+
- 开工前 → `/wl-spec` 生成开发 Spec → 确认后 `/wl-code` 实现
|
|
347
|
+
- 完整链:prd → task → spec → code → test → commit → task finish(双通飞轮)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wl-search
|
|
3
3
|
description: "查代码/业务/API/字段/PRD + 知识图谱(影响分析/覆盖矩阵/功能画像/业务流程/多跳遍历)的唯一入口。"
|
|
4
|
-
argument-hint: "[keyword] or --api [path] or subcommand. 全系
|
|
4
|
+
argument-hint: "[keyword] or --api [path] or subcommand. 全系15个能力见下表"
|
|
5
5
|
auto-approve: true
|
|
6
6
|
allowed-tools: [Read, Bash]
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
# /wl-search - 搜索代码 & 知识图谱
|
|
9
|
+
# /wl-search - 搜索代码 & 知识图谱 & RAG 语义检索
|
|
10
10
|
|
|
11
11
|
User input: $ARGUMENTS
|
|
12
12
|
|
|
@@ -15,48 +15,131 @@ User input: $ARGUMENTS
|
|
|
15
15
|
```python
|
|
16
16
|
from capability import resolve
|
|
17
17
|
cap = resolve()
|
|
18
|
-
result = cap.mcp.call("
|
|
18
|
+
result = cap.mcp.call("rag_search", {"query": "车辆保养", "top_k": 8})
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
自动路由:有 MCP 走 MCP
|
|
21
|
+
自动路由:有 MCP 走 MCP(直连平台知识层,快),无 MCP 走 wlkj.py(CLI 降级)。零宿主感知。
|
|
22
22
|
|
|
23
|
-
## ⚡
|
|
23
|
+
## ⚡ 第一步:先判断问题类型,选对检索通道(3 路检索)
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|---------|-----------------|----------|
|
|
27
|
-
| **"XX怎么实现的/怎么做的"** | `cap.mcp.call("context_pack", {"keyword": "XX", "role": "dev"})` | 不要一个个 search(会搜 5-7 次,慢费 token) |
|
|
28
|
-
| **"XX代码在哪"** | `cap.mcp.call("search_code", {"keyword": "XX"})` | 不要 context(杀鸡用牛刀) |
|
|
29
|
-
| **"改 XX 影响谁"** | `cap.mcp.call("get_impact", {"endpoint": "/XX"})` | — |
|
|
25
|
+
**核心升级:本命令有 3 路检索,按问题类型选最合适的一路(不是无脑 search_code)。**
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
| 问题类型 | 首选检索通道 | 为什么 |
|
|
28
|
+
|---------|-------------|--------|
|
|
29
|
+
| **"车辆保养"相关的代码/字段/API**(语义找相关,词不必一样) | `rag_search` 语义召回 | 能找到"维修记录"即使没共享词,召回最全 |
|
|
30
|
+
| **"这个功能的业务流程是什么 / 整体怎么运转"**(全局问答) | `ask_corpus` GraphRAG 问答 | 用社区摘要直接答,不是堆代码片段 |
|
|
31
|
+
| **"handleExport 这个符号在哪定义/调用"**(精确符号定位) | `search_code` 关键词 | 精确命中,找特定符号最快 |
|
|
32
|
+
| **"XX怎么实现的/怎么做的"**(一次取全代码+API+字段) | `context_pack` | 一条命令拿全 8 段上下文 |
|
|
33
|
+
| **"改 XX 影响谁"** | `get_impact` | 影响分析专用 |
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
> **顺序铁律**:理解/盘点类问题,**先 rag_search(语义召回最全)**;有"整体流程/业务怎么运转"的全局问题,**再补 ask_corpus(GraphRAG 答案级)**;只在精确找某个符号/特定字符串时才用 search_code。
|
|
36
|
+
> Glob 找不到文件时用 search_code 兜底,**不准跑 find/findstr/dir /s**。
|
|
37
|
+
|
|
38
|
+
### 三路检索详解(RAG 升级核心)
|
|
39
|
+
|
|
40
|
+
**① rag_search — 语义召回(默认首选,召回最全)**
|
|
41
|
+
```python
|
|
42
|
+
# 语义检索:query 是自然语言/业务词,不必和代码里的词一样
|
|
43
|
+
# 能找到"车辆保养"相关的"维修记录",即使两者没共享词
|
|
44
|
+
cap.mcp.call("rag_search", {"query": "车辆保养流程", "top_k": 8})
|
|
45
|
+
```
|
|
46
|
+
- 返回:相关代码片段 / 字段 / API,按语义相关度排序
|
|
47
|
+
- 适用:写 PRD/改代码前找相关实现、盘点某业务有哪些代码、关键词搜索召回不全时
|
|
48
|
+
- `top_k` 默认 8,要更全调到 12-15
|
|
49
|
+
|
|
50
|
+
**② ask_corpus — GraphRAG 全局问答(答业务流程类问题)**
|
|
51
|
+
```python
|
|
52
|
+
# GraphRAG 社区摘要问答:直接给"答案",不是堆代码片段
|
|
53
|
+
# 能答"资产管理的业务流程是什么""这个功能整体怎么运转"
|
|
54
|
+
cap.mcp.call("ask_corpus", {"q": "车辆保养的整体业务流程是什么", "top_k": 3})
|
|
55
|
+
```
|
|
56
|
+
- 返回:基于知识图谱社区摘要的自然语言回答
|
|
57
|
+
- 适用:问"整体流程/业务怎么运转/这个功能是干嘛的"等全局问题
|
|
58
|
+
- ⚠️ 引擎工具名是 `ask_corpus`,平台侧映射到 `graphrag_ask`(mcp_config.json 已配)
|
|
59
|
+
|
|
60
|
+
**③ search_code — 精确关键词(找特定符号/字符串)**
|
|
61
|
+
```python
|
|
62
|
+
# 精确关键词:找特定函数名/类名/字符串字面量
|
|
63
|
+
cap.mcp.call("search_code", {"keyword": "handleExport", "platform": "web"})
|
|
64
|
+
```
|
|
65
|
+
- 返回:精确命中的代码位置
|
|
66
|
+
- 适用:已知符号名要定位、rag_search 召回了但要精确找某行
|
|
67
|
+
|
|
68
|
+
### 输出整合(三路并用时)
|
|
69
|
+
|
|
70
|
+
理解一个功能时,建议 **rag_search + ask_corpus 并用**:
|
|
71
|
+
1. `rag_search` 拿到相关代码/字段/API(事实依据)
|
|
72
|
+
2. `ask_corpus` 拿到业务流程的自然语言回答(全局视角)
|
|
73
|
+
3. 整合:先讲业务流程(来自 ask_corpus),再列相关代码/字段(来自 rag_search)
|
|
74
|
+
4. 精确符号定位才补 `search_code`
|
|
75
|
+
|
|
76
|
+
### 盘点模式(多 agent 并行召回 · 宿主能力)
|
|
77
|
+
|
|
78
|
+
"盘点某业务有哪些代码/字段/API/Wiki/PRD"这类要全量扫的,宿主支持 Agent 并行时**派多个 subagent 各召回一类并发跑**,再合并成一张盘点表:
|
|
79
|
+
- agent①:`rag_search` 召回代码片段 + `search_code` 精确符号
|
|
80
|
+
- agent②:`search_api` 召回相关端点
|
|
81
|
+
- agent③:`search_wiki` 召回模块文档
|
|
82
|
+
- agent④:`search_prd` / `search_prd_semantic` 召回历史 PRD
|
|
83
|
+
- 合并:去重 + 按制品分组,输出"代码 N 处 / API M 个 / Wiki K 篇 / PRD J 份"
|
|
84
|
+
|
|
85
|
+
不支持 Agent 并行 → 按上方三路检索串行跑(rag_search 一次召回最全,已够多数盘点)。
|
|
86
|
+
|
|
87
|
+
## 知识图谱能力(20+,统一 cap.mcp.call 调用)
|
|
35
88
|
|
|
36
89
|
| 用户要查什么 | 调用方式 |
|
|
37
90
|
|-------------|---------|
|
|
38
|
-
|
|
|
91
|
+
| **语义找相关代码/字段(首选,召回最全)** | `cap.mcp.call("rag_search", {"query": "车辆保养", "top_k": 8})` |
|
|
92
|
+
| **GraphRAG 全局业务流程问答** | `cap.mcp.call("ask_corpus", {"q": "保养流程是什么", "top_k": 3})` |
|
|
93
|
+
| 代码在哪 / 精确搜关键词 | `cap.mcp.call("search_code", {"keyword": "考勤", "platform": "web"})` |
|
|
39
94
|
| API 端点 | `cap.mcp.call("search_api", {"keyword": "salary"})` |
|
|
40
95
|
| 已有 PRD(防重复造轮子) | `cap.mcp.call("search_prd", {"keyword": "保险"})` |
|
|
41
96
|
| 改某接口影响哪些页面 | `cap.mcp.call("get_impact", {"endpoint": "/asset"})` |
|
|
97
|
+
| **改动风险评估(7项多证据,score+level)** | `cap.mcp.call("risk_assessment", {"project_id":"<UUID>", "entity":"<符号>"})` |
|
|
98
|
+
| **路径置信度(证据路径置信+路径链)** | `cap.mcp.call("get_confidence", {"project_id":"<UUID>", "entity":"<符号>"})` |
|
|
99
|
+
| **文件/符号变更史(代码→需求,被哪些需求改过)** | `cap.mcp.call("code_history", {"project_id":"<UUID>", "file_path":"<文件名>"})` |
|
|
100
|
+
| **需求代码变更切片(需求→代码,XQ/WT号查改过哪些函数)** | `cap.mcp.call("code_changes", {"project_id":"<UUID>", "req_key":"XQ1248"})` |
|
|
101
|
+
| **禅道story反查平台spec(看需求已有开发规格)** | `cap.mcp.call("find_specs_by_zentao", {"project_id":"<UUID>", "zentao_id":"<story号>"})` |
|
|
42
102
|
| 某函数/端点的完整关联 | `cap.mcp.call("context_360", {"symbol": "handleExport"})` |
|
|
43
103
|
| 一次取全(代码+页面+字段+API) | `cap.mcp.call("context_pack", {"keyword": "车辆", "role": "pm"})` |
|
|
44
104
|
| 哪些功能有/没测试 | `cap.mcp.call("coverage_matrix", {})` |
|
|
45
105
|
| 功能完整画像 | `cap.mcp.call("feature_overview", {"feature": "资产管理"})` |
|
|
46
106
|
| 业务流程链(几步) | `cap.mcp.call("get_workflow", {"module": "assets"})` |
|
|
47
107
|
| 多跳遍历(关联实体) | `cap.mcp.call("multi_hop", {"symbol": "资产管理", "depth": 3})` |
|
|
108
|
+
| **业务链路追踪(概念→PRD+代码+表+测试)** | `cap.mcp.call("business_trace", {"query": "保险理赔", "depth": 3})` |
|
|
109
|
+
| **需求全貌(REQ-ID→PRD+代码+表+测试)** | `cap.mcp.call("req_trace", {"req_id": "REQ-2026-042"})` |
|
|
110
|
+
| **字段全链路(表单→接口→Java字段→DB列)** | `cap.mcp.call("trace_dataflow", {"field": "vehicleNo"})` |
|
|
111
|
+
| **概念多源画像(PRD+代码+表+原型)** | `cap.mcp.call("anchor_view", {"concept": "保险单"})` |
|
|
112
|
+
| **5制品全证据链(PRD+代码+表+测试+原型+强度+缺失提示)** | `cap.mcp.call("evidence_chain", {"concept": "保险单"})` |
|
|
113
|
+
| **PRD 正文语义搜(搜正文,不只标题)** | `cap.mcp.call("search_prd_semantic", {"query": "异常筛选"})` |
|
|
48
114
|
| Repo Wiki 模块文档 | `cap.mcp.call("search_wiki", {"keyword": "考勤"})` |
|
|
49
115
|
| 原型预填(真实数据) | `cap.mcp.call("fill_prototype", {"keyword": "车辆", "platform": "web"})` |
|
|
50
116
|
| 设计系统规范 | `cap.mcp.call("get_design_system", {"platform": "web"})` |
|
|
51
117
|
|
|
118
|
+
## 🎨 富展示(看板 HTML · 复用 cap.present)
|
|
119
|
+
|
|
120
|
+
get_impact / coverage_matrix / feature_overview 的结果可一键转富展示看板 HTML(QoderWork 嵌入对话 / CLI 落盘 journal):
|
|
121
|
+
```bash
|
|
122
|
+
# 影响传播树(分层 upstream/downstream 可折叠)
|
|
123
|
+
$PY "$R/.qoder/scripts/validation/metrics/present_board.py" impact --entity <符号> --project-id <UUID>
|
|
124
|
+
# 测试覆盖热力图(功能×测试 有/无)
|
|
125
|
+
$PY "$R/.qoder/scripts/validation/metrics/present_board.py" coverage --project-id <UUID>
|
|
126
|
+
# 功能画像卡(端点+按钮+用例+页面+PRD)
|
|
127
|
+
$PY "$R/.qoder/scripts/validation/metrics/present_board.py" feature --feature <功能名> --project-id <UUID>
|
|
128
|
+
```
|
|
129
|
+
- **QoderWork 桌面端**(cap.present.available):HTML 嵌入对话流,富展示取代纯文本表格
|
|
130
|
+
- **CLI/IDE**:落盘 `workspace/members/{dev}/journal/{name}-{ts}.html`,输出路径供打开
|
|
131
|
+
- 不用 cap.present 也能跑——上面的能力表是纯文本调用,富展示只是增强可视化(T244 接入点)
|
|
132
|
+
|
|
52
133
|
## 快速判断该用哪个
|
|
53
134
|
|
|
135
|
+
- **"这个功能怎么实现 / 相关代码有哪些"** → 先 `rag_search`(语义最全),不够再 `search_code`
|
|
136
|
+
- **"这个功能的业务流程是什么 / 整体怎么运转"** → `ask_corpus`(GraphRAG 问答)
|
|
54
137
|
- **"这个功能已经有了吗"** → `prd` 查需求 + `feature` 看画像
|
|
55
138
|
- **"改这个会影响谁"** → `impact`
|
|
56
139
|
- **"哪些功能缺测试"** → `coverage`
|
|
57
|
-
- **"盘点流程有几步"** → `workflow`
|
|
140
|
+
- **"盘点流程有几步"** → `workflow` 或 `ask_corpus`
|
|
58
141
|
- **"XX 谁调用了/调用链"** → `context360` 或 `hop`
|
|
59
|
-
- **写 PRD 前一次取全** → `context_pack --role pm`
|
|
142
|
+
- **写 PRD 前一次取全** → `rag_search` + `context_pack --role pm`
|
|
60
143
|
- **出原型前** → `design_system` + `fill_prototype`
|
|
61
144
|
|
|
62
145
|
## 字段/页面风格/组件
|
|
@@ -107,13 +190,16 @@ $PY "$R/.qoder/scripts/orchestration/wlkj.py" kg grep-text 车辆不存在 --ext
|
|
|
107
190
|
|
|
108
191
|
## How to Use Results
|
|
109
192
|
|
|
110
|
-
1.
|
|
111
|
-
2.
|
|
112
|
-
3.
|
|
193
|
+
1. 三路检索并用时:先讲业务流程(ask_corpus),再列相关代码/字段(rag_search),精确符号补 search_code
|
|
194
|
+
2. Pick the most relevant files (2-3 max)
|
|
195
|
+
3. Read ONLY those files directly
|
|
196
|
+
4. Answer the user's question — 提炼后回答,别贴原始输出
|
|
113
197
|
|
|
114
198
|
## Examples
|
|
115
199
|
|
|
116
|
-
- `/wl-search
|
|
200
|
+
- `/wl-search 车辆保养` → 先 `rag_search({"query":"车辆保养","top_k":8})`(语义最全),有流程问题再 `ask_corpus({"q":"车辆保养流程"})`
|
|
201
|
+
- `/wl-search 车辆保养的业务流程是什么` → `cap.mcp.call("ask_corpus", {"q": "车辆保养的业务流程是什么", "top_k": 3})`
|
|
202
|
+
- `/wl-search handleExport 在哪` → `cap.mcp.call("search_code", {"keyword": "handleExport"})`(精确符号)
|
|
117
203
|
- `/wl-search --api salary` → `cap.mcp.call("search_api", {"keyword": "salary"})`
|
|
118
204
|
- `/wl-search 改 /asset 影响谁` → `cap.mcp.call("get_impact", {"endpoint": "/asset"})`
|
|
119
205
|
- `/wl-search 哪些功能没测试` → `cap.mcp.call("coverage_matrix", {})`
|