@hupan56/wlkj 2.7.12 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/bin/cli.js +1435 -1107
  2. package/package.json +29 -29
  3. package/templates/qoder/agents/insight-planning.md +1 -1
  4. package/templates/qoder/agents/insight-research.md +28 -15
  5. package/templates/qoder/commands/optional/wl-insight.md +161 -161
  6. package/templates/qoder/commands/optional/wl-report.md +20 -39
  7. package/templates/qoder/commands/optional/wl-status.md +4 -4
  8. package/templates/qoder/commands/wl-code.md +2 -2
  9. package/templates/qoder/commands/wl-design.md +6 -6
  10. package/templates/qoder/commands/wl-init.md +3 -3
  11. package/templates/qoder/commands/wl-prd.md +26 -13
  12. package/templates/qoder/commands/wl-req.md +43 -0
  13. package/templates/qoder/commands/wl-search.md +78 -47
  14. package/templates/qoder/commands/wl-task.md +343 -40
  15. package/templates/qoder/commands/wl-test.md +43 -17
  16. package/templates/qoder/config.yaml +52 -14
  17. package/templates/qoder/hooks/post-tool-use.py +181 -0
  18. package/templates/qoder/hooks/session-start.py +94 -23
  19. package/templates/qoder/hooks/stop-eval.py +207 -0
  20. package/templates/qoder/hooks/user-prompt-submit.py +139 -0
  21. package/templates/qoder/rules/wl-pipeline.md +85 -49
  22. package/templates/qoder/scripts/README.md +102 -0
  23. package/templates/qoder/scripts/capability/__init__.py +26 -0
  24. package/templates/qoder/scripts/capability/__main__.py +72 -0
  25. package/templates/qoder/scripts/capability/adapters/__init__.py +29 -0
  26. package/templates/qoder/scripts/capability/adapters/cli.py +316 -0
  27. package/templates/qoder/scripts/capability/adapters/mcp.py +334 -0
  28. package/templates/qoder/scripts/capability/adapters/qw.py +271 -0
  29. package/templates/qoder/scripts/capability/caps/__init__.py +27 -0
  30. package/templates/qoder/scripts/capability/caps/context.py +36 -0
  31. package/templates/qoder/scripts/capability/caps/cron.py +50 -0
  32. package/templates/qoder/scripts/capability/caps/identity.py +43 -0
  33. package/templates/qoder/scripts/capability/caps/memory.py +71 -0
  34. package/templates/qoder/scripts/capability/caps/notify.py +41 -0
  35. package/templates/qoder/scripts/capability/caps/present.py +48 -0
  36. package/templates/qoder/scripts/capability/caps/repo.py +31 -0
  37. package/templates/qoder/scripts/capability/caps/sandbox.py +43 -0
  38. package/templates/qoder/scripts/capability/chain.py +92 -0
  39. package/templates/qoder/scripts/capability/memory_chain.py +41 -0
  40. package/templates/qoder/scripts/capability/registry.py +246 -0
  41. package/templates/qoder/scripts/capability/registry_mcp.py +250 -0
  42. package/templates/qoder/scripts/capability/smoke_test.py +211 -0
  43. package/templates/qoder/scripts/capability/smoke_test_report.json +94 -0
  44. package/templates/qoder/scripts/deployment/setup/__init__.py +11 -0
  45. package/templates/qoder/scripts/deployment/setup/carriers.py +669 -0
  46. package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
  47. package/templates/qoder/scripts/{init_doctor.py → deployment/setup/init_doctor.py} +100 -39
  48. package/templates/qoder/scripts/{install_qoderwork.py → deployment/setup/install_qoderwork.py} +48 -30
  49. package/templates/qoder/scripts/{platform_doctor.py → deployment/setup/platform_doctor.py} +271 -259
  50. package/templates/qoder/scripts/{repo_root.py → deployment/setup/repo_root.py} +9 -2
  51. package/templates/qoder/scripts/{setup.py → deployment/setup/setup.py} +143 -14
  52. package/templates/qoder/scripts/{setup_lanhu.py → deployment/setup/setup_lanhu.py} +979 -963
  53. package/templates/qoder/scripts/domain/design/__init__.py +0 -0
  54. package/templates/qoder/scripts/{fill_prototype.py → domain/design/fill_prototype.py} +17 -5
  55. package/templates/qoder/scripts/{gen_design_doc.py → domain/design/gen_design_doc.py} +406 -394
  56. package/templates/qoder/scripts/domain/kg/__init__.py +11 -0
  57. package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
  58. package/templates/qoder/scripts/domain/kg/build/build_entity_registry.py +201 -0
  59. package/templates/qoder/scripts/domain/kg/build/build_relations.py +132 -0
  60. package/templates/qoder/scripts/{build_style_index.py → domain/kg/build/build_style_index.py} +50 -15
  61. package/templates/qoder/scripts/domain/kg/build/build_workflows.py +149 -0
  62. package/templates/qoder/scripts/{kg_build.py → domain/kg/build/kg_build.py} +685 -612
  63. package/templates/qoder/scripts/{kg_build_db.py → domain/kg/build/kg_build_db.py} +338 -327
  64. package/templates/qoder/scripts/{kg_incremental.py → domain/kg/build/kg_incremental.py} +425 -393
  65. package/templates/qoder/scripts/{learn_aggregate.py → domain/kg/build/learn_aggregate.py} +212 -201
  66. package/templates/qoder/scripts/domain/kg/extract/__init__.py +0 -0
  67. package/templates/qoder/scripts/{common → domain/kg/extract}/extract.py +430 -419
  68. package/templates/qoder/scripts/domain/kg/extract/test_extract.py +115 -0
  69. package/templates/qoder/scripts/{common → domain/kg/extract}/ts_extract.py +614 -536
  70. package/templates/qoder/scripts/domain/kg/graph/__init__.py +0 -0
  71. package/templates/qoder/scripts/{kg_link_db.py → domain/kg/graph/kg_link_db.py} +235 -224
  72. package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
  73. package/templates/qoder/scripts/{kg.py → domain/kg/kg.py} +871 -708
  74. package/templates/qoder/scripts/domain/kg/kg_capabilities.py +182 -0
  75. package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
  76. package/templates/qoder/scripts/{context_pack.py → domain/kg/search/context_pack.py} +45 -17
  77. package/templates/qoder/scripts/{enrich_prompt.py → domain/kg/search/enrich_prompt.py} +238 -226
  78. package/templates/qoder/scripts/domain/kg/search/prefetch.py +384 -0
  79. package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
  80. package/templates/qoder/scripts/{search_index.py → domain/kg/search/search_index.py} +210 -88
  81. package/templates/qoder/scripts/domain/kg/server/__init__.py +0 -0
  82. package/templates/qoder/scripts/domain/kg/server/kgd.py +549 -0
  83. package/templates/qoder/scripts/domain/kg/server/perf_bench.py +197 -0
  84. package/templates/qoder/scripts/domain/kg/storage/__init__.py +0 -0
  85. package/templates/qoder/scripts/{kg_duckdb.py → domain/kg/storage/kg_duckdb.py} +70 -45
  86. package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
  87. package/templates/qoder/scripts/{learn.py → domain/learning/learn.py} +157 -146
  88. package/templates/qoder/scripts/domain/report/__init__.py +11 -0
  89. package/templates/qoder/scripts/{add_session.py → domain/report/add_session.py} +256 -244
  90. package/templates/qoder/scripts/{export.py → domain/report/export.py} +72 -4
  91. package/templates/qoder/scripts/{report.py → domain/report/report.py} +292 -281
  92. package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
  93. package/templates/qoder/scripts/domain/report/role.py +39 -0
  94. package/templates/qoder/scripts/{status.py → domain/report/status.py} +737 -628
  95. package/templates/qoder/scripts/domain/report/status_snapshot.py +191 -0
  96. package/templates/qoder/scripts/domain/requirement/__init__.py +0 -0
  97. package/templates/qoder/scripts/{archive_prd.py → domain/requirement/archive_prd.py} +389 -377
  98. package/templates/qoder/scripts/domain/requirement/req.py +228 -0
  99. package/templates/qoder/scripts/domain/task/__init__.py +11 -0
  100. package/templates/qoder/scripts/{git_sync.py → domain/task/git_sync.py} +90 -50
  101. package/templates/qoder/scripts/{syncgate.py → domain/task/syncgate.py} +18 -7
  102. package/templates/qoder/scripts/domain/task/task.py +229 -0
  103. package/templates/qoder/scripts/domain/task/task_lifecycle.py +606 -0
  104. package/templates/qoder/scripts/domain/task/task_query.py +162 -0
  105. package/templates/qoder/scripts/domain/task/task_relations.py +425 -0
  106. package/templates/qoder/scripts/{team_sync.py → domain/task/team_sync.py} +101 -23
  107. package/templates/qoder/scripts/domain/task/zentao_sync.py +370 -0
  108. package/templates/qoder/scripts/foundation/__init__.py +0 -0
  109. package/templates/qoder/scripts/foundation/bootstrap.py +145 -0
  110. package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
  111. package/templates/qoder/scripts/foundation/core/cmd_registry.py +112 -0
  112. package/templates/qoder/scripts/foundation/core/config.py +187 -0
  113. package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -400
  114. package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
  115. package/templates/qoder/scripts/foundation/data/contract.py +317 -0
  116. package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
  117. package/templates/qoder/scripts/foundation/data/result.py +223 -0
  118. package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -392
  119. package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
  120. package/templates/qoder/scripts/foundation/identity/check_publish.py +103 -0
  121. package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -238
  122. package/templates/qoder/scripts/foundation/identity/guard.py +159 -0
  123. package/templates/qoder/scripts/{common → foundation/identity}/identity.py +132 -9
  124. package/templates/qoder/scripts/foundation/identity/roles.py +60 -0
  125. package/templates/qoder/scripts/foundation/integrations/__init__.py +0 -0
  126. package/templates/qoder/scripts/{common → foundation/integrations}/active_task.py +30 -15
  127. package/templates/qoder/scripts/{common → foundation/integrations}/feishu.py +11 -10
  128. package/templates/qoder/scripts/{common → foundation/integrations}/terms.py +3 -3
  129. package/templates/qoder/scripts/foundation/integrations/zentao_client.py +220 -0
  130. package/templates/qoder/scripts/foundation/io/__init__.py +0 -0
  131. package/templates/qoder/scripts/{common → foundation/io}/filelock.py +1 -1
  132. package/templates/qoder/scripts/{common → foundation/io}/reqid.py +1 -1
  133. package/templates/qoder/scripts/foundation/protocol/__init__.py +0 -0
  134. package/templates/qoder/scripts/foundation/protocol/duckdb_conn.py +39 -0
  135. package/templates/qoder/scripts/foundation/protocol/mcp_base.py +268 -0
  136. package/templates/qoder/scripts/foundation/utils/__init__.py +0 -0
  137. package/templates/qoder/scripts/{common → foundation/utils}/eval_api.py +12 -1
  138. package/templates/qoder/scripts/{common → foundation/utils}/pip_install.py +23 -6
  139. package/templates/qoder/scripts/{common → foundation/utils}/platform_guard.py +1 -1
  140. package/templates/qoder/scripts/orchestration/__init__.py +0 -0
  141. package/templates/qoder/scripts/orchestration/wlkj.py +185 -0
  142. package/templates/qoder/scripts/protocol/__init__.py +0 -0
  143. package/templates/qoder/scripts/protocol/browser/README.md +207 -0
  144. package/templates/qoder/scripts/protocol/browser/SKILL.md +265 -0
  145. package/templates/qoder/scripts/protocol/browser/config.env +9 -0
  146. package/templates/qoder/scripts/protocol/browser/references/cdp-api.md +110 -0
  147. package/templates/qoder/scripts/protocol/browser/references/migration-2.5.3.md +72 -0
  148. package/templates/qoder/scripts/protocol/browser/references/site-patterns/.gitkeep +0 -0
  149. package/templates/qoder/scripts/protocol/browser/scripts/browser-discovery.mjs +138 -0
  150. package/templates/qoder/scripts/protocol/browser/scripts/cdp-proxy.mjs +672 -0
  151. package/templates/qoder/scripts/protocol/browser/scripts/check-deps.mjs +206 -0
  152. package/templates/qoder/scripts/protocol/browser/scripts/find-url.mjs +253 -0
  153. package/templates/qoder/scripts/protocol/browser/scripts/match-site.mjs +46 -0
  154. package/templates/qoder/scripts/protocol/browser/templates/config.env.template +9 -0
  155. package/templates/qoder/scripts/protocol/mcp/__init__.py +11 -0
  156. package/templates/qoder/scripts/protocol/mcp/kg_mcp_server.py +478 -0
  157. package/templates/qoder/scripts/{lanhu_stdio_wrapper.py → protocol/mcp/lanhu_stdio_wrapper.py} +131 -119
  158. package/templates/qoder/scripts/protocol/mcp/mcp_doctor.py +548 -0
  159. package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
  160. package/templates/qoder/scripts/protocol/mcp/mysql_mcp_server.py +461 -0
  161. package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +1920 -0
  162. package/templates/qoder/scripts/protocol/transports/__init__.py +56 -0
  163. package/templates/qoder/scripts/protocol/transports/base.py +87 -0
  164. package/templates/qoder/scripts/protocol/transports/cli.py +132 -0
  165. package/templates/qoder/scripts/protocol/transports/http.py +141 -0
  166. package/templates/qoder/scripts/protocol/transports/stdio.py +293 -0
  167. package/templates/qoder/scripts/run_weekly_update.bat +27 -18
  168. package/templates/qoder/scripts/run_weekly_update.sh +22 -13
  169. package/templates/qoder/scripts/validation/__init__.py +0 -0
  170. package/templates/qoder/scripts/validation/eval/__init__.py +0 -0
  171. package/templates/qoder/scripts/validation/eval/perf-report-2026-06-24.md +139 -0
  172. package/templates/qoder/scripts/validation/eval/qwork_harness.py +617 -0
  173. package/templates/qoder/scripts/validation/eval/report-commands.md +220 -0
  174. package/templates/qoder/scripts/validation/eval/transcript_timing.py +386 -0
  175. package/templates/qoder/scripts/validation/metrics/__init__.py +0 -0
  176. package/templates/qoder/scripts/{eval_prd.py → validation/metrics/eval_prd.py} +84 -15
  177. package/templates/qoder/scripts/validation/metrics/usability_score.py +750 -0
  178. package/templates/qoder/scripts/validation/test/__init__.py +11 -0
  179. package/templates/qoder/scripts/validation/test/assertion_gen.py +551 -0
  180. package/templates/qoder/scripts/{autotest.py → validation/test/autotest.py} +1234 -1751
  181. package/templates/qoder/scripts/validation/test/autotest_auth.py +109 -0
  182. package/templates/qoder/scripts/{autotest_batch.py → validation/test/autotest_batch.py} +255 -224
  183. package/templates/qoder/scripts/validation/test/autotest_data.py +680 -0
  184. package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
  185. package/templates/qoder/scripts/{autotest_run.py → validation/test/autotest_run.py} +323 -297
  186. package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
  187. package/templates/qoder/scripts/{benchmark.py → validation/test/benchmark.py} +17 -5
  188. package/templates/qoder/scripts/{kg_auto_login.py → validation/test/kg_auto_login.py} +208 -196
  189. package/templates/qoder/scripts/{kg_test_runner.py → validation/test/kg_test_runner.py} +13 -2
  190. package/templates/qoder/scripts/{page_probe.py → validation/test/page_probe.py} +470 -459
  191. package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
  192. package/templates/qoder/settings.json +23 -2
  193. package/templates/qoder/skills/design-import/SKILL.md +235 -226
  194. package/templates/qoder/skills/design-review/SKILL.md +91 -82
  195. package/templates/qoder/skills/prd-generator/SKILL.md +38 -24
  196. package/templates/qoder/skills/prd-review/SKILL.md +8 -6
  197. package/templates/qoder/skills/prototype-generator/SKILL.md +296 -247
  198. package/templates/qoder/skills/spec-coder/SKILL.md +24 -15
  199. package/templates/qoder/skills/spec-generator/SKILL.md +24 -12
  200. package/templates/qoder/skills/test-generator/SKILL.md +9 -7
  201. package/templates/qoder/skills/wl-code/SKILL.md +25 -13
  202. package/templates/qoder/skills/wl-commit/SKILL.md +10 -9
  203. package/templates/qoder/skills/wl-design/SKILL.md +7 -5
  204. package/templates/qoder/skills/wl-init/SKILL.md +8 -8
  205. package/templates/qoder/skills/wl-insight/SKILL.md +25 -12
  206. package/templates/qoder/skills/wl-prd-full/SKILL.md +59 -8
  207. package/templates/qoder/skills/wl-prd-quick/SKILL.md +7 -7
  208. package/templates/qoder/skills/wl-prd-review/SKILL.md +18 -6
  209. package/templates/qoder/skills/wl-report/SKILL.md +27 -25
  210. package/templates/qoder/skills/wl-search/SKILL.md +151 -80
  211. package/templates/qoder/skills/wl-spec/SKILL.md +9 -7
  212. package/templates/qoder/skills/wl-status/SKILL.md +50 -18
  213. package/templates/qoder/skills/wl-task/SKILL.md +94 -12
  214. package/templates/qoder/skills/wl-test/SKILL.md +154 -45
  215. package/templates/qoder/templates/prd-full-template.md +7 -0
  216. package/templates/root/AGENTS.md +275 -237
  217. package/templates/root/requirements.txt +3 -0
  218. package/templates/root//344/275/277/347/224/250/350/257/264/346/230/216.md +3 -3
  219. package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +2 -2
  220. package/templates/qoder/hooks/inject-workflow-state.py +0 -169
  221. package/templates/qoder/scripts/__pycache__/check_mcp_launch.cpython-39.pyc +0 -0
  222. package/templates/qoder/scripts/__pycache__/install_qoderwork.cpython-39.pyc +0 -0
  223. package/templates/qoder/scripts/__pycache__/mcp_launcher.cpython-39.pyc +0 -0
  224. package/templates/qoder/scripts/__pycache__/platform_doctor.cpython-39.pyc +0 -0
  225. package/templates/qoder/scripts/check_carriers.py +0 -238
  226. package/templates/qoder/scripts/check_mcp.py +0 -298
  227. package/templates/qoder/scripts/check_mcp_launch.py +0 -183
  228. package/templates/qoder/scripts/check_qoderwork_consistency.py +0 -166
  229. package/templates/qoder/scripts/collect_prds.py +0 -31
  230. package/templates/qoder/scripts/common/mentions.py +0 -134
  231. package/templates/qoder/scripts/common/utf8.py +0 -38
  232. package/templates/qoder/scripts/extract_api_params.py +0 -246
  233. package/templates/qoder/scripts/extract_routes.py +0 -54
  234. package/templates/qoder/scripts/extract_routes_tree.py +0 -78
  235. package/templates/qoder/scripts/handoff.py +0 -22
  236. package/templates/qoder/scripts/init_developer.py +0 -76
  237. package/templates/qoder/scripts/kg_mcp_server.py +0 -801
  238. package/templates/qoder/scripts/kg_semantic.py +0 -150
  239. package/templates/qoder/scripts/mcp_launcher.py +0 -414
  240. package/templates/qoder/scripts/mysql_mcp_server.py +0 -396
  241. package/templates/qoder/scripts/parse_prds.py +0 -33
  242. package/templates/qoder/scripts/role.py +0 -51
  243. package/templates/qoder/scripts/sync_carriers.py +0 -259
  244. package/templates/qoder/scripts/task.py +0 -1261
  245. package/templates/qoder/scripts/workspace_init.py +0 -102
  246. package/templates/qoder/scripts/zentao_mcp_server.py +0 -424
  247. package/templates/qoder/skills/prompt-enrich/SKILL.md +0 -90
  248. /package/templates/qoder/scripts/{common → deployment}/__init__.py +0 -0
  249. /package/templates/qoder/{skills/prototype-generator/SKILL.md.zcode-79180-2af4721f-f9a6-412c-88db-c0af680d211b.tmp → scripts/domain/__init__.py} +0 -0
  250. /package/templates/qoder/scripts/{common → domain/kg/graph}/graph_traverse.py +0 -0
  251. /package/templates/qoder/scripts/{common → domain/kg/server}/repowiki.py +0 -0
  252. /package/templates/qoder/scripts/{common → foundation/io}/atomicio.py +0 -0
  253. /package/templates/qoder/scripts/{secure-ls.js → validation/test/secure-ls.js} +0 -0
@@ -1,5 +1,17 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
+ # v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
4
+ import os as _o, sys as _s
5
+ _f = _o.path.abspath(__file__)
6
+ for _ in range(10):
7
+ _f = _o.path.dirname(_f)
8
+ _cp = _o.path.join(_f, 'foundation')
9
+ if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
10
+ break
11
+ if _cp not in _s.path: _s.path.insert(0, _cp)
12
+ from bootstrap import setup; setup()
13
+ from foundation.core.paths import get_repo_root
14
+
3
15
  """
4
16
  setup.py - 一键就绪 (小而美)
5
17
 
@@ -23,6 +35,7 @@ setup.py - 一键就绪 (小而美)
23
35
 
24
36
  import argparse
25
37
  import os
38
+ import shutil
26
39
  import subprocess
27
40
  import sys
28
41
  from pathlib import Path
@@ -34,7 +47,7 @@ except (AttributeError, TypeError, OSError):
34
47
  pass
35
48
 
36
49
  THIS_DIR = Path(__file__).resolve().parent
37
- BASE = THIS_DIR.parent.parent # repo root
50
+ BASE = get_repo_root()
38
51
 
39
52
 
40
53
  # ============================================================
@@ -420,10 +433,78 @@ def _write_team_remote_to_config(url):
420
433
  pass
421
434
 
422
435
 
436
+ def _detect_local_branch(base):
437
+ """探测当前本地分支名。unborn 分支 (git init 后没 commit) 时,
438
+ git rev-parse --abbrev-ref HEAD 会报 fatal (exit 128), 必须用 symbolic-ref。
439
+ 不同 git 版本默认分支是 master 或 main, 不能写死。"""
440
+ r = run(['git', 'symbolic-ref', '--short', 'HEAD'], cwd=str(base))
441
+ if r.returncode == 0 and r.stdout.strip():
442
+ return r.stdout.strip()
443
+ # 兜底 (理论上 symbolic-ref 不会失败, 但稳健起见)
444
+ r2 = run(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], cwd=str(base))
445
+ if r2.returncode == 0 and r2.stdout.strip() and r2.stdout.strip() != 'HEAD':
446
+ return r2.stdout.strip()
447
+ return 'master'
448
+
449
+
450
+ def _backup_local_data(base, remote_branch):
451
+ """reset --hard 会用远程覆盖整个工作树。开发者可能本地填了 config.yaml 的真实
452
+ mysql/feishu 密码但没 commit, 直接 reset 会吞掉这些数据。
453
+ 在 reset 前, 把"团队数据文件"里被本地修改过的内容备份到 .wlkj-pre-reset/,
454
+ reset 后提示用户: 这些是 reset 前的本地版本, 你可能需要把密码重新填回去。
455
+ 引擎文件 (gitignored) 不需要备份 — 反正由 update 重新生成。
456
+ 返回被备份的原始相对路径列表 (用 / 分隔, 与 cli.js JS 版一致)。
457
+ """
458
+ backup_dir = base / '.wlkj-pre-reset'
459
+ backed = []
460
+ # 只备份团队数据文件 (git 跟踪的关键数据), 不备份引擎。
461
+ # 用正斜杠统一, 避免跨平台路径分隔符不一致 (Windows os.path.join 用反斜杠)。
462
+ DATA_FILES = ['.qoder/config.yaml', '.qoder/config.toml', '.qoder/settings.json']
463
+ backup_dir.mkdir(parents=True, exist_ok=True)
464
+ try:
465
+ for rel in DATA_FILES:
466
+ local = base / rel
467
+ if not local.is_file():
468
+ continue
469
+ try:
470
+ lc = local.read_text(encoding='utf-8')
471
+ except Exception:
472
+ continue
473
+ # 拿远程版本对比
474
+ # 注意: MSYS2/Git Bash 会把 'origin/master:path' 里的 / 转成 \ →
475
+ # 变成 'origin\master;path' 报 ambiguous argument。
476
+ # 设 MSYS_NO_PATHCONV=1 禁用转换 (Windows 原生 cmd 不受影响)。
477
+ rshow = run(['git', 'show', f'origin/{remote_branch}:{rel}'],
478
+ cwd=str(base),
479
+ env={**os.environ, 'MSYS_NO_PATHCONV': '1',
480
+ 'MSYS2_ARG_CONV_EXCL': '*'})
481
+ remote_content = rshow.stdout if rshow.returncode == 0 else None
482
+ # 只在本地与远程不同 (或远程没有) 时备份
483
+ same = (remote_content is not None and remote_content.strip() == lc.strip())
484
+ if not same:
485
+ # 扁平化文件名: .qoder/config.yaml -> .qoder__config.yaml (跨平台)
486
+ flat = rel.replace('/', '__').replace('\\', '__')
487
+ target = backup_dir / flat
488
+ shutil.copy2(str(local), str(target))
489
+ backed.append(rel)
490
+ except Exception:
491
+ pass # 备份失败不阻塞 reset, 但会少一层保护
492
+ return backed
493
+
494
+
495
+
423
496
  def _setup_tracking(base):
424
497
  """git remote add 之后调: fetch 远程 + 设置当前分支的上游 tracking。
425
498
  没这步, git pull 会报 "no tracking information for the current branch"。
426
499
  fetch 可能因网络/认证失败 — 失败只警告, 不阻塞 (remote 至少配上了)。
500
+
501
+ 关键修复 (Trellis 化): 如果本地是空的 git init 历史 (没有 commit) 或与远程
502
+ 不相关 (unrelated histories), 就直接 git reset --hard origin/<branch> 采用远程历史。
503
+ 原理: 引擎代码现在由 npm 包生成 (不在 git 里), 团队数据 (config/data/workspace) 在
504
+ 远程 → 本地空历史直接采用远程是唯一正确姿势, 彻底消除 "refusing to merge unrelated
505
+ histories"。
506
+ 数据安全: reset 前会先把本地修改过的团队数据文件 (config 等) 备份到 .wlkj-pre-reset/,
507
+ 防止开发者未提交的真实密码/配置被远程覆盖丢失。
427
508
  """
428
509
  # fetch 远程分支
429
510
  r = run(['git', 'fetch', 'origin'], cwd=str(base))
@@ -435,9 +516,7 @@ def _setup_tracking(base):
435
516
  else:
436
517
  warn('git fetch 失败 (不阻塞, 之后 /wl-init 时重试): ' + err[:80])
437
518
  return
438
- # 确定本地当前分支名
439
- br_r = run(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], cwd=str(base))
440
- local_branch = br_r.stdout.strip() if br_r.returncode == 0 else 'master'
519
+
441
520
  # 远程有 master 还是 main? 优先 master (团队约定), fallback main
442
521
  remote_branch = None
443
522
  for cand in ('master', 'main'):
@@ -447,10 +526,46 @@ def _setup_tracking(base):
447
526
  break
448
527
  if not remote_branch:
449
528
  return # 远程没分支(空仓库), 没法设 tracking, 等 push 后再说
450
- # 设置上游 tracking
529
+
530
+ # 确定本地当前分支名 (unborn 分支用 symbolic-ref, 不能用 rev-parse)
531
+ local_branch = _detect_local_branch(base)
532
+
533
+ # === 检测本地是否有有效历史 (是否有 commit) ===
534
+ head_r = run(['git', 'rev-parse', '--verify', 'HEAD'], cwd=str(base))
535
+ has_local_commit = head_r.returncode == 0
536
+ # 探测 unrelated histories (即便本地有 commit, 无公共祖先也需采用远程)
537
+ unrelated = False
538
+ if has_local_commit:
539
+ mb_r = run(['git', 'merge-base', local_branch, f'origin/{remote_branch}'], cwd=str(base))
540
+ unrelated = (mb_r.returncode != 0)
541
+
542
+ if not has_local_commit or unrelated:
543
+ # 本地无有效历史 (git init 没提交过) 或与远程无公共祖先。
544
+ # 本地这点平行历史无价值 (团队真实历史都在远程) → 采用远程历史。
545
+ # 但 reset --hard 会覆盖工作树 → 先备份本地改过的团队数据, 防丢密码。
546
+ if unrelated:
547
+ warn(f'检测到无关历史 (本地与 origin/{remote_branch} 无公共祖先) — 采用远程历史')
548
+ backed = _backup_local_data(base, remote_branch)
549
+ rr = run(['git', 'reset', '--hard', f'origin/{remote_branch}'], cwd=str(base))
550
+ if rr.returncode == 0:
551
+ ok(f'已采用远程历史 (origin/{remote_branch})')
552
+ if backed:
553
+ warn('reset 前已备份你本地修改过的数据文件 (可能含未提交的真实密码/配置):')
554
+ for rel in backed:
555
+ warn(f' → .wlkj-pre-reset/{rel.replace("/", "__")} (reset 前的本地版本)')
556
+ warn('请检查这些文件, 把需要的配置/密码重新填回 .qoder/config.yaml 后删除备份目录。')
557
+ else:
558
+ warn('reset --hard 失败: ' + (rr.stderr or '').strip()[:80])
559
+ # reset 后本地分支已指向远程 commit, 现在能设上游了
560
+ run(['git', 'branch', f'--set-upstream-to=origin/{remote_branch}', local_branch], cwd=str(base))
561
+ return
562
+
563
+ # 有公共祖先, 正常设上游
451
564
  run(['git', 'branch', f'--set-upstream-to=origin/{remote_branch}', local_branch], cwd=str(base))
452
565
 
453
566
 
567
+
568
+
454
569
  def configure_team_remote():
455
570
  """配置团队协作仓库的 git remote (workspace/ 产出往这里 push)。
456
571
 
@@ -532,10 +647,12 @@ def offer_cron(skip=False):
532
647
  return
533
648
 
534
649
  if ask('注册周五 18:00 自动更新知识图谱? (团队只需一台机器注册)', 'y'):
650
+ # cron 脚本在 scripts/ 根 (THIS_DIR = scripts/deployment/setup/, 上两级)
651
+ cron_dir = THIS_DIR.parent.parent
535
652
  if sys.platform == 'win32':
536
- r = run(['cmd', '/c', str(THIS_DIR / 'setup_weekly_cron.bat')], cwd=str(BASE))
653
+ r = run(['cmd', '/c', str(cron_dir / 'setup_weekly_cron.bat')], cwd=str(BASE))
537
654
  else:
538
- r = run(['bash', str(THIS_DIR / 'setup_weekly_cron.sh')], cwd=str(BASE))
655
+ r = run(['bash', str(cron_dir / 'setup_weekly_cron.sh')], cwd=str(BASE))
539
656
  if r.returncode == 0:
540
657
  ok('cron 已注册 (周五 18:00)')
541
658
  else:
@@ -655,13 +772,25 @@ def print_ready(name, role):
655
772
  if projects:
656
773
  ok(f'源码仓库: {len(projects)} 个项目 ({", ".join(projects[:3])})')
657
774
 
658
- # 索引
659
- ki = BASE / 'data' / 'index' / 'code-keyword.json'
660
- if ki.is_file():
775
+ # 知识图谱 (DuckDB 是唯一事实源; 旧 code-keyword.json 已废弃)
776
+ kg = BASE / 'data' / 'index' / 'kg.duckdb'
777
+ if kg.is_file():
661
778
  try:
662
- import json
663
- data = json.loads(ki.read_text(encoding='utf-8'))
664
- ok(f'知识图谱: {len(data)} keywords')
779
+ size_kb = kg.stat().st_size // 1024
780
+ # 尝试读关键词行数作为"有内容"的证据 (读不到只报大小)
781
+ kw_n = None
782
+ try:
783
+ import duckdb as _ddb
784
+ con = _ddb.connect(str(kg), read_only=True)
785
+ row = con.execute('SELECT COUNT(*) FROM keywords').fetchone()
786
+ con.close()
787
+ kw_n = row[0] if row else None
788
+ except Exception:
789
+ pass
790
+ if kw_n:
791
+ ok(f'知识图谱: {kw_n} keywords (kg.duckdb {size_kb} KB)')
792
+ else:
793
+ ok(f'知识图谱: kg.duckdb {size_kb} KB')
665
794
  except Exception:
666
795
  pass
667
796
 
@@ -684,7 +813,7 @@ def print_ready(name, role):
684
813
 
685
814
  print()
686
815
  print(' 现在可以开始了:')
687
- print(' /wl-prd-full 写需求 /wl-search 查代码 /wl-task 建任务')
816
+ print(' /wl-prd 写需求 /wl-search 查代码 /wl-task 建任务')
688
817
  print(' /wl-status 看进度 /wl-report 出日报 /wl-commit 提交')
689
818
  print()
690
819
  print(' 或直接用自然语言:')