@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.
- package/bin/cli.js +1435 -1107
- package/package.json +29 -29
- package/templates/qoder/agents/insight-planning.md +1 -1
- package/templates/qoder/agents/insight-research.md +28 -15
- package/templates/qoder/commands/optional/wl-insight.md +161 -161
- package/templates/qoder/commands/optional/wl-report.md +20 -39
- package/templates/qoder/commands/optional/wl-status.md +4 -4
- package/templates/qoder/commands/wl-code.md +2 -2
- package/templates/qoder/commands/wl-design.md +6 -6
- package/templates/qoder/commands/wl-init.md +3 -3
- package/templates/qoder/commands/wl-prd.md +26 -13
- package/templates/qoder/commands/wl-req.md +43 -0
- package/templates/qoder/commands/wl-search.md +78 -47
- package/templates/qoder/commands/wl-task.md +343 -40
- package/templates/qoder/commands/wl-test.md +43 -17
- package/templates/qoder/config.yaml +52 -14
- package/templates/qoder/hooks/post-tool-use.py +181 -0
- package/templates/qoder/hooks/session-start.py +94 -23
- package/templates/qoder/hooks/stop-eval.py +207 -0
- package/templates/qoder/hooks/user-prompt-submit.py +139 -0
- package/templates/qoder/rules/wl-pipeline.md +85 -49
- package/templates/qoder/scripts/README.md +102 -0
- package/templates/qoder/scripts/capability/__init__.py +26 -0
- package/templates/qoder/scripts/capability/__main__.py +72 -0
- package/templates/qoder/scripts/capability/adapters/__init__.py +29 -0
- package/templates/qoder/scripts/capability/adapters/cli.py +316 -0
- package/templates/qoder/scripts/capability/adapters/mcp.py +334 -0
- package/templates/qoder/scripts/capability/adapters/qw.py +271 -0
- package/templates/qoder/scripts/capability/caps/__init__.py +27 -0
- package/templates/qoder/scripts/capability/caps/context.py +36 -0
- package/templates/qoder/scripts/capability/caps/cron.py +50 -0
- package/templates/qoder/scripts/capability/caps/identity.py +43 -0
- package/templates/qoder/scripts/capability/caps/memory.py +71 -0
- package/templates/qoder/scripts/capability/caps/notify.py +41 -0
- package/templates/qoder/scripts/capability/caps/present.py +48 -0
- package/templates/qoder/scripts/capability/caps/repo.py +31 -0
- package/templates/qoder/scripts/capability/caps/sandbox.py +43 -0
- package/templates/qoder/scripts/capability/chain.py +92 -0
- package/templates/qoder/scripts/capability/memory_chain.py +41 -0
- package/templates/qoder/scripts/capability/registry.py +246 -0
- package/templates/qoder/scripts/capability/registry_mcp.py +250 -0
- package/templates/qoder/scripts/capability/smoke_test.py +211 -0
- package/templates/qoder/scripts/capability/smoke_test_report.json +94 -0
- package/templates/qoder/scripts/deployment/setup/__init__.py +11 -0
- package/templates/qoder/scripts/deployment/setup/carriers.py +669 -0
- package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
- package/templates/qoder/scripts/{init_doctor.py → deployment/setup/init_doctor.py} +100 -39
- package/templates/qoder/scripts/{install_qoderwork.py → deployment/setup/install_qoderwork.py} +48 -30
- package/templates/qoder/scripts/{platform_doctor.py → deployment/setup/platform_doctor.py} +271 -259
- package/templates/qoder/scripts/{repo_root.py → deployment/setup/repo_root.py} +9 -2
- package/templates/qoder/scripts/{setup.py → deployment/setup/setup.py} +143 -14
- package/templates/qoder/scripts/{setup_lanhu.py → deployment/setup/setup_lanhu.py} +979 -963
- package/templates/qoder/scripts/domain/design/__init__.py +0 -0
- package/templates/qoder/scripts/{fill_prototype.py → domain/design/fill_prototype.py} +17 -5
- package/templates/qoder/scripts/{gen_design_doc.py → domain/design/gen_design_doc.py} +406 -394
- package/templates/qoder/scripts/domain/kg/__init__.py +11 -0
- package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
- package/templates/qoder/scripts/domain/kg/build/build_entity_registry.py +201 -0
- package/templates/qoder/scripts/domain/kg/build/build_relations.py +132 -0
- package/templates/qoder/scripts/{build_style_index.py → domain/kg/build/build_style_index.py} +50 -15
- package/templates/qoder/scripts/domain/kg/build/build_workflows.py +149 -0
- package/templates/qoder/scripts/{kg_build.py → domain/kg/build/kg_build.py} +685 -612
- package/templates/qoder/scripts/{kg_build_db.py → domain/kg/build/kg_build_db.py} +338 -327
- package/templates/qoder/scripts/{kg_incremental.py → domain/kg/build/kg_incremental.py} +425 -393
- package/templates/qoder/scripts/{learn_aggregate.py → domain/kg/build/learn_aggregate.py} +212 -201
- package/templates/qoder/scripts/domain/kg/extract/__init__.py +0 -0
- package/templates/qoder/scripts/{common → domain/kg/extract}/extract.py +430 -419
- package/templates/qoder/scripts/domain/kg/extract/test_extract.py +115 -0
- package/templates/qoder/scripts/{common → domain/kg/extract}/ts_extract.py +614 -536
- package/templates/qoder/scripts/domain/kg/graph/__init__.py +0 -0
- package/templates/qoder/scripts/{kg_link_db.py → domain/kg/graph/kg_link_db.py} +235 -224
- package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
- package/templates/qoder/scripts/{kg.py → domain/kg/kg.py} +871 -708
- package/templates/qoder/scripts/domain/kg/kg_capabilities.py +182 -0
- package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
- package/templates/qoder/scripts/{context_pack.py → domain/kg/search/context_pack.py} +45 -17
- package/templates/qoder/scripts/{enrich_prompt.py → domain/kg/search/enrich_prompt.py} +238 -226
- package/templates/qoder/scripts/domain/kg/search/prefetch.py +384 -0
- package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
- package/templates/qoder/scripts/{search_index.py → domain/kg/search/search_index.py} +210 -88
- package/templates/qoder/scripts/domain/kg/server/__init__.py +0 -0
- package/templates/qoder/scripts/domain/kg/server/kgd.py +549 -0
- package/templates/qoder/scripts/domain/kg/server/perf_bench.py +197 -0
- package/templates/qoder/scripts/domain/kg/storage/__init__.py +0 -0
- package/templates/qoder/scripts/{kg_duckdb.py → domain/kg/storage/kg_duckdb.py} +70 -45
- package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
- package/templates/qoder/scripts/{learn.py → domain/learning/learn.py} +157 -146
- package/templates/qoder/scripts/domain/report/__init__.py +11 -0
- package/templates/qoder/scripts/{add_session.py → domain/report/add_session.py} +256 -244
- package/templates/qoder/scripts/{export.py → domain/report/export.py} +72 -4
- package/templates/qoder/scripts/{report.py → domain/report/report.py} +292 -281
- package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
- package/templates/qoder/scripts/domain/report/role.py +39 -0
- package/templates/qoder/scripts/{status.py → domain/report/status.py} +737 -628
- package/templates/qoder/scripts/domain/report/status_snapshot.py +191 -0
- package/templates/qoder/scripts/domain/requirement/__init__.py +0 -0
- package/templates/qoder/scripts/{archive_prd.py → domain/requirement/archive_prd.py} +389 -377
- package/templates/qoder/scripts/domain/requirement/req.py +228 -0
- package/templates/qoder/scripts/domain/task/__init__.py +11 -0
- package/templates/qoder/scripts/{git_sync.py → domain/task/git_sync.py} +90 -50
- package/templates/qoder/scripts/{syncgate.py → domain/task/syncgate.py} +18 -7
- package/templates/qoder/scripts/domain/task/task.py +229 -0
- package/templates/qoder/scripts/domain/task/task_lifecycle.py +606 -0
- package/templates/qoder/scripts/domain/task/task_query.py +162 -0
- package/templates/qoder/scripts/domain/task/task_relations.py +425 -0
- package/templates/qoder/scripts/{team_sync.py → domain/task/team_sync.py} +101 -23
- package/templates/qoder/scripts/domain/task/zentao_sync.py +370 -0
- package/templates/qoder/scripts/foundation/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/bootstrap.py +145 -0
- package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/core/cmd_registry.py +112 -0
- package/templates/qoder/scripts/foundation/core/config.py +187 -0
- package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -400
- package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/data/contract.py +317 -0
- package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
- package/templates/qoder/scripts/foundation/data/result.py +223 -0
- package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -392
- package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/identity/check_publish.py +103 -0
- package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -238
- package/templates/qoder/scripts/foundation/identity/guard.py +159 -0
- package/templates/qoder/scripts/{common → foundation/identity}/identity.py +132 -9
- package/templates/qoder/scripts/foundation/identity/roles.py +60 -0
- package/templates/qoder/scripts/foundation/integrations/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/integrations}/active_task.py +30 -15
- package/templates/qoder/scripts/{common → foundation/integrations}/feishu.py +11 -10
- package/templates/qoder/scripts/{common → foundation/integrations}/terms.py +3 -3
- package/templates/qoder/scripts/foundation/integrations/zentao_client.py +220 -0
- package/templates/qoder/scripts/foundation/io/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/io}/filelock.py +1 -1
- package/templates/qoder/scripts/{common → foundation/io}/reqid.py +1 -1
- package/templates/qoder/scripts/foundation/protocol/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/protocol/duckdb_conn.py +39 -0
- package/templates/qoder/scripts/foundation/protocol/mcp_base.py +268 -0
- package/templates/qoder/scripts/foundation/utils/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/utils}/eval_api.py +12 -1
- package/templates/qoder/scripts/{common → foundation/utils}/pip_install.py +23 -6
- package/templates/qoder/scripts/{common → foundation/utils}/platform_guard.py +1 -1
- package/templates/qoder/scripts/orchestration/__init__.py +0 -0
- package/templates/qoder/scripts/orchestration/wlkj.py +185 -0
- package/templates/qoder/scripts/protocol/__init__.py +0 -0
- package/templates/qoder/scripts/protocol/browser/README.md +207 -0
- package/templates/qoder/scripts/protocol/browser/SKILL.md +265 -0
- package/templates/qoder/scripts/protocol/browser/config.env +9 -0
- package/templates/qoder/scripts/protocol/browser/references/cdp-api.md +110 -0
- package/templates/qoder/scripts/protocol/browser/references/migration-2.5.3.md +72 -0
- package/templates/qoder/scripts/protocol/browser/references/site-patterns/.gitkeep +0 -0
- package/templates/qoder/scripts/protocol/browser/scripts/browser-discovery.mjs +138 -0
- package/templates/qoder/scripts/protocol/browser/scripts/cdp-proxy.mjs +672 -0
- package/templates/qoder/scripts/protocol/browser/scripts/check-deps.mjs +206 -0
- package/templates/qoder/scripts/protocol/browser/scripts/find-url.mjs +253 -0
- package/templates/qoder/scripts/protocol/browser/scripts/match-site.mjs +46 -0
- package/templates/qoder/scripts/protocol/browser/templates/config.env.template +9 -0
- package/templates/qoder/scripts/protocol/mcp/__init__.py +11 -0
- package/templates/qoder/scripts/protocol/mcp/kg_mcp_server.py +478 -0
- package/templates/qoder/scripts/{lanhu_stdio_wrapper.py → protocol/mcp/lanhu_stdio_wrapper.py} +131 -119
- package/templates/qoder/scripts/protocol/mcp/mcp_doctor.py +548 -0
- package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
- package/templates/qoder/scripts/protocol/mcp/mysql_mcp_server.py +461 -0
- package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +1920 -0
- package/templates/qoder/scripts/protocol/transports/__init__.py +56 -0
- package/templates/qoder/scripts/protocol/transports/base.py +87 -0
- package/templates/qoder/scripts/protocol/transports/cli.py +132 -0
- package/templates/qoder/scripts/protocol/transports/http.py +141 -0
- package/templates/qoder/scripts/protocol/transports/stdio.py +293 -0
- package/templates/qoder/scripts/run_weekly_update.bat +27 -18
- package/templates/qoder/scripts/run_weekly_update.sh +22 -13
- package/templates/qoder/scripts/validation/__init__.py +0 -0
- package/templates/qoder/scripts/validation/eval/__init__.py +0 -0
- package/templates/qoder/scripts/validation/eval/perf-report-2026-06-24.md +139 -0
- package/templates/qoder/scripts/validation/eval/qwork_harness.py +617 -0
- package/templates/qoder/scripts/validation/eval/report-commands.md +220 -0
- package/templates/qoder/scripts/validation/eval/transcript_timing.py +386 -0
- package/templates/qoder/scripts/validation/metrics/__init__.py +0 -0
- package/templates/qoder/scripts/{eval_prd.py → validation/metrics/eval_prd.py} +84 -15
- package/templates/qoder/scripts/validation/metrics/usability_score.py +750 -0
- package/templates/qoder/scripts/validation/test/__init__.py +11 -0
- package/templates/qoder/scripts/validation/test/assertion_gen.py +551 -0
- package/templates/qoder/scripts/{autotest.py → validation/test/autotest.py} +1234 -1751
- package/templates/qoder/scripts/validation/test/autotest_auth.py +109 -0
- package/templates/qoder/scripts/{autotest_batch.py → validation/test/autotest_batch.py} +255 -224
- package/templates/qoder/scripts/validation/test/autotest_data.py +680 -0
- package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
- package/templates/qoder/scripts/{autotest_run.py → validation/test/autotest_run.py} +323 -297
- package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
- package/templates/qoder/scripts/{benchmark.py → validation/test/benchmark.py} +17 -5
- package/templates/qoder/scripts/{kg_auto_login.py → validation/test/kg_auto_login.py} +208 -196
- package/templates/qoder/scripts/{kg_test_runner.py → validation/test/kg_test_runner.py} +13 -2
- package/templates/qoder/scripts/{page_probe.py → validation/test/page_probe.py} +470 -459
- package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
- package/templates/qoder/settings.json +23 -2
- package/templates/qoder/skills/design-import/SKILL.md +235 -226
- package/templates/qoder/skills/design-review/SKILL.md +91 -82
- package/templates/qoder/skills/prd-generator/SKILL.md +38 -24
- package/templates/qoder/skills/prd-review/SKILL.md +8 -6
- package/templates/qoder/skills/prototype-generator/SKILL.md +296 -247
- package/templates/qoder/skills/spec-coder/SKILL.md +24 -15
- package/templates/qoder/skills/spec-generator/SKILL.md +24 -12
- package/templates/qoder/skills/test-generator/SKILL.md +9 -7
- package/templates/qoder/skills/wl-code/SKILL.md +25 -13
- package/templates/qoder/skills/wl-commit/SKILL.md +10 -9
- package/templates/qoder/skills/wl-design/SKILL.md +7 -5
- package/templates/qoder/skills/wl-init/SKILL.md +8 -8
- package/templates/qoder/skills/wl-insight/SKILL.md +25 -12
- package/templates/qoder/skills/wl-prd-full/SKILL.md +59 -8
- package/templates/qoder/skills/wl-prd-quick/SKILL.md +7 -7
- package/templates/qoder/skills/wl-prd-review/SKILL.md +18 -6
- package/templates/qoder/skills/wl-report/SKILL.md +27 -25
- package/templates/qoder/skills/wl-search/SKILL.md +151 -80
- package/templates/qoder/skills/wl-spec/SKILL.md +9 -7
- package/templates/qoder/skills/wl-status/SKILL.md +50 -18
- package/templates/qoder/skills/wl-task/SKILL.md +94 -12
- package/templates/qoder/skills/wl-test/SKILL.md +154 -45
- package/templates/qoder/templates/prd-full-template.md +7 -0
- package/templates/root/AGENTS.md +275 -237
- package/templates/root/requirements.txt +3 -0
- package/templates/root//344/275/277/347/224/250/350/257/264/346/230/216.md +3 -3
- package/templates/root//346/226/260/346/211/213/346/214/207/345/215/227.md +2 -2
- package/templates/qoder/hooks/inject-workflow-state.py +0 -169
- package/templates/qoder/scripts/__pycache__/check_mcp_launch.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/__pycache__/install_qoderwork.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/__pycache__/mcp_launcher.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/__pycache__/platform_doctor.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/check_carriers.py +0 -238
- package/templates/qoder/scripts/check_mcp.py +0 -298
- package/templates/qoder/scripts/check_mcp_launch.py +0 -183
- package/templates/qoder/scripts/check_qoderwork_consistency.py +0 -166
- package/templates/qoder/scripts/collect_prds.py +0 -31
- package/templates/qoder/scripts/common/mentions.py +0 -134
- package/templates/qoder/scripts/common/utf8.py +0 -38
- package/templates/qoder/scripts/extract_api_params.py +0 -246
- package/templates/qoder/scripts/extract_routes.py +0 -54
- package/templates/qoder/scripts/extract_routes_tree.py +0 -78
- package/templates/qoder/scripts/handoff.py +0 -22
- package/templates/qoder/scripts/init_developer.py +0 -76
- package/templates/qoder/scripts/kg_mcp_server.py +0 -801
- package/templates/qoder/scripts/kg_semantic.py +0 -150
- package/templates/qoder/scripts/mcp_launcher.py +0 -414
- package/templates/qoder/scripts/mysql_mcp_server.py +0 -396
- package/templates/qoder/scripts/parse_prds.py +0 -33
- package/templates/qoder/scripts/role.py +0 -51
- package/templates/qoder/scripts/sync_carriers.py +0 -259
- package/templates/qoder/scripts/task.py +0 -1261
- package/templates/qoder/scripts/workspace_init.py +0 -102
- package/templates/qoder/scripts/zentao_mcp_server.py +0 -424
- package/templates/qoder/skills/prompt-enrich/SKILL.md +0 -90
- /package/templates/qoder/scripts/{common → deployment}/__init__.py +0 -0
- /package/templates/qoder/{skills/prototype-generator/SKILL.md.zcode-79180-2af4721f-f9a6-412c-88db-c0af680d211b.tmp → scripts/domain/__init__.py} +0 -0
- /package/templates/qoder/scripts/{common → domain/kg/graph}/graph_traverse.py +0 -0
- /package/templates/qoder/scripts/{common → domain/kg/server}/repowiki.py +0 -0
- /package/templates/qoder/scripts/{common → foundation/io}/atomicio.py +0 -0
- /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 =
|
|
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
|
-
|
|
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(
|
|
653
|
+
r = run(['cmd', '/c', str(cron_dir / 'setup_weekly_cron.bat')], cwd=str(BASE))
|
|
537
654
|
else:
|
|
538
|
-
r = run(['bash', str(
|
|
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
|
-
|
|
660
|
-
if
|
|
775
|
+
# 知识图谱 (DuckDB 是唯一事实源; 旧 code-keyword.json 已废弃)
|
|
776
|
+
kg = BASE / 'data' / 'index' / 'kg.duckdb'
|
|
777
|
+
if kg.is_file():
|
|
661
778
|
try:
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
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
|
|
816
|
+
print(' /wl-prd 写需求 /wl-search 查代码 /wl-task 建任务')
|
|
688
817
|
print(' /wl-status 看进度 /wl-report 出日报 /wl-commit 提交')
|
|
689
818
|
print()
|
|
690
819
|
print(' 或直接用自然语言:')
|