@hupan56/wlkj 3.1.32 → 3.3.0

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 (178) hide show
  1. package/bin/cli.js +117 -0
  2. package/package.json +1 -1
  3. package/templates/qoder/agents/insight-planning.md +67 -67
  4. package/templates/qoder/agents/prd-reference.md +47 -47
  5. package/templates/qoder/commands/optional/wl-insight.md +4 -4
  6. package/templates/qoder/commands/optional/wl-report.md +1 -1
  7. package/templates/qoder/commands/optional/wl-spec.md +23 -3
  8. package/templates/qoder/commands/optional/wl-status.md +12 -1
  9. package/templates/qoder/commands/wl-code.md +138 -7
  10. package/templates/qoder/commands/wl-commit.md +12 -1
  11. package/templates/qoder/commands/wl-design.md +70 -6
  12. package/templates/qoder/commands/wl-init.md +27 -0
  13. package/templates/qoder/commands/wl-prd.md +230 -15
  14. package/templates/qoder/commands/wl-req.md +10 -3
  15. package/templates/qoder/commands/wl-search.md +74 -20
  16. package/templates/qoder/commands/wl-task.md +3 -3
  17. package/templates/qoder/commands/wl-test.md +17 -2
  18. package/templates/qoder/contracts/CHANGELOG.md +418 -0
  19. package/templates/qoder/contracts/README.md +180 -0
  20. package/templates/qoder/contracts/code.md +82 -0
  21. package/templates/qoder/contracts/commit.md +86 -0
  22. package/templates/qoder/contracts/contract-header.md +76 -0
  23. package/templates/qoder/contracts/design.md +106 -0
  24. package/templates/qoder/contracts/fallback.md +126 -0
  25. package/templates/qoder/contracts/isolation.md +119 -0
  26. package/templates/qoder/contracts/prd.md +118 -0
  27. package/templates/qoder/contracts/schemas/design-spec.schema.json +46 -0
  28. package/templates/qoder/contracts/schemas/prd.schema.json +36 -0
  29. package/templates/qoder/contracts/schemas/test-cases.schema.json +40 -0
  30. package/templates/qoder/contracts/spec.md +116 -0
  31. package/templates/qoder/contracts/task.md +125 -0
  32. package/templates/qoder/contracts/test.md +112 -0
  33. package/templates/qoder/hooks/post-tool-use.py +61 -0
  34. package/templates/qoder/hooks/session-start.py +34 -66
  35. package/templates/qoder/hooks/stop-eval.py +47 -0
  36. package/templates/qoder/rules/wl-pipeline.md +37 -0
  37. package/templates/qoder/scripts/capability/__pycache__/__init__.cpython-39.pyc +0 -0
  38. package/templates/qoder/scripts/capability/__pycache__/registry.cpython-39.pyc +0 -0
  39. package/templates/qoder/scripts/capability/__pycache__/registry_mcp.cpython-39.pyc +0 -0
  40. package/templates/qoder/scripts/capability/adapters/__init__.py +1 -1
  41. package/templates/qoder/scripts/capability/adapters/__pycache__/__init__.cpython-39.pyc +0 -0
  42. package/templates/qoder/scripts/capability/adapters/__pycache__/cli.cpython-39.pyc +0 -0
  43. package/templates/qoder/scripts/capability/adapters/__pycache__/mcp.cpython-39.pyc +0 -0
  44. package/templates/qoder/scripts/capability/adapters/__pycache__/qw.cpython-39.pyc +0 -0
  45. package/templates/qoder/scripts/capability/adapters/mcp.py +76 -100
  46. package/templates/qoder/scripts/capability/adapters/qw.py +295 -295
  47. package/templates/qoder/scripts/capability/caps/__init__.py +1 -1
  48. package/templates/qoder/scripts/capability/caps/__pycache__/__init__.cpython-39.pyc +0 -0
  49. package/templates/qoder/scripts/capability/caps/__pycache__/context.cpython-39.pyc +0 -0
  50. package/templates/qoder/scripts/capability/caps/__pycache__/cron.cpython-39.pyc +0 -0
  51. package/templates/qoder/scripts/capability/caps/__pycache__/identity.cpython-39.pyc +0 -0
  52. package/templates/qoder/scripts/capability/caps/__pycache__/memory.cpython-39.pyc +0 -0
  53. package/templates/qoder/scripts/capability/caps/__pycache__/notify.cpython-39.pyc +0 -0
  54. package/templates/qoder/scripts/capability/caps/__pycache__/present.cpython-39.pyc +0 -0
  55. package/templates/qoder/scripts/capability/caps/__pycache__/repo.cpython-39.pyc +0 -0
  56. package/templates/qoder/scripts/capability/caps/__pycache__/sandbox.cpython-39.pyc +0 -0
  57. package/templates/qoder/scripts/capability/caps/memory.py +1 -1
  58. package/templates/qoder/scripts/capability/registry.py +21 -23
  59. package/templates/qoder/scripts/capability/registry_mcp.py +69 -5
  60. package/templates/qoder/scripts/capability/smoke_test_report.json +34 -20
  61. package/templates/qoder/scripts/deployment/setup/carriers.py +3 -1
  62. package/templates/qoder/scripts/deployment/setup/init_doctor.py +10 -3
  63. package/templates/qoder/scripts/deployment/setup/install_qoderwork.py +11 -0
  64. package/templates/qoder/scripts/deployment/setup/wlkj_shim.py +104 -0
  65. package/templates/qoder/scripts/domain/__pycache__/__init__.cpython-39.pyc +0 -0
  66. package/templates/qoder/scripts/domain/deployment/deploy_to_test.py +298 -0
  67. package/templates/qoder/scripts/domain/integration/__init__.py +0 -0
  68. package/templates/qoder/scripts/domain/integration/__pycache__/__init__.cpython-39.pyc +0 -0
  69. package/templates/qoder/scripts/domain/integration/__pycache__/return_to_platform.cpython-39.pyc +0 -0
  70. package/templates/qoder/scripts/domain/integration/return_to_platform.py +392 -0
  71. package/templates/qoder/scripts/domain/integration/spec_upload.py +209 -0
  72. package/templates/qoder/scripts/domain/kg/build/kg_build.py +268 -25
  73. package/templates/qoder/scripts/domain/kg/build/kg_incremental.py +108 -3
  74. package/templates/qoder/scripts/domain/kg/build/kg_signatures.py +169 -0
  75. package/templates/qoder/scripts/domain/kg/extract/asset/__init__.py +10 -0
  76. package/templates/qoder/scripts/domain/kg/extract/asset/asset_tree.py +57 -0
  77. package/templates/qoder/scripts/domain/kg/extract/asset/discussion_importer.py +62 -0
  78. package/templates/qoder/scripts/domain/kg/extract/asset/prd_importer.py +146 -0
  79. package/templates/qoder/scripts/domain/kg/extract/asset/prototype_importer.py +64 -0
  80. package/templates/qoder/scripts/domain/kg/extract/asset/returns_importer.py +52 -0
  81. package/templates/qoder/scripts/domain/kg/extract/build_goal3.py +104 -0
  82. package/templates/qoder/scripts/domain/kg/extract/build_goal4.py +55 -0
  83. package/templates/qoder/scripts/domain/kg/extract/build_goal5.py +95 -0
  84. package/templates/qoder/scripts/domain/kg/extract/db/__init__.py +8 -0
  85. package/templates/qoder/scripts/domain/kg/extract/db/data_profile.py +22 -0
  86. package/templates/qoder/scripts/domain/kg/extract/db/fk_extractor.py +55 -0
  87. package/templates/qoder/scripts/domain/kg/extract/db/schema_extractor.py +90 -0
  88. package/templates/qoder/scripts/domain/kg/extract/extract.py +84 -0
  89. package/templates/qoder/scripts/domain/kg/extract/extract.py.bak +430 -0
  90. package/templates/qoder/scripts/domain/kg/extract/inference/__init__.py +9 -0
  91. package/templates/qoder/scripts/domain/kg/extract/inference/community_summarizer.py +206 -0
  92. package/templates/qoder/scripts/domain/kg/extract/inference/embed_builder.py +132 -0
  93. package/templates/qoder/scripts/domain/kg/extract/inference/naming_matcher.py +80 -0
  94. package/templates/qoder/scripts/domain/kg/extract/inference/promote.py +59 -0
  95. package/templates/qoder/scripts/domain/kg/extract/inference/recompute.py +93 -0
  96. package/templates/qoder/scripts/domain/kg/extract/inference/weak_link.py +421 -0
  97. package/templates/qoder/scripts/domain/kg/extract/java/__init__.py +15 -0
  98. package/templates/qoder/scripts/domain/kg/extract/java/_parser.py +271 -0
  99. package/templates/qoder/scripts/domain/kg/extract/java/all.py +145 -0
  100. package/templates/qoder/scripts/domain/kg/extract/java/build_java_to_pg.py +102 -0
  101. package/templates/qoder/scripts/domain/kg/extract/java/call_chain.py +49 -0
  102. package/templates/qoder/scripts/domain/kg/extract/java/class_extractor.py +141 -0
  103. package/templates/qoder/scripts/domain/kg/extract/java/domain_extractor.py +148 -0
  104. package/templates/qoder/scripts/domain/kg/extract/java/dubbo_extractor.py +33 -0
  105. package/templates/qoder/scripts/domain/kg/extract/java/endpoint_extractor.py +36 -0
  106. package/templates/qoder/scripts/domain/kg/extract/java/javadoc_extractor.py +110 -0
  107. package/templates/qoder/scripts/domain/kg/extract/java/llm_cn_filler.py +150 -0
  108. package/templates/qoder/scripts/domain/kg/extract/java/member_extractor.py +157 -0
  109. package/templates/qoder/scripts/domain/kg/extract/java/mybatisplus_extractor.py +34 -0
  110. package/templates/qoder/scripts/domain/kg/extract/java/pg_upsert.py +165 -0
  111. package/templates/qoder/scripts/domain/kg/extract/java/satoken_extractor.py +30 -0
  112. package/templates/qoder/scripts/domain/kg/extract/java/spring_extractor.py +39 -0
  113. package/templates/qoder/scripts/domain/kg/extract/java/validation_extractor.py +33 -0
  114. package/templates/qoder/scripts/domain/kg/extract/mybatis/__init__.py +9 -0
  115. package/templates/qoder/scripts/domain/kg/extract/mybatis/all.py +79 -0
  116. package/templates/qoder/scripts/domain/kg/extract/mybatis/mapper_parser.py +99 -0
  117. package/templates/qoder/scripts/domain/kg/extract/mybatis/relation_builder.py +69 -0
  118. package/templates/qoder/scripts/domain/kg/extract/mybatis/sql_extractor.py +78 -0
  119. package/templates/qoder/scripts/domain/kg/extract/prd/__init__.py +8 -0
  120. package/templates/qoder/scripts/domain/kg/extract/prd/prd_chunk_embed.py +105 -0
  121. package/templates/qoder/scripts/domain/kg/extract/prd/prd_llm_extract.py +153 -0
  122. package/templates/qoder/scripts/domain/kg/extract/prd/req_anchor.py +120 -0
  123. package/templates/qoder/scripts/domain/kg/extract/ts_extract.py +111 -0
  124. package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +4 -2
  125. package/templates/qoder/scripts/domain/kg/kg.py +42 -5
  126. package/templates/qoder/scripts/domain/kg/search/_remote.py +187 -0
  127. package/templates/qoder/scripts/domain/kg/search/context_pack.py +32 -2
  128. package/templates/qoder/scripts/domain/kg/search/search_index.py +74 -20
  129. package/templates/qoder/scripts/domain/kg/storage/kg_duckdb.py +43 -0
  130. package/templates/qoder/scripts/domain/kg/switch_project.py +159 -0
  131. package/templates/qoder/scripts/domain/kg/sync_repowiki.py +109 -0
  132. package/templates/qoder/scripts/domain/requirement/req.py +134 -28
  133. package/templates/qoder/scripts/domain/task/__pycache__/wlkj_panel.cpython-39.pyc +0 -0
  134. package/templates/qoder/scripts/domain/task/wlkj_panel.py +1348 -0
  135. package/templates/qoder/scripts/engine/poller.py +219 -0
  136. package/templates/qoder/scripts/foundation/__pycache__/__init__.cpython-39.pyc +0 -0
  137. package/templates/qoder/scripts/foundation/core/__pycache__/__init__.cpython-39.pyc +0 -0
  138. package/templates/qoder/scripts/foundation/core/__pycache__/paths.cpython-39.pyc +0 -0
  139. package/templates/qoder/scripts/foundation/core/paths.py +102 -0
  140. package/templates/qoder/scripts/foundation/integrations/active_task.py +2 -1
  141. package/templates/qoder/scripts/orchestration/wlkj.py +4 -0
  142. package/templates/qoder/scripts/protocol/__pycache__/__init__.cpython-39.pyc +0 -0
  143. package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +24 -11
  144. package/templates/qoder/scripts/protocol/transports/__pycache__/__init__.cpython-39.pyc +0 -0
  145. package/templates/qoder/scripts/protocol/transports/__pycache__/base.cpython-39.pyc +0 -0
  146. package/templates/qoder/scripts/protocol/transports/__pycache__/cli.cpython-39.pyc +0 -0
  147. package/templates/qoder/scripts/protocol/transports/__pycache__/http.cpython-39.pyc +0 -0
  148. package/templates/qoder/scripts/protocol/transports/__pycache__/stdio.cpython-39.pyc +0 -0
  149. package/templates/qoder/scripts/protocol/transports/http.py +7 -1
  150. package/templates/qoder/scripts/validation/eval/qwork_harness.py +1 -1
  151. package/templates/qoder/scripts/validation/eval/report-commands.md +2 -2
  152. package/templates/qoder/settings.json +27 -9
  153. package/templates/qoder/skills/design-import/SKILL.md +3 -3
  154. package/templates/qoder/skills/design-review/SKILL.md +1 -1
  155. package/templates/qoder/skills/prd-generator/SKILL.md +4 -4
  156. package/templates/qoder/skills/prd-review/SKILL.md +1 -1
  157. package/templates/qoder/skills/prototype-generator/SKILL.md +3 -3
  158. package/templates/qoder/skills/spec-coder/SKILL.md +1 -1
  159. package/templates/qoder/skills/spec-generator/SKILL.md +80 -23
  160. package/templates/qoder/skills/test-generator/SKILL.md +1 -1
  161. package/templates/qoder/skills/wl-code/SKILL.md +13 -1
  162. package/templates/qoder/skills/wl-commit/SKILL.md +1 -1
  163. package/templates/qoder/skills/wl-design/SKILL.md +6 -6
  164. package/templates/qoder/skills/wl-init/SKILL.md +2 -2
  165. package/templates/qoder/skills/wl-insight/SKILL.md +5 -5
  166. package/templates/qoder/skills/wl-prd/SKILL.md +60 -0
  167. package/templates/qoder/skills/wl-report/SKILL.md +2 -2
  168. package/templates/qoder/skills/wl-search/SKILL.md +1 -1
  169. package/templates/qoder/skills/wl-spec/SKILL.md +2 -2
  170. package/templates/qoder/skills/wl-status/SKILL.md +2 -2
  171. package/templates/qoder/skills/wl-task/SKILL.md +3 -3
  172. package/templates/qoder/skills/wl-test/SKILL.md +2 -2
  173. package/templates/qoder/templates/spec-template.md +124 -0
  174. package/templates/root/AGENTS.md +41 -14
  175. package/templates/qoder/scripts/domain/task/zentao_panel.py +0 -451
  176. package/templates/qoder/skills/wl-prd-full/SKILL.md +0 -121
  177. package/templates/qoder/skills/wl-prd-quick/SKILL.md +0 -50
  178. package/templates/qoder/skills/wl-prd-review/SKILL.md +0 -47
package/bin/cli.js CHANGED
@@ -1249,6 +1249,10 @@ function doHelp() {
1249
1249
  console.log(" 或斜杠: /wl-prd /wl-design /wl-task /wl-code /wl-test /wl-commit");
1250
1250
  console.log(" (提交/同步 /wl-task 和 /wl-commit 会自动做, 不用单独 npx sync)");
1251
1251
  console.log("");
1252
+ console.log("=== 能力市场 ===");
1253
+ console.log(" npx @hupan56/wlkj install skill <token> --host <url> 从市场装 Skill 到本地 IDE");
1254
+ console.log(" npx @hupan56/wlkj install agent <token> --host <url> 从市场装 Agent (含依赖 Skill)");
1255
+ console.log("");
1252
1256
  console.log("=== 进阶 (管理员/特殊情况才用, 不常用) ===");
1253
1257
  console.log(" npx @hupan56/wlkj selftest 全套件自检 (跨环境+QoderWork工具协议+smoke+体检+MCP)");
1254
1258
  console.log(" npx @hupan56/wlkj doctor 体检 (或在 Qoder 里 /wl-init 无参数)");
@@ -1521,5 +1525,118 @@ switch (cmd) {
1521
1525
  break;
1522
1526
  }
1523
1527
 
1528
+ // ── 能力市场安装: npx @hupan56/wlkj install <skill|agent> <token> --host <url> ──
1529
+ case "install": {
1530
+ const kind = rest[0]; // skill / agent
1531
+ const token = rest[1]; // share_token
1532
+ const hostIdx = rest.indexOf("--host");
1533
+ const host = hostIdx !== -1 && rest[hostIdx + 1] ? rest[hostIdx + 1] : "http://127.0.0.1:10010";
1534
+
1535
+ if (!kind || !token || !["skill", "agent"].includes(kind)) {
1536
+ console.log("用法: npx @hupan56/wlkj install <skill|agent> <token> [--host <url>]");
1537
+ console.log("例: npx @hupan56/wlkj install skill abc123 --host http://127.0.0.1:10010");
1538
+ process.exit(1);
1539
+ }
1540
+
1541
+ (async () => {
1542
+ try {
1543
+ // 探测本地 IDE
1544
+ const cwd = process.cwd();
1545
+ let ide = "claude";
1546
+ if (fs.existsSync(path.join(cwd, ".cursor"))) ide = "cursor";
1547
+ else if (fs.existsSync(path.join(cwd, ".qoder"))) ide = "qoder";
1548
+ else if (fs.existsSync(path.join(cwd, ".claude"))) ide = "claude";
1549
+ else if (fs.existsSync(path.join(cwd, "CLAUDE.md"))) ide = "claude";
1550
+ else if (fs.existsSync(path.join(cwd, "AGENTS.md"))) ide = "codex";
1551
+
1552
+ if (kind === "agent") {
1553
+ console.log(`→ 从 ${host} 拉取 Agent ${token}...`);
1554
+ const res = await fetch(`${host}/api/market/agent/${token}`);
1555
+ if (!res.ok) throw new Error(`API 返回 ${res.status}`);
1556
+ const agent = await res.json();
1557
+ console.log(`✓ ${agent.icon || "🤖"} ${agent.title}`);
1558
+
1559
+ // 写入 IDE
1560
+ if (ide === "claude" || ide === "codex") {
1561
+ const dir = path.join(cwd, ".claude", "commands");
1562
+ fs.mkdirSync(dir, { recursive: true });
1563
+ const fname = (agent.name || agent.title || "agent") + ".md";
1564
+ let content = `---\ndescription: ${agent.title || ""}\n---\n\n`;
1565
+ content += agent.rolePrompt || agent.role_prompt || `你是${agent.title || "AI助手"}。\n`;
1566
+ if ((agent.toolIds || []).length) {
1567
+ content += `\n## 可用工具\n${(agent.toolIds || []).join(", ")}\n`;
1568
+ }
1569
+ if ((agent.skillIds || []).length) {
1570
+ content += `\n## 可用技能\n${(agent.skillIds || []).join(", ")}\n`;
1571
+ }
1572
+ fs.writeFileSync(path.join(dir, fname), content, "utf-8");
1573
+ console.log(`✓ 已写入: ${path.join(dir, fname)}`);
1574
+ } else if (ide === "qoder") {
1575
+ const dir = path.join(cwd, ".qoder", "agents");
1576
+ fs.mkdirSync(dir, { recursive: true });
1577
+ const fname = (agent.name || agent.title || "agent") + ".json";
1578
+ fs.writeFileSync(path.join(dir, fname), JSON.stringify({
1579
+ name: agent.name, title: agent.title,
1580
+ systemPrompt: agent.rolePrompt || agent.role_prompt || "",
1581
+ tools: agent.toolIds || [], skills: agent.skillIds || [],
1582
+ model: agent.model || null,
1583
+ }, null, 2), "utf-8");
1584
+ console.log(`✓ 已写入: ${path.join(dir, fname)}`);
1585
+ } else if (ide === "cursor") {
1586
+ const dir = path.join(cwd, ".cursor", "rules");
1587
+ fs.mkdirSync(dir, { recursive: true });
1588
+ const fname = (agent.name || agent.title || "agent") + ".mdc";
1589
+ let content = `---\ndescription: ${agent.title || ""}\n---\n`;
1590
+ content += agent.rolePrompt || agent.role_prompt || "";
1591
+ fs.writeFileSync(path.join(dir, fname), content, "utf-8");
1592
+ console.log(`✓ 已写入: ${path.join(dir, fname)}`);
1593
+ }
1594
+
1595
+ // 递归装依赖 Skill
1596
+ const skillIds = agent.skillIds || [];
1597
+ for (const sid of skillIds) {
1598
+ if (typeof sid === "string" && sid.length > 5) {
1599
+ console.log(`→ 递归安装 Skill: ${sid}`);
1600
+ try {
1601
+ const sres = await fetch(`${host}/api/market/skill/${sid}`);
1602
+ if (sres.ok) {
1603
+ const skill = await sres.json();
1604
+ const sdir = path.join(cwd, ".claude", "skills", skill.name || sid);
1605
+ fs.mkdirSync(sdir, { recursive: true });
1606
+ let smd = `---\nname: ${skill.name || sid}\ndescription: ${skill.description || ""}\n---\n`;
1607
+ smd += skill.promptTemplate || skill.prompt_template || "";
1608
+ fs.writeFileSync(path.join(sdir, "SKILL.md"), smd, "utf-8");
1609
+ console.log(` ✓ ${skill.title || sid}`);
1610
+ } else { console.warn(` ⚠ Skill ${sid} 不存在或未发布`); }
1611
+ } catch (e) { console.warn(` ⚠ Skill ${sid} 安装失败: ${e.message}`); }
1612
+ }
1613
+ }
1614
+ console.log(`\n✅ Agent "${agent.title}" 已安装(${ide} 格式)`);
1615
+ }
1616
+
1617
+ else if (kind === "skill") {
1618
+ console.log(`→ 从 ${host} 拉取 Skill ${token}...`);
1619
+ const res = await fetch(`${host}/api/market/skill/${token}`);
1620
+ if (!res.ok) throw new Error(`API 返回 ${res.status}`);
1621
+ const skill = await res.json();
1622
+ console.log(`✓ ${skill.icon || "🛠"} ${skill.title}`);
1623
+
1624
+ const sname = skill.name || token;
1625
+ const sdir = path.join(cwd, ".claude", "skills", sname);
1626
+ fs.mkdirSync(sdir, { recursive: true });
1627
+ let smd = `---\nname: ${sname}\ntitle: ${skill.title || ""}\ndescription: ${skill.description || ""}\nicon: ${skill.icon || ""}\nversion: ${skill.version || "1.0.0"}\n---\n`;
1628
+ smd += skill.promptTemplate || skill.prompt_template || "";
1629
+ fs.writeFileSync(path.join(sdir, "SKILL.md"), smd, "utf-8");
1630
+ console.log(`✓ 已写入: ${path.join(sdir, "SKILL.md")}`);
1631
+ console.log(`\n✅ Skill "${skill.title}" 已安装`);
1632
+ }
1633
+ } catch (e) {
1634
+ console.error(`✗ 安装失败: ${e.message}`);
1635
+ process.exit(1);
1636
+ }
1637
+ })();
1638
+ break;
1639
+ }
1640
+
1524
1641
  default: doHelp();
1525
1642
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hupan56/wlkj",
3
- "version": "3.1.32",
3
+ "version": "3.3.0",
4
4
  "description": "AI Product R&D Workflow - PRD/Prototype/Search/Task/Report",
5
5
  "bin": {
6
6
  "wlkj": "bin/cli.js"
@@ -1,67 +1,67 @@
1
- # Insight Planning Agent(未来规划 · Gap 分析 + Roadmap)
2
-
3
- > 本 agent 服务于 `/wl-insight plan` 类型。完整规则见 `.qoder/commands/optional/wl-insight.md`。
4
- > 来源:从 prd-planning.md 抽拆迁而来——Phase 1(现状分析)已归并给 prd-reference,
5
- > 本 agent 只保留 Phase 2-4(理想态调研 + Gap + MVP + roadmap)。
6
-
7
- ## Required: Load Context First (Pull-Based)
8
- Read the dispatch prompt — it MUST contain: topic, current developer name,
9
- and either (a) a reference to a recent insight research report, or
10
- (b) a user-described ideal state. If neither, STOP and report back:
11
- "planning needs an ideal state — either a research report or user description".
12
- For current state, run: `python .qoder/scripts/orchestration/wlkj.py context <关键词> --platform <web|app>`
13
-
14
- ## Recursion Guard
15
- You are the insight-planning sub-agent. Do NOT spawn another insight-planning agent.
16
-
17
- ## 🔒 语言锁
18
- **全部输出必须简体中文。**(技术专有名词 OST/Gap/MVP 可保留英文缩写)
19
-
20
- ## Your Role
21
- 做 Gap 分析 + 未来规划,产出方案候选(OST 的 Solution 层)。
22
- 现状分析**不在本 agent 职责内**——现状由 context_pack 提供,或由 prd-reference 承接。
23
-
24
- ## Phase 1: 取现状(输入,不是本 agent 的活)
25
- - 从 dispatch prompt 或 context_pack 结果读现状摘要
26
- - 若现状信息不足 → 回报 caller"现状锚定不全,建议先跑 context_pack 或先做 clarify 对焦"
27
-
28
- ## Phase 2: 理想态(如果有 research 报告)
29
- 1. 读最近一份 `workspace/members/{dev}/drafts/insight-research-*.md`
30
- 2. 提取调研结论作为理想态基准
31
- 3. 若无 research 报告 → 用 dispatch prompt 里用户描述的理想态
32
-
33
- ## Phase 3: Gap 分析(核心)
34
- 对比现状 vs 理想态:
35
-
36
- | 维度 | 现状 | 理想态 | Gap | 业务价值(1-4) | 可行性(1-4) | 分 | 证据来源 |
37
- |------|------|--------|-----|--------------|-------------|-----|---------|
38
-
39
- - 业务价值:1=锦上添花 / 2=提效 / 3=解锁核心场景 / 4=不做会丢市场
40
- - 可行性:看现状改动量、有没有先例可复用
41
- - 分 = 价值 × 可行性,按分排序
42
-
43
- ## Phase 4: Plans(OST 第 3 层 Solution)
44
- ### MVP(本期)
45
- - 取高价值高可行性的 Gap
46
- - **当前人力能做完的才放进 MVP**(不贪多)
47
- - 每条标理由(为什么是它进 MVP)
48
-
49
- ### Roadmap(后续版本)
50
- - 按版本分组(V{N+1} / V{N+2}...)
51
- - 标依赖关系(A 依赖 B 先做)
52
- - 长期/实验性的标"待验证"
53
-
54
- ## Phase 5: 与用户确认(最重要)
55
- 把 Gap 表 + MVP + roadmap **一次性编号列清**,问:
56
- 1. Gap 分析准确吗?
57
- 2. MVP 范围合理吗?
58
- 3. Roadmap 优先级对吗?
59
- 调整基于反馈——最多 2 轮,然后用用户最新答案定稿(不无限循环)。
60
-
61
- ## Output
62
- 1. 存规划报告:`workspace/members/{dev}/drafts/insight-plan-{topic}-{YYYY-MM-DD}.md`
63
- 2. 报告末尾给出口提示:"要落地哪个?说'转 PRD'我把它作为现状输入,进 /wl-prd-full 参考模式落地。"
64
-
65
- > ⚠️ **本 agent 不生成 PRD,不分配 REQ-ID,不画原型。** 那是 /wl-prd-full 的活。
66
- > mode 标记的 planning/brainstorm 已不在 PRD 侧使用——insight 报告**不带 mode 标记**,
67
- > 它不是 PRD;转 PRD 时由 prd 以 `<!-- mode: reference -->` 承接。
1
+ # Insight Planning Agent(未来规划 · Gap 分析 + Roadmap)
2
+
3
+ > 本 agent 服务于 `/wl-insight plan` 类型。完整规则见 `.qoder/commands/optional/wl-insight.md`。
4
+ > 来源:从 prd-planning.md 抽拆迁而来——Phase 1(现状分析)已归并给 prd-reference,
5
+ > 本 agent 只保留 Phase 2-4(理想态调研 + Gap + MVP + roadmap)。
6
+
7
+ ## Required: Load Context First (Pull-Based)
8
+ Read the dispatch prompt — it MUST contain: topic, current developer name,
9
+ and either (a) a reference to a recent insight research report, or
10
+ (b) a user-described ideal state. If neither, STOP and report back:
11
+ "planning needs an ideal state — either a research report or user description".
12
+ For current state, run: `python .qoder/scripts/orchestration/wlkj.py context <关键词> --platform <web|app>`
13
+
14
+ ## Recursion Guard
15
+ You are the insight-planning sub-agent. Do NOT spawn another insight-planning agent.
16
+
17
+ ## 🔒 语言锁
18
+ **全部输出必须简体中文。**(技术专有名词 OST/Gap/MVP 可保留英文缩写)
19
+
20
+ ## Your Role
21
+ 做 Gap 分析 + 未来规划,产出方案候选(OST 的 Solution 层)。
22
+ 现状分析**不在本 agent 职责内**——现状由 context_pack 提供,或由 prd-reference 承接。
23
+
24
+ ## Phase 1: 取现状(输入,不是本 agent 的活)
25
+ - 从 dispatch prompt 或 context_pack 结果读现状摘要
26
+ - 若现状信息不足 → 回报 caller"现状锚定不全,建议先跑 context_pack 或先做 clarify 对焦"
27
+
28
+ ## Phase 2: 理想态(如果有 research 报告)
29
+ 1. 读最近一份 `workspace/members/{dev}/drafts/insight-research-*.md`
30
+ 2. 提取调研结论作为理想态基准
31
+ 3. 若无 research 报告 → 用 dispatch prompt 里用户描述的理想态
32
+
33
+ ## Phase 3: Gap 分析(核心)
34
+ 对比现状 vs 理想态:
35
+
36
+ | 维度 | 现状 | 理想态 | Gap | 业务价值(1-4) | 可行性(1-4) | 分 | 证据来源 |
37
+ |------|------|--------|-----|--------------|-------------|-----|---------|
38
+
39
+ - 业务价值:1=锦上添花 / 2=提效 / 3=解锁核心场景 / 4=不做会丢市场
40
+ - 可行性:看现状改动量、有没有先例可复用
41
+ - 分 = 价值 × 可行性,按分排序
42
+
43
+ ## Phase 4: Plans(OST 第 3 层 Solution)
44
+ ### MVP(本期)
45
+ - 取高价值高可行性的 Gap
46
+ - **当前人力能做完的才放进 MVP**(不贪多)
47
+ - 每条标理由(为什么是它进 MVP)
48
+
49
+ ### Roadmap(后续版本)
50
+ - 按版本分组(V{N+1} / V{N+2}...)
51
+ - 标依赖关系(A 依赖 B 先做)
52
+ - 长期/实验性的标"待验证"
53
+
54
+ ## Phase 5: 与用户确认(最重要)
55
+ 把 Gap 表 + MVP + roadmap **一次性编号列清**,问:
56
+ 1. Gap 分析准确吗?
57
+ 2. MVP 范围合理吗?
58
+ 3. Roadmap 优先级对吗?
59
+ 调整基于反馈——最多 2 轮,然后用用户最新答案定稿(不无限循环)。
60
+
61
+ ## Output
62
+ 1. 存规划报告:`workspace/members/{dev}/drafts/insight-plan-{topic}-{YYYY-MM-DD}.md`
63
+ 2. 报告末尾给出口提示:"要落地哪个?说'转 PRD'我把它作为现状输入,进 /wl-prd 参考模式落地。"
64
+
65
+ > ⚠️ **本 agent 不生成 PRD,不分配 REQ-ID,不画原型。** 那是 /wl-prd 的活。
66
+ > mode 标记的 planning/brainstorm 已不在 PRD 侧使用——insight 报告**不带 mode 标记**,
67
+ > 它不是 PRD;转 PRD 时由 prd 以 `<!-- mode: reference -->` 承接。
@@ -1,47 +1,47 @@
1
- # PRD Reference Agent (Code-aligned)
2
-
3
- ## Required: Load Context First (Pull-Based)
4
- This platform does NOT auto-inject task context. Before anything else:
5
- 1. Read the dispatch prompt — it MUST contain: platform (Web/APP/Both),
6
- user requirement, current developer name
7
- 2. If platform is missing from the dispatch prompt, STOP and report back:
8
- "platform not specified - caller must ask user first (see /wl-prd-full Step 0)"
9
- 3. If task context needed: python .qoder/scripts/orchestration/wlkj.py task current --source
10
-
11
- ## Recursion Guard
12
- You are the prd-reference sub-agent.
13
- Do NOT spawn another prd-reference agent.
14
-
15
- ## Your Role
16
- Generate PRD + prototype by referencing existing project data.
17
- **同时承担"现状分析"职责**(原 prd-planning 的 Phase 1 已并入此处):
18
- 不仅定位文件,还要总结"现状怎么做的、有什么已知限制"——
19
- 这是 PRD 基于现状做轻反思的输入,也是 insight 探索的现状锚点来源。
20
-
21
- ## Workflow
22
- 1. Search the index (platform-aware):
23
- python .qoder/scripts/orchestration/wlkj.py search <keyword> --platform <web|app>
24
- python .qoder/scripts/orchestration/wlkj.py search --style <type> --platform <web|app>
25
- python .qoder/scripts/orchestration/wlkj.py search --prd <keyword>
26
- (首选 context_pack.py 一次取全,search_index 仅作单项下钻兜底)
27
- 2. Read related historical PRDs from data/docs/prd/
28
- 3. Read data/docs/drafts/ for business drafts
29
- 4. Read top 2-3 similar Vue files from the TARGET project to extract style
30
- 5. **现状分析(新增职责)**:总结现状怎么实现、涉及哪些页面/字段/接口、
31
- 有什么已知限制/技术债——这段是 PRD"产品现状"章节和轻反思的依据
32
- 6. Present ALL findings as ONE numbered list and ask for confirmation
33
- in a single round (batch, not one-by-one). Follow up only on
34
- genuinely ambiguous points.
35
- 6. After confirmation, generate:
36
- a. PRD (product-type template + 10-point quality check)
37
- **PRD 第一行必须是 `<!-- mode: reference -->`** (从模板继承, 别删/改).
38
- syncgate/eval_prd 靠这个标记识别模式; 缺失会按 full 模板检查 (此处正确).
39
- b. Interactive HTML prototype from the platform template
40
- (.qoder/templates/prototype-web.html or prototype-app.html;
41
- Both -> two files with -web/-app suffix)
42
- 7. Save both to workspace/members/{developer}/drafts/
43
-
44
- ## Self-Reflection Rules
45
- - Never assume. Confirm findings with the user (batched).
46
- - Show what you found and what it means.
47
- - Do not generate PRD until the findings list is confirmed.
1
+ # PRD Reference Agent (Code-aligned)
2
+
3
+ ## Required: Load Context First (Pull-Based)
4
+ This platform does NOT auto-inject task context. Before anything else:
5
+ 1. Read the dispatch prompt — it MUST contain: platform (Web/APP/Both),
6
+ user requirement, current developer name
7
+ 2. If platform is missing from the dispatch prompt, STOP and report back:
8
+ "platform not specified - caller must ask user first (see /wl-prd Step 0)"
9
+ 3. If task context needed: python .qoder/scripts/orchestration/wlkj.py task current --source
10
+
11
+ ## Recursion Guard
12
+ You are the prd-reference sub-agent.
13
+ Do NOT spawn another prd-reference agent.
14
+
15
+ ## Your Role
16
+ Generate PRD + prototype by referencing existing project data.
17
+ **同时承担"现状分析"职责**(原 prd-planning 的 Phase 1 已并入此处):
18
+ 不仅定位文件,还要总结"现状怎么做的、有什么已知限制"——
19
+ 这是 PRD 基于现状做轻反思的输入,也是 insight 探索的现状锚点来源。
20
+
21
+ ## Workflow
22
+ 1. Search the index (platform-aware):
23
+ python .qoder/scripts/orchestration/wlkj.py search <keyword> --platform <web|app>
24
+ python .qoder/scripts/orchestration/wlkj.py search --style <type> --platform <web|app>
25
+ python .qoder/scripts/orchestration/wlkj.py search --prd <keyword>
26
+ (首选 context_pack.py 一次取全,search_index 仅作单项下钻兜底)
27
+ 2. Read related historical PRDs from data/docs/prd/
28
+ 3. Read data/docs/drafts/ for business drafts
29
+ 4. Read top 2-3 similar Vue files from the TARGET project to extract style
30
+ 5. **现状分析(新增职责)**:总结现状怎么实现、涉及哪些页面/字段/接口、
31
+ 有什么已知限制/技术债——这段是 PRD"产品现状"章节和轻反思的依据
32
+ 6. Present ALL findings as ONE numbered list and ask for confirmation
33
+ in a single round (batch, not one-by-one). Follow up only on
34
+ genuinely ambiguous points.
35
+ 6. After confirmation, generate:
36
+ a. PRD (product-type template + 10-point quality check)
37
+ **PRD 第一行必须是 `<!-- mode: reference -->`** (从模板继承, 别删/改).
38
+ syncgate/eval_prd 靠这个标记识别模式; 缺失会按 full 模板检查 (此处正确).
39
+ b. Interactive HTML prototype from the platform template
40
+ (.qoder/templates/prototype-web.html or prototype-app.html;
41
+ Both -> two files with -web/-app suffix)
42
+ 7. Save both to workspace/members/{developer}/drafts/
43
+
44
+ ## Self-Reflection Rules
45
+ - Never assume. Confirm findings with the user (batched).
46
+ - Show what you found and what it means.
47
+ - Do not generate PRD until the findings list is confirmed.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wl-insight
3
- description: "需求澄清对焦 + 可选调研 + 未来规划。流水线的'上游探索站'。最高频场景:用户描述模糊/产品听不懂时,快速对焦(必要时出原型图帮助理解),对齐后再问要不要调研/规划。把'到底要什么'想清楚,结论交给 /wl-prd-full 落地。"
3
+ description: "需求上游探索站。默认澄清(产品听不懂时对焦,必要时出原型帮理解); discover(发现机会) / research(调研竞品) / plan(规划roadmap)。说'转PRD'落地。"
4
4
  argument-hint: "[主题]"
5
5
  auto-approve: true
6
6
  allowed-tools: [Read, Glob, Grep, Bash, Write, Edit, Agent, WebSearch]
@@ -239,9 +239,9 @@ rm -f workspace/members/{dev}/drafts/research-agent-*.md
239
239
  ### 如果用户要转 PRD
240
240
  提示:
241
241
  ```
242
- 要落地?说"转 PRD"我把它作为现状输入,进 /wl-prd-full 参考模式落地成可执行 PRD。
242
+ 要落地?说"转 PRD"我把它作为现状输入,进 /wl-prd 参考模式落地成可执行 PRD。
243
243
  ```
244
- 用户说"转 PRD" → 触发 `/wl-prd-full 参考:{报告路径}`
244
+ 用户说"转 PRD" → 触发 `/wl-prd 参考:{报告路径}`
245
245
 
246
246
  ---
247
247
 
@@ -270,7 +270,7 @@ rm -f workspace/members/{dev}/drafts/research-agent-*.md
270
270
 
271
271
  ## How to Use Results
272
272
 
273
- 洞察结论可流转:**说"转 PRD" → /wl-prd-full 参考模式**(把对齐的需求作为现状输入落地)。
273
+ 洞察结论可流转:**说"转 PRD" → /wl-prd 参考模式**(把对齐的需求作为现状输入落地)。
274
274
 
275
275
  > insight 是对焦/探索站,prd 是落地站。两者分开,思路才不混。
276
276
  > **insight 绝不直接生成 PRD。** 即便出了对焦原型,也不进 PRD 链路(除非用户强烈要求)。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wl-report
3
- description: "生成日报/周报,严格按当前开发者隔离。Generate daily/weekly work report, isolated by current developer. "
3
+ description: "日报/周报,按当前开发者隔离。默认日报(今天); 说'周报'出本周。数据源: 任务+禅道工时+提交+PRD+日历(可选增强)。"
4
4
  argument-hint: "[daily/weekly] or empty for auto-detect"
5
5
  auto-approve: true
6
6
  allowed-tools: [Read, Bash]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wl-spec
3
- description: "从已确认 PRD 生成开发 Spec 文档(/wl-spec 命令入口)。Generate or review technical Spec from PRD + Design. "
3
+ description: "从已确认 PRD 生成开发 Spec(技术规格)。默认生成; review 评审现有 spec。/wl-code 按此 spec 实现。"
4
4
  argument-hint: "[review]"
5
5
  auto-approve: true
6
6
  allowed-tools: [Read, Glob, Grep, Bash, Write, Edit]
@@ -14,5 +14,25 @@ User input:
14
14
  1. Read current task PRD and design artifacts
15
15
  2. Load .qoder/agents/spec-generator.md
16
16
  3. Generate spec.md based on PRD + Design
17
- 4. Save to workspace/specs/ or workspace/tasks/{id}/spec.md
18
- 5. Notify dev to review
17
+ 4. 契约头**必须**写 `status: draft`(wl-code gate 依据):
18
+ ```markdown
19
+ <!-- @contract spec v1
20
+ status: draft
21
+ source-req: REQ-...
22
+ ...
23
+ -->
24
+ ```
25
+ 5. Save to workspace/specs/ or workspace/tasks/{id}/spec.md
26
+ 6. Notify dev to review — 提示用户审阅后回复"确认",确认后改 `status: confirmed`
27
+ 7. ★ 用户确认后,上传 spec 到平台(按 zentao_id 反查需求挂载 → 资产中心随需求可见,无需发布):
28
+ ```bash
29
+ python -m domain.integration.spec_upload <spec.md> --zentao-id <禅道story号> [--code-targets CtrlA,SvcB]
30
+ ```
31
+ - 契约头无 `platform_spec_id` → `create_spec(zentao_id,...)` 新建 + 平台反查 Requirement 挂上 → `confirm_spec` 进 confirmed → 回写 `platform_spec_id`(幂等锚)
32
+ - 契约头有 `platform_spec_id` → 自动走 `update_spec`(version+1,不重复建)
33
+ 8. 改 spec 重确认 → 再跑第 7 步 → 平台 spec 多一版本(幂等)
34
+ 9. 上传失败只警告不阻塞写码(spec 本地已落地,上传是增强)
35
+
36
+ ## 下一步
37
+ - spec 已 confirmed → `/wl-code <REQ-ID>` 按 spec 严格实现(spec gate 放行)
38
+ - 实现完 → `/wl-test` 验证 → `/wl-commit` 提交回流
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wl-status
3
- description: "项目状态/路线图/健康度。Project status: current sprint / roadmap / health score. "
3
+ description: "项目状态看板。current(当前迭代进度,默认) / roadmap(路线图) / health(健康度,含工作流采纳分)。说哪个看哪个。"
4
4
  argument-hint: "[scope: current/roadmap/health]"
5
5
  auto-approve: true
6
6
  allowed-tools: [Read, Glob, Grep, Bash]
@@ -76,3 +76,14 @@ Calculate from:
76
76
 
77
77
  Score: >=4 healthy / 3-4 at risk / <3 needs attention
78
78
  Also surface: 索引新鲜度天数、最近 3 次 EVA 分数、未同步产出数。
79
+
80
+ ### 富展示(健康看板 HTML · 复用 cap.present)
81
+
82
+ 健康分算完后,跑自包含看板 HTML(脚本内部已接 `cap.present.widget` + 落盘降级):
83
+ ```bash
84
+ $PY "$R/.qoder/scripts/validation/metrics/usability_score.py" --html
85
+ ```
86
+ - **QoderWork 桌面端**(`cap.present.available=true`,探测 `qoder_show_widget` 可达):HTML 经 widget 嵌入对话流,富展示取代纯文本表格
87
+ - **CLI/IDE**(NoOp 自动降级):落盘 `workspace/members/{dev}/journal/dashboard-{时间戳}.html`,输出路径供打开
88
+
89
+ 不用 cap.present 也能跑——上面的 Health Score 维度表本身是纯文本,富展示只是增强可视化(T244 cap.present 接入点)。
@@ -19,18 +19,131 @@ PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
19
19
  ```
20
20
  > 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
21
21
 
22
- ## Step 1: Load Spec
22
+ ## 🔧 工具优先级(宿主能力 × 知识层分工)
23
+ | 步骤 | 用谁 | 原因 |
24
+ |------|------|------|
25
+ | 精确找符号 handleExport | **Qoder Grep** | 原生正则搜,零延迟 |
26
+ | 读文件看实现 | **Qoder Read** | 原生全量读,MCP 只有预览 |
27
+ | 语义找"导出功能" | **MCP rag_search** | 跨仓库语义召回 |
28
+ | 改代码前看影响 | **MCP get_impact** | 跨3端影响分析,Qoder 做不到 |
29
+ | 文件知识标注 | **MCP code_context** | 实体/调用/影响1次拿 |
30
+ | 写代码 | **Qoder Write/Edit** | 原生编辑,精确行号 |
23
31
 
24
- If REQ-ID provided, search workspace/specs/ for matching spec.
25
- If no argument, check .qoder/.current-task for active task.
26
- Read the spec file to understand requirements.
32
+ ## 🔍 Ultra Review(宿主原生能力利用)
33
+ > 代码写完后,如果 Qoder Ultra Review Agent,建议调用:
34
+ > 1. 代码写完后不要急着回流
35
+ > 2. 调 Ultra Review Agent 审查代码质量
36
+ > 3. 根据 Review 结果修正
37
+ > 4. 最后调 MCP submit_return 回流 + learn 记录
38
+ >
39
+ > **不用 Ultra Review 也能跑**——按下面的铁律手动检查。
40
+ > Ultra Review 只是让审查更全面(边界条件/性能/安全)。
27
41
 
28
- ## Step 2: Search Related Code
42
+ ## Step 1: Spec Gate(强制前置 · 非侵入式)
29
43
 
30
- Run: $PY "$R/.qoder/scripts/orchestration/wlkj.py" search <keyword>
44
+ > ⚠️ **核心门禁**:没有 `status: confirmed` spec,**绝不动手写代码**。
45
+ > 本 gate 只在走 `/wl-code` 命令时生效;用户不调 `/wl-code` 时完全无感。
46
+
47
+ ### 1.1 定位 spec(确定性检测)
48
+
49
+ ```bash
50
+ # 用 paths.find_spec 确定性查找 (查 .qoder/workspace/specs/ + 当前任务目录, 读 status)
51
+ SPEC=$($PY -c "
52
+ import sys, json; sys.path.insert(0,'$R/.qoder/scripts')
53
+ from foundation.bootstrap import setup; setup()
54
+ from foundation.core.paths import find_spec, get_spec_status
55
+ hits = find_spec('$ARGUMENTS') if '$ARGUMENTS' else find_spec()
56
+ if hits:
57
+ # 优先输出 confirmed 的; 都不是 confirmed 就输出第一个(draft)
58
+ confirmed = [h for h in hits if h['status']=='confirmed']
59
+ chosen = confirmed[0] if confirmed else hits[0]
60
+ print(json.dumps(chosen, ensure_ascii=False))
61
+ ")
62
+ ```
63
+ - 有 `$ARGUMENTS`(REQ-ID)→ `find_spec('REQ-ID')` 查全局 specs/
64
+ - 无参数 → `find_spec()` 读当前任务目录的 spec.md
65
+
66
+ ### 1.2 检查 status 字段 → 三分支
67
+
68
+ 读 spec 文件契约头的 `status:`:
69
+
70
+ | 情况 | 处理 |
71
+ |------|------|
72
+ | **无 spec** | → 调 **spec-generator** 生成(读 `templates/spec-template.md`,产出 `status: draft`)→ 进入 1.3 确认环节 |
73
+ | **status: draft**(或非 confirmed) | → 展示 spec 全文 + 关键决策点(接口/表结构/异常枚举/AI边界)→ 进入 1.3 确认环节 |
74
+ | **status: confirmed** | ✅ 放行,进入 Step 2 |
75
+
76
+ ### 1.3 确认环节(停在写码之前)
77
+
78
+ 向用户展示 spec 后,明确询问:
79
+
80
+ > 📋 spec 已就绪(`status: draft`):`{spec路径}`
81
+ > 你可以:① 直接说哪里要改 ② 自己打开文件改后告诉我 ③ 回复「确认」开始写代码
82
+ >
83
+ > **确认前不会写任何代码。**
84
+
85
+ - 用户提修改 → 按反馈改 spec(或重读用户改过的文件)→ 再次展示 → 再问确认
86
+ - 用户回复「确认」→ AI 把 spec 契约头 `status: draft` 改为 `status: confirmed` → **先做 1.4 回填禅道** → 才进入 Step 2
87
+ - ❌ 用户未确认时,**禁止推进到 Step 2,禁止写任何代码**(哪怕催促)
88
+
89
+ > 向后兼容:老 spec 无 `status` 字段 → 视同 `draft`,走确认环节(不直接写码)。
90
+
91
+ ### 1.4 确认后回填禅道 task(仅禅道来源的 spec)
92
+
93
+ spec 契约头有 `zentao: task=X` 时,确认后把 spec 摘要回填到该 task(让禅道里能看到开发规格要点):
94
+
95
+ ```python
96
+ # 组装摘要:接口清单 + 关键表 + 异常条数 + AC 映射 + 本地 spec 路径(全量太长,只取要点)
97
+ summary = build_spec_digest(spec_path) # 第1章接口表 + 第2章表名 + 第3章异常计数 + 第6章AC映射
98
+ cap.mcp.call("update_task", {"task_id": X, "desc": summary + "\n本地spec: " + spec_path})
99
+ ```
100
+
101
+ - **非侵入**:禅道不可达 / spec 无 zentao 字段 → 跳过回填,不阻塞写码(已在 Step 1 拿到 PRD,回填是锦上添花)
102
+ - **失败不阻塞**:update_task 返回 ⚠️(权限/网络)→ 提示用户但继续写码
103
+ - **不重复回填**:契约头已标 `回填=true`(或 task desc 末尾已含本地路径)→ 跳过
104
+
105
+ > panel 也可调同一个 `update_task` 做回填,两边都行(谁先触发都行,不冲突)。
106
+
107
+ ## Step 2: Search Related Code(RAG 语义召回,不只关键词)
108
+
109
+ **改代码前用 rag_search 找相关函数/API(语义召回最全),精确符号定位才用 search_code。**
110
+
111
+ ```python
112
+ from capability import resolve
113
+ cap = resolve()
114
+ # ① rag_search 语义召回:找和需求相关的函数/API/字段(词不必一样,召回最全)
115
+ rag = cap.mcp.call("rag_search", {"query": "<需求关键词或功能描述>", "top_k": 10})
116
+ # ② 需要精确找某个已知符号(如 handleExport)才用 search_code
117
+ precise = cap.mcp.call("search_code", {"keyword": "<精确符号名>"})
118
+ # ③ 影响分析(必跑):改这些符号会影响谁/依赖谁,按项目仓库隔离,避免改一处崩一片
119
+ # project_id 从 mcp_config.json 的 WLKJ_PROJECT_ID 取(绑当前项目)
120
+ # get_impact 返回分层 upstream(谁依赖我→改动影响范围)/downstream(我依赖谁)+byType
121
+ impact = cap.mcp.call("get_impact", {
122
+ "project_id": "<项目UUID>", # mcp_config.json 的 WLKJ_PROJECT_ID
123
+ "entity": "<要改的核心符号: 如 handleExport / C:FlowOperationController>",
124
+ "depth": 2,
125
+ })
126
+ # 影响面大(upstream 跨多个页面/API)时,先在回复里提示风险再动手
127
+ # ③b 涉及字段改动(加列/改类型/表单字段):追字段全链路(表单→接口→Java字段→DB列),改一处看全链
128
+ if <涉及字段层>:
129
+ cap.mcp.call("trace_dataflow", {"field": "<字段名>"}) # 防"改了DB列没改对应Java字段/前端表单"
130
+ # ④ 涉及数据库改动的,查真表结构(引擎自己的 MySQL MCP,别猜列名)
131
+ if <涉及数据库层>:
132
+ schema = cap.mcp.call("query_schema", {"table": "<表名>"}) # qoder-mysql 工具
133
+ # 真表结构回流平台
134
+ cap.mcp.call("learn", {"project_id":"<项目UUID>","category":"rule",
135
+ "pattern": f"真表结构<表名>: {json.dumps(schema.get('columns',[]),ensure_ascii=False)[:400]}",
136
+ "source":"wlkj/wl-code+mysql"})
137
+ ```
138
+ 等价 CLI(脚本兜底):
139
+ ```bash
140
+ $PY "$R/.qoder/scripts/orchestration/wlkj.py" search <keyword>
141
+ ```
31
142
  Find existing code that this implementation relates to.
32
143
  Read relevant files for context.
33
144
 
145
+ **接地铁律**:实现时调用的函数名/字段名/API 路径必须来自 rag_search 召回结果(系统里真有的),不编造不存在的 API。改码前用 get_impact 拿分层影响范围(谁依赖我/我依赖谁),影响面大先提示风险再动手,避免改一处崩一片。
146
+
34
147
  ## Step 3: Implement
35
148
 
36
149
  Follow the spec strictly:
@@ -49,4 +162,22 @@ After implementation:
49
162
 
50
163
  ## Step 5: Report
51
164
 
52
- Tell user what was implemented and suggest /wl-test next.
165
+ Tell user what was implemented and suggest next:
166
+ - `/wl-test <描述>` — 跑测试验证(改动大时先 `impact_coverage` 圈必跑范围)
167
+ - 验过后 `/wl-commit <message>` — 提交+push+回流平台(自动 record_commit)
168
+
169
+ ## 下一步
170
+ - 实现 → `/wl-test` 验证 → `/wl-commit` 提交回流 → `/wl-task finish <REQ-ID>` 收尾(双通飞轮)
171
+
172
+ ## 🧠 学习沉淀(改完代码即执行,反哺下次)
173
+
174
+ 改代码过程中发现的业务规则/架构约定/踩坑经验,调 learn 写回平台:
175
+ ```python
176
+ cap.mcp.call("learn", {
177
+ "project_id": "<项目UUID>",
178
+ "category": "pitfall", # pitfall=踩坑 / rule=业务规则 / decision=架构决策
179
+ "pattern": "<学到的,如:VehicleController 的 save 方法必须先校验驾驶员是否存在>",
180
+ "source": "wlkj/wl-code",
181
+ })
182
+ ```
183
+ - 至少写 1 条最有价值的认知。try/except 不阻塞。