@hupan56/wlkj 3.0.0 → 3.1.3
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 -1373
- package/package.json +1 -1
- package/templates/qoder/commands/optional/wl-insight.md +6 -4
- 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 +5 -5
- 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 +3 -3
- 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 +10 -10
- package/templates/qoder/config.yaml +35 -13
- package/templates/qoder/hooks/post-tool-use.py +181 -0
- package/templates/qoder/hooks/session-start.py +82 -1
- 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 +70 -8
- package/templates/qoder/scripts/README.md +78 -115
- 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/{report → deployment/setup}/__init__.py +11 -11
- package/templates/qoder/scripts/{setup → deployment/setup}/carriers.py +33 -26
- package/templates/qoder/scripts/deployment/setup/carriers_verify.py +148 -0
- package/templates/qoder/scripts/{setup → deployment/setup}/init_doctor.py +55 -23
- package/templates/qoder/scripts/{setup → deployment/setup}/install_qoderwork.py +20 -12
- package/templates/qoder/scripts/{setup → deployment/setup}/platform_doctor.py +8 -2
- package/templates/qoder/scripts/{setup → deployment/setup}/repo_root.py +113 -112
- package/templates/qoder/scripts/{setup → deployment/setup}/setup.py +35 -12
- package/templates/qoder/scripts/{setup → deployment/setup}/setup_lanhu.py +13 -7
- package/templates/qoder/scripts/domain/__init__.py +0 -0
- package/templates/qoder/scripts/domain/design/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/design}/fill_prototype.py +12 -6
- package/templates/qoder/scripts/{report → domain/design}/gen_design_doc.py +8 -2
- package/templates/qoder/scripts/{setup → domain/kg}/__init__.py +11 -11
- package/templates/qoder/scripts/domain/kg/build/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_entity_registry.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_relations.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_style_index.py +13 -7
- package/templates/qoder/scripts/{kg → domain/kg/build}/build_workflows.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build.py +76 -9
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_build_db.py +7 -2
- package/templates/qoder/scripts/{kg → domain/kg/build}/kg_incremental.py +11 -6
- package/templates/qoder/scripts/{report → domain/kg/build}/learn_aggregate.py +9 -4
- 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/{common → domain/kg/extract}/test_extract.py +115 -115
- 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 → domain/kg/graph}/kg_link_db.py +7 -2
- package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +683 -0
- package/templates/qoder/scripts/{kg → domain/kg}/kg.py +263 -30
- package/templates/qoder/scripts/{common → domain/kg}/kg_capabilities.py +182 -182
- package/templates/qoder/scripts/domain/kg/search/__init__.py +0 -0
- package/templates/qoder/scripts/{kg → domain/kg/search}/context_pack.py +30 -9
- package/templates/qoder/scripts/{kg → domain/kg/search}/enrich_prompt.py +10 -4
- package/templates/qoder/scripts/{kg → domain/kg/search}/prefetch.py +33 -8
- package/templates/qoder/scripts/{common → domain/kg/search}/search_engine.py +207 -205
- package/templates/qoder/scripts/{kg → domain/kg/search}/search_index.py +143 -77
- 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 → domain/kg/storage}/kg_duckdb.py +38 -14
- package/templates/qoder/scripts/domain/learning/__init__.py +0 -0
- package/templates/qoder/scripts/{report → domain/learning}/learn.py +8 -3
- package/templates/qoder/scripts/{mcp → domain/report}/__init__.py +11 -11
- package/templates/qoder/scripts/{report → domain/report}/add_session.py +9 -3
- package/templates/qoder/scripts/{report → domain/report}/export.py +10 -5
- package/templates/qoder/scripts/{report → domain/report}/report.py +9 -4
- package/templates/qoder/scripts/domain/report/report_snapshot.py +261 -0
- package/templates/qoder/scripts/{report → domain/report}/role.py +10 -4
- package/templates/qoder/scripts/{report → domain/report}/status.py +112 -9
- 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/{report → domain/requirement}/archive_prd.py +8 -2
- package/templates/qoder/scripts/{report → domain/requirement}/req.py +228 -222
- package/templates/qoder/scripts/{kg → domain/task}/__init__.py +11 -11
- package/templates/qoder/scripts/domain/task/__pycache__/syncgate.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/{task → domain/task}/git_sync.py +40 -21
- package/templates/qoder/scripts/{task → domain/task}/syncgate.py +13 -8
- package/templates/qoder/scripts/{task → domain/task}/task.py +13 -5
- package/templates/qoder/scripts/{task → domain/task}/task_lifecycle.py +606 -596
- package/templates/qoder/scripts/{task → domain/task}/task_query.py +162 -161
- package/templates/qoder/scripts/{task → domain/task}/task_relations.py +425 -424
- package/templates/qoder/scripts/{task → domain/task}/team_sync.py +9 -4
- 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/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/__pycache__/bootstrap.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/{common → foundation}/bootstrap.py +10 -10
- package/templates/qoder/scripts/foundation/core/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/core/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/core/__pycache__/paths.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/{common → foundation/core}/cmd_registry.py +1 -1
- package/templates/qoder/scripts/{common → foundation/core}/config.py +1 -1
- package/templates/qoder/scripts/{common → foundation/core}/paths.py +706 -586
- package/templates/qoder/scripts/foundation/data/__init__.py +0 -0
- package/templates/qoder/scripts/{common → foundation/data}/contract.py +2 -2
- package/templates/qoder/scripts/{common → foundation/data}/events.py +2 -2
- package/templates/qoder/scripts/{common → foundation/data}/result.py +1 -1
- package/templates/qoder/scripts/{common → foundation/data}/task_utils.py +427 -404
- package/templates/qoder/scripts/foundation/identity/__init__.py +0 -0
- package/templates/qoder/scripts/foundation/identity/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/identity/__pycache__/identity.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/{common → foundation/identity}/check_publish.py +103 -98
- package/templates/qoder/scripts/{common → foundation/identity}/developer.py +239 -239
- package/templates/qoder/scripts/{common → foundation/identity}/guard.py +2 -2
- package/templates/qoder/scripts/{common → foundation/identity}/identity.py +14 -10
- package/templates/qoder/scripts/{common → foundation/identity}/roles.py +1 -1
- 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 +2 -2
- 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/foundation/io/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/io/__pycache__/atomicio.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/io/__pycache__/filelock.cpython-39.pyc +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/{common → foundation/protocol}/mcp_base.py +1 -1
- 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/{mcp → protocol/mcp}/lanhu_stdio_wrapper.py +11 -5
- package/templates/qoder/scripts/{mcp → protocol/mcp}/mcp_doctor.py +47 -14
- package/templates/qoder/scripts/protocol/mcp/mcp_launcher.py +600 -0
- package/templates/qoder/scripts/{mcp → protocol/mcp}/mysql_mcp_server.py +181 -67
- 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/{report → validation/metrics}/eval_prd.py +17 -10
- 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/{test → validation/test}/autotest.py +64 -4
- package/templates/qoder/scripts/{common → validation/test}/autotest_auth.py +1 -1
- package/templates/qoder/scripts/{test → validation/test}/autotest_batch.py +16 -3
- package/templates/qoder/scripts/{test → validation/test}/autotest_data.py +17 -12
- package/templates/qoder/scripts/validation/test/autotest_opencli.py +646 -0
- package/templates/qoder/scripts/{test → validation/test}/autotest_run.py +17 -3
- package/templates/qoder/scripts/validation/test/autotest_webaccess.py +571 -0
- package/templates/qoder/scripts/{test → validation/test}/benchmark.py +12 -6
- package/templates/qoder/scripts/{test → validation/test}/kg_auto_login.py +8 -2
- package/templates/qoder/scripts/{test → validation/test}/kg_test_runner.py +7 -2
- package/templates/qoder/scripts/{test → validation/test}/page_probe.py +8 -3
- package/templates/qoder/scripts/validation/test/smoke_all_commands.py +170 -0
- package/templates/qoder/settings.json +30 -0
- package/templates/qoder/skills/design-import/SKILL.md +22 -13
- package/templates/qoder/skills/design-review/SKILL.md +19 -10
- package/templates/qoder/skills/prd-generator/SKILL.md +22 -18
- package/templates/qoder/skills/prd-review/SKILL.md +6 -4
- package/templates/qoder/skills/prototype-generator/SKILL.md +63 -14
- package/templates/qoder/skills/spec-coder/SKILL.md +22 -13
- package/templates/qoder/skills/spec-generator/SKILL.md +22 -10
- package/templates/qoder/skills/test-generator/SKILL.md +7 -5
- package/templates/qoder/skills/wl-code/SKILL.md +23 -11
- package/templates/qoder/skills/wl-commit/SKILL.md +9 -8
- package/templates/qoder/skills/wl-design/SKILL.md +5 -3
- package/templates/qoder/skills/wl-init/SKILL.md +6 -6
- package/templates/qoder/skills/wl-insight/SKILL.md +23 -10
- package/templates/qoder/skills/wl-prd-full/SKILL.md +57 -6
- package/templates/qoder/skills/wl-prd-quick/SKILL.md +3 -3
- package/templates/qoder/skills/wl-prd-review/SKILL.md +16 -4
- package/templates/qoder/skills/wl-report/SKILL.md +25 -23
- package/templates/qoder/skills/wl-search/SKILL.md +149 -78
- package/templates/qoder/skills/wl-spec/SKILL.md +7 -5
- package/templates/qoder/skills/wl-status/SKILL.md +48 -16
- package/templates/qoder/skills/wl-task/SKILL.md +92 -10
- package/templates/qoder/skills/wl-test/SKILL.md +75 -29
- package/templates/qoder/templates/prd-full-template.md +7 -0
- package/templates/root/AGENTS.md +275 -236
- 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/.runtime/ctx-cache-5660152f1d6dd819.md +0 -23
- package/templates/.qoder/.runtime/ctx-cache-afdce0dac06b25b0.md +0 -23
- package/templates/.qoder/.runtime/search-cache-eae7644e7b122f35.txt +0 -1
- package/templates/.qoder/learning/eval-history.jsonl +0 -28
- package/templates/data/index/wiki-index.json +0 -8
- package/templates/qoder/nul +0 -4
- package/templates/qoder/scripts/kg/extract.py +0 -398
- package/templates/qoder/scripts/kg/kg_semantic.py +0 -156
- package/templates/qoder/scripts/mcp/kg_mcp_server.py +0 -606
- package/templates/qoder/scripts/mcp/mcp_launcher.py +0 -442
- package/templates/qoder/scripts/mcp/zentao_mcp_server.py +0 -384
- package/templates/qoder/scripts/task/__init__.py +0 -11
- package/templates/qoder/scripts/test/__init__.py +0 -11
- package/templates/qoder/scripts/wlkj.py +0 -116
- /package/templates/qoder/scripts/{common → deployment}/__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/{test → validation/test}/secure-ls.js +0 -0
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
4
|
import os as _o, sys as _s
|
|
5
|
-
|
|
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
|
|
6
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
7
12
|
from bootstrap import setup; setup()
|
|
8
13
|
|
|
@@ -50,12 +55,12 @@ except (AttributeError, TypeError, OSError, IOError):
|
|
|
50
55
|
except Exception:
|
|
51
56
|
pass
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
sys.path.insert(0, SCRIPTS_DIR)
|
|
58
|
+
from foundation.core.paths import get_repo_root, get_developer, get_developer_info
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
SCRIPTS_DIR = str(get_repo_root())
|
|
61
|
+
sys.path.insert(0, SCRIPTS_DIR)
|
|
57
62
|
|
|
58
|
-
BASE =
|
|
63
|
+
BASE = SCRIPTS_DIR
|
|
59
64
|
CODE_DIR = os.path.join(BASE, 'data', 'code')
|
|
60
65
|
INDEX_DIR = os.path.join(BASE, 'data', 'index')
|
|
61
66
|
TPL_DIR = os.path.join(BASE, '.qoder', 'templates')
|
|
@@ -83,16 +88,24 @@ def problem(msg, hint=None):
|
|
|
83
88
|
|
|
84
89
|
def run_script(script, *args, timeout=1800):
|
|
85
90
|
"""跑另一个脚本, 实时透传输出。
|
|
86
|
-
|
|
91
|
+
|
|
92
|
+
v3.x: 脚本已分子目录 (domain/task/, domain/kg/build/, ...), 不再固定在少数子包。
|
|
93
|
+
用递归 glob 在 scripts/ 下找, 找不到才报错 —— 根治"目录一重组 run_script 就断链"
|
|
94
|
+
(旧版硬扫 io/setup/kg/build/test 这几个子目录, v3.0 重组后全找不到)。
|
|
95
|
+
"""
|
|
96
|
+
import glob
|
|
97
|
+
if not script.endswith('.py'):
|
|
98
|
+
script = script + '.py'
|
|
87
99
|
# 先试 scripts/根
|
|
88
100
|
cand = os.path.join(SCRIPTS_DIR, script)
|
|
89
101
|
if not os.path.isfile(cand):
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
102
|
+
# 递归找 scripts/**/<script>
|
|
103
|
+
hits = glob.glob(os.path.join(SCRIPTS_DIR, '**', script), recursive=True)
|
|
104
|
+
if hits:
|
|
105
|
+
cand = hits[0]
|
|
106
|
+
else:
|
|
107
|
+
print('[run_script] 找不到脚本: %s (在 scripts/ 下递归也没找到)' % script)
|
|
108
|
+
return False
|
|
96
109
|
cmd = [sys.executable, cand] + list(args)
|
|
97
110
|
r = subprocess.run(cmd, cwd=BASE, timeout=timeout)
|
|
98
111
|
return r.returncode == 0
|
|
@@ -101,7 +114,7 @@ def run_script(script, *args, timeout=1800):
|
|
|
101
114
|
def load_config():
|
|
102
115
|
"""v3.0: 转发到 Config 单例 (带 mtime 缓存)。"""
|
|
103
116
|
try:
|
|
104
|
-
from
|
|
117
|
+
from foundation.core.config import Config
|
|
105
118
|
return Config.load().raw
|
|
106
119
|
except Exception:
|
|
107
120
|
cfg = os.path.join(BASE, '.qoder', 'config.yaml')
|
|
@@ -185,11 +198,29 @@ def check_dependencies(fix=False):
|
|
|
185
198
|
req = os.path.join(BASE, 'requirements.txt')
|
|
186
199
|
if os.path.isfile(req):
|
|
187
200
|
# 用镜像兜底安装: 默认源失败 → 自动切清华/阿里/腾讯
|
|
188
|
-
|
|
201
|
+
# 注意: install_with_fallback 在 Anaconda 3.9+ Windows 上, pip 长时间编译
|
|
202
|
+
# 退出时偶发 GIL 崩溃 (Python 进程死)。这里 try 兜住: 崩了就用 os.system
|
|
203
|
+
# 跑裸 pip (独立进程, 无 GIL 问题) 兜底, 绝不让 doctor --fix 卡死。
|
|
189
204
|
print(' → 安装: pip install -r requirements.txt (失败自动切国内镜像)')
|
|
190
|
-
result =
|
|
205
|
+
result = None
|
|
206
|
+
try:
|
|
207
|
+
from foundation.utils.pip_install import install_with_fallback
|
|
208
|
+
result = install_with_fallback(['-r', req])
|
|
209
|
+
except Exception as _e:
|
|
210
|
+
print(' [WARN] 镜像安装工具异常 (%s), 改用直装' % str(_e)[:60])
|
|
211
|
+
# 工具崩了或返回失败 → 用 os.system 直装 (清华镜像, 独立进程无 GIL 风险)
|
|
212
|
+
if not result or not result.get('ok'):
|
|
213
|
+
print(' → 直装: pip install -r requirements.txt (清华镜像)')
|
|
214
|
+
import subprocess as _sp
|
|
215
|
+
_rc = _sp.call([sys.executable, '-m', 'pip', 'install', '--no-input',
|
|
216
|
+
'--progress-bar', 'off', '-i',
|
|
217
|
+
'https://pypi.tuna.tsinghua.edu.cn/simple',
|
|
218
|
+
'--trusted-host', 'pypi.tuna.tsinghua.edu.cn',
|
|
219
|
+
'-r', req])
|
|
220
|
+
result = {'ok': _rc == 0, 'source': '清华' if _rc == 0 else None,
|
|
221
|
+
'missing': [], 'hint': None}
|
|
191
222
|
if result['ok']:
|
|
192
|
-
src = result
|
|
223
|
+
src = result.get('source')
|
|
193
224
|
say(FIX, '依赖安装成功' + ('' if src == 'default' else ' (镜像源: %s)' % src))
|
|
194
225
|
# 装完后重新验证 (旧版装完不复查, 会把装失败误报为已装)
|
|
195
226
|
missing_core = []
|
|
@@ -200,7 +231,8 @@ def check_dependencies(fix=False):
|
|
|
200
231
|
except ImportError:
|
|
201
232
|
missing_core.append(pkg)
|
|
202
233
|
else:
|
|
203
|
-
print(' [MISS]
|
|
234
|
+
print(' [MISS] 依赖仍未装齐, 手动: pip install -r requirements.txt '
|
|
235
|
+
'-i https://pypi.tuna.tsinghua.edu.cn/simple')
|
|
204
236
|
# 重新验证, 看哪些真的还缺
|
|
205
237
|
missing_core = []
|
|
206
238
|
for mod, pkg, usage, is_core in PIP_DEPS:
|
|
@@ -246,7 +278,7 @@ def check_developer(fix, name=None, role=None):
|
|
|
246
278
|
return None
|
|
247
279
|
if name and (not current or current != name):
|
|
248
280
|
if fix:
|
|
249
|
-
from
|
|
281
|
+
from foundation.identity.developer import init_developer
|
|
250
282
|
if init_developer(name, role):
|
|
251
283
|
actions.append('注册/切换开发者: ' + name)
|
|
252
284
|
return name
|
|
@@ -430,11 +462,11 @@ def print_degraded_status():
|
|
|
430
462
|
print('=' * 56)
|
|
431
463
|
print(' 以下功能需要源码, 当前不可用:')
|
|
432
464
|
print(' /wl-search 搜代码 (无源码 = 搜不到)')
|
|
433
|
-
print(' /wl-prd
|
|
465
|
+
print(' /wl-prd 完整 PRD 的字段/API 锚定 (会跳过, 原型可用)')
|
|
434
466
|
print(' 知识图谱 MCP search_code/api 等工具 (启动但返回空)')
|
|
435
467
|
print()
|
|
436
468
|
print(' 以下功能不依赖源码, 当前可用:')
|
|
437
|
-
print(' /wl-prd
|
|
469
|
+
print(' /wl-prd 零星需求模式 (纯文案/小改动)')
|
|
438
470
|
print(' /wl-task 任务管理')
|
|
439
471
|
print(' /wl-report 日报周报')
|
|
440
472
|
print(' /wl-commit 代码提交 (提交的是工作流本身的改动)')
|
|
@@ -730,7 +762,7 @@ def check_lanhu():
|
|
|
730
762
|
mcp_file = os.path.join(home, '.qoderwork', 'mcp.json')
|
|
731
763
|
if not os.path.isfile(mcp_file):
|
|
732
764
|
say(WARN, '未配置蓝湖 MCP (团队不用蓝湖可忽略)')
|
|
733
|
-
print(' 用的话跑: python .qoder/scripts/setup
|
|
765
|
+
print(' 用的话跑: python .qoder/scripts/deployment/setup/setup_lanhu.py')
|
|
734
766
|
return
|
|
735
767
|
|
|
736
768
|
try:
|
|
@@ -742,7 +774,7 @@ def check_lanhu():
|
|
|
742
774
|
|
|
743
775
|
if 'lanhu' not in servers:
|
|
744
776
|
say(WARN, '未配置蓝湖 MCP (团队不用蓝湖可忽略)')
|
|
745
|
-
print(' 用的话跑: python .qoder/scripts/setup
|
|
777
|
+
print(' 用的话跑: python .qoder/scripts/deployment/setup/setup_lanhu.py')
|
|
746
778
|
return
|
|
747
779
|
|
|
748
780
|
entry = servers['lanhu']
|
|
@@ -818,7 +850,7 @@ def main():
|
|
|
818
850
|
print('=' * 56)
|
|
819
851
|
return 1
|
|
820
852
|
if _has_source_code():
|
|
821
|
-
print('环境健康, 可以开始工作: /wl-prd
|
|
853
|
+
print('环境健康, 可以开始工作: /wl-prd <需求描述>')
|
|
822
854
|
else:
|
|
823
855
|
print('工作流核心已就绪 (见上方降级说明补源码)。')
|
|
824
856
|
print('=' * 56)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
3
3
|
import os as _o, sys as _s
|
|
4
|
-
|
|
4
|
+
_f = _o.path.abspath(__file__)
|
|
5
|
+
for _ in range(10):
|
|
6
|
+
_f = _o.path.dirname(_f)
|
|
7
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
8
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
9
|
+
break
|
|
5
10
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
6
11
|
from bootstrap import setup; setup()
|
|
12
|
+
from foundation.core.paths import get_repo_root
|
|
7
13
|
|
|
8
14
|
"""
|
|
9
15
|
install_qoderwork.py - 把 .qoder/skills/ 安装到 QoderWork 桌面端可识别的位置
|
|
@@ -46,7 +52,7 @@ if sys.platform == "win32":
|
|
|
46
52
|
|
|
47
53
|
# 路径自检:项目根 = 本文件上四级 (v3.0: setup/ -> scripts/ -> .qoder/ -> repo)
|
|
48
54
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
49
|
-
PROJECT_ROOT =
|
|
55
|
+
PROJECT_ROOT = get_repo_root()
|
|
50
56
|
SOURCE_SKILLS_DIR = PROJECT_ROOT / ".qoder" / "skills"
|
|
51
57
|
SOURCE_COMMANDS_DIR = PROJECT_ROOT / ".qoder" / "commands"
|
|
52
58
|
|
|
@@ -416,10 +422,12 @@ def rewrite_mcp_json_for_launcher():
|
|
|
416
422
|
# 绝对路径每次 install 时探测, 换机器重跑 update 自动刷新。
|
|
417
423
|
# 依赖查找: 先找装了 duckdb 的 python (find_python_with_core_deps),
|
|
418
424
|
# 找不到回退 detect_python_command。
|
|
419
|
-
try
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
425
|
+
# ⚠ find_python_with_core_deps 返回 None (不抛异常) 时, 旧代码因 try/except
|
|
426
|
+
# 捕不到 → py_cmd 留 None → mcp.json 写 "command": null → QoderWork 起 MCP
|
|
427
|
+
# 失败变黄。这里显式 None 判断 + 多级回退, 绝不写 null。
|
|
428
|
+
py_cmd = find_python_with_core_deps()
|
|
429
|
+
if not py_cmd:
|
|
430
|
+
py_cmd = detect_python_command() or sys.executable or "python"
|
|
423
431
|
launcher = str(_HOME / ".qoderwork" / "mcp_launcher.py")
|
|
424
432
|
# MCP 名 → launcher 子命令
|
|
425
433
|
name_map = {
|
|
@@ -496,7 +504,7 @@ def main():
|
|
|
496
504
|
print("MCP 配置刷新 (--mcp-only)")
|
|
497
505
|
print("=" * 56)
|
|
498
506
|
# 1. 复制 launcher
|
|
499
|
-
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "mcp" / "mcp_launcher.py" # v3.0: mcp子包
|
|
507
|
+
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "protocol" / "mcp" / "mcp_launcher.py" # v3.0: protocol/mcp子包
|
|
500
508
|
launcher_dst = _HOME / ".qoderwork" / "mcp_launcher.py"
|
|
501
509
|
try:
|
|
502
510
|
launcher_dst.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -669,7 +677,7 @@ def main():
|
|
|
669
677
|
# QoderWork 桌面端工作目录是临时会话目录, 不是仓库根, 相对路径失效。
|
|
670
678
|
# repo_root.py 从 mcp.json 反推仓库根, 命令文件靠它定位脚本/模板。
|
|
671
679
|
if action in ("install", "check"):
|
|
672
|
-
repo_root_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "setup" / "repo_root.py" # v3.0: setup子包
|
|
680
|
+
repo_root_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "deployment" / "setup" / "repo_root.py" # v3.0: deployment/setup子包
|
|
673
681
|
repo_root_dst = _HOME / ".qoderwork" / "repo_root.py"
|
|
674
682
|
if repo_root_src.is_file():
|
|
675
683
|
if action == "check":
|
|
@@ -694,7 +702,7 @@ def main():
|
|
|
694
702
|
# .repo-root 锚点文件让 launcher 能定位仓库根 (不依赖 mcp.json 里的路径)。
|
|
695
703
|
if action in ("install", "check"):
|
|
696
704
|
print(f"\n--- mcp_launcher.py (统一 MCP 启动器) ---")
|
|
697
|
-
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "mcp" / "mcp_launcher.py" # v3.0: mcp子包
|
|
705
|
+
launcher_src = SOURCE_COMMANDS_DIR.parent / "scripts" / "protocol" / "mcp" / "mcp_launcher.py" # v3.0: protocol/mcp子包
|
|
698
706
|
launcher_dst = _HOME / ".qoderwork" / "mcp_launcher.py"
|
|
699
707
|
anchor_dst = _HOME / ".qoderwork" / ".repo-root"
|
|
700
708
|
if action == "check":
|
|
@@ -765,7 +773,7 @@ def main():
|
|
|
765
773
|
elif lh_status == "would-add":
|
|
766
774
|
print(f" [MISS] 未注册蓝湖 MCP, 安装时会写入 {QODERWORK_MCP_FILE}")
|
|
767
775
|
# STDIO 模式由 QoderWork 自动管, 不查端口; 只确认 wrapper + 源码就绪
|
|
768
|
-
wrapper = PROJECT_ROOT / ".qoder" / "scripts" / "lanhu_stdio_wrapper.py"
|
|
776
|
+
wrapper = PROJECT_ROOT / ".qoder" / "scripts" / "protocol" / "mcp" / "lanhu_stdio_wrapper.py"
|
|
769
777
|
lanhu_dir = PROJECT_ROOT / "external" / "lanhu-mcp"
|
|
770
778
|
if wrapper.is_file():
|
|
771
779
|
print(f" wrapper 就绪: {wrapper.name} (按角色读 cookie)")
|
|
@@ -777,8 +785,8 @@ def main():
|
|
|
777
785
|
if action == "install" and counts["err"] == 0:
|
|
778
786
|
print("\n✓ 安装完成。重启 QoderWork(或新建对话)后技能生效。")
|
|
779
787
|
print(" 在 QoderWork 里直接用自然语言即可,例如:")
|
|
780
|
-
print(' "写个保险异常筛选的 PRD" -> /wl-prd
|
|
781
|
-
print(' "列表加个导出按钮" -> /wl-prd
|
|
788
|
+
print(' "写个保险异常筛选的 PRD" -> /wl-prd(正经需求, 完整档)')
|
|
789
|
+
print(' "列表加个导出按钮" -> /wl-prd(小改动, 自动走快速档)')
|
|
782
790
|
print(' "查一下考勤代码在哪" -> /wl-search')
|
|
783
791
|
elif action == "install" and counts["err"] > 0:
|
|
784
792
|
print(f"\n⚠ 有 {counts['err']} 个安装失败,见上方 [ERR] 行。")
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
4
|
import os as _o, sys as _s
|
|
5
|
-
|
|
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
|
|
6
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
7
12
|
from bootstrap import setup; setup()
|
|
13
|
+
from foundation.core.paths import get_repo_root
|
|
8
14
|
|
|
9
15
|
"""
|
|
10
16
|
platform_doctor.py - 跨平台环境自诊断 (任何 OS 跑, 输出环境真相)
|
|
@@ -49,7 +55,7 @@ for candidate in [HERE.parent.parent, HERE.parent, HERE]:
|
|
|
49
55
|
BASE = candidate
|
|
50
56
|
break
|
|
51
57
|
if BASE is None:
|
|
52
|
-
BASE =
|
|
58
|
+
BASE = get_repo_root()
|
|
53
59
|
|
|
54
60
|
report = {'platform': {}, 'tools': {}, 'engine': {}, 'mcp': {},
|
|
55
61
|
'role': {}, 'issues': [], 'verdict': 'UNKNOWN'}
|
|
@@ -1,112 +1,113 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from bootstrap import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
python ~/.qoderwork/repo_root.py
|
|
20
|
-
python ~/.qoderwork/repo_root.py --
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
python
|
|
24
|
-
""
|
|
25
|
-
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
('
|
|
97
|
-
('
|
|
98
|
-
('
|
|
99
|
-
('
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# repo_root.py — 自适应定位 QODER 流水线仓库根(QoderWork 桌面端专用)。
|
|
3
|
+
#
|
|
4
|
+
# ⚠️ 本文件被 install_qoderwork.py 复制到 ~/.qoderwork/repo_root.py, 在那里它
|
|
5
|
+
# 独立运行 (不依赖仓库内的任何模块)。所以这里**零 import 依赖**——
|
|
6
|
+
# 不能 from bootstrap import (那是仓库内的模块, 定位器不能依赖被定位的东西)。
|
|
7
|
+
# bootstrap 的 sys.path 自举作用对其他被复制脚本有效, 对本定位器是死循环。
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
repo_root.py — 自适应定位 QODER 流水线仓库根(QoderWork 桌面端专用)。
|
|
11
|
+
|
|
12
|
+
为什么需要它:
|
|
13
|
+
QoderWork 桌面端的工作目录是临时会话目录(workspace/xxx), 不是仓库根。
|
|
14
|
+
命令文件里的相对路径 .qoder/scripts/xxx.py 全部失效。
|
|
15
|
+
本脚本从 ~/.qoderwork/mcp.json 的 kg_mcp_server.py 绝对路径反推仓库根,
|
|
16
|
+
自适应(换机器重装 install 后 mcp.json 会更新, 无需硬编码)。
|
|
17
|
+
|
|
18
|
+
用法(命令文件里):
|
|
19
|
+
python ~/.qoderwork/repo_root.py # 打印仓库根绝对路径
|
|
20
|
+
python ~/.qoderwork/repo_root.py --script kg.py # 打印仓库内脚本的绝对路径
|
|
21
|
+
python ~/.qoderwork/repo_root.py --template prd-quick-template.md
|
|
22
|
+
|
|
23
|
+
R=$(python ~/.qoderwork/repo_root.py) # 在 Bash 里捕获仓库根
|
|
24
|
+
python "$R/.qoder/scripts/kg.py" context 保险 --platform web
|
|
25
|
+
"""
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def find_repo_root():
|
|
32
|
+
"""定位 QODER 仓库根。优先级:
|
|
33
|
+
1. ~/.qoderwork/.repo-root 文件 (install 时写, 主路径)
|
|
34
|
+
2. 环境变量 QODER_REPO
|
|
35
|
+
3. 向上找 .qoder/scripts/ (cwd 在仓库内)
|
|
36
|
+
4. 本脚本所在位置 (开发态)
|
|
37
|
+
失败返回 None。
|
|
38
|
+
"""
|
|
39
|
+
home = os.path.expanduser('~')
|
|
40
|
+
|
|
41
|
+
# 方法1: .repo-root 锚点文件 (install_qoderwork 写的, 最可靠)
|
|
42
|
+
anchor = os.path.join(home, '.qoderwork', '.repo-root')
|
|
43
|
+
if os.path.isfile(anchor):
|
|
44
|
+
try:
|
|
45
|
+
line = open(anchor, encoding='utf-8').read().strip()
|
|
46
|
+
if line and os.path.isdir(os.path.join(line, '.qoder', 'scripts')):
|
|
47
|
+
return line
|
|
48
|
+
except OSError:
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
# 方法2: 环境变量
|
|
52
|
+
env_repo = os.environ.get('QODER_REPO')
|
|
53
|
+
if env_repo and os.path.isdir(os.path.join(env_repo, '.qoder', 'scripts')):
|
|
54
|
+
return env_repo
|
|
55
|
+
|
|
56
|
+
# 方法3: 向上找 .qoder 目录(适用于工作目录在仓库内的情况, 如 IDE)
|
|
57
|
+
here = os.path.abspath(os.getcwd())
|
|
58
|
+
for _ in range(8):
|
|
59
|
+
if os.path.isdir(os.path.join(here, '.qoder', 'scripts')):
|
|
60
|
+
return here
|
|
61
|
+
parent = os.path.dirname(here)
|
|
62
|
+
if parent == here:
|
|
63
|
+
break
|
|
64
|
+
here = parent
|
|
65
|
+
|
|
66
|
+
# 方法4: 本脚本所在位置(若它被放到仓库 .qoder/scripts/ 下)
|
|
67
|
+
try:
|
|
68
|
+
s = os.path.abspath(__file__)
|
|
69
|
+
root = os.path.dirname(os.path.dirname(os.path.dirname(s)))
|
|
70
|
+
if os.path.isdir(os.path.join(root, '.qoder', 'scripts')):
|
|
71
|
+
return root
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main():
|
|
79
|
+
root = find_repo_root()
|
|
80
|
+
if not root:
|
|
81
|
+
print('ERROR: 无法定位 QODER 仓库根。请确认 ~/.qoderwork/mcp.json 存在且指向有效的 kg_mcp_server.py', file=sys.stderr)
|
|
82
|
+
return 1
|
|
83
|
+
|
|
84
|
+
# 子路径模式: --script / --template
|
|
85
|
+
args = sys.argv[1:]
|
|
86
|
+
if args and args[0] in ('--script', '--scripts'):
|
|
87
|
+
# 打印仓库内 .qoder/scripts/<name> 的绝对路径
|
|
88
|
+
name = args[1] if len(args) > 1 else ''
|
|
89
|
+
print(os.path.join(root, '.qoder', 'scripts', name))
|
|
90
|
+
elif args and args[0] in ('--template', '--templates'):
|
|
91
|
+
name = args[1] if len(args) > 1 else ''
|
|
92
|
+
print(os.path.join(root, '.qoder', 'templates', name))
|
|
93
|
+
elif args and args[0] == '--test':
|
|
94
|
+
# 自检: 验证关键文件存在
|
|
95
|
+
checks = [
|
|
96
|
+
('kg.py', '.qoder/scripts/domain/kg/kg.py'),
|
|
97
|
+
('eval_prd.py', '.qoder/scripts/validation/metrics/eval_prd.py'),
|
|
98
|
+
('quick模板', '.qoder/templates/prd-quick-template.md'),
|
|
99
|
+
('full模板', '.qoder/templates/prd-full-template.md'),
|
|
100
|
+
('kg.duckdb', 'data/index/kg.duckdb'),
|
|
101
|
+
]
|
|
102
|
+
print('仓库根: %s' % root)
|
|
103
|
+
for label, rel in checks:
|
|
104
|
+
ok = os.path.isfile(os.path.join(root, rel))
|
|
105
|
+
print(' %s %s' % ('✅' if ok else '❌', label))
|
|
106
|
+
else:
|
|
107
|
+
# 默认: 只打印仓库根
|
|
108
|
+
print(root)
|
|
109
|
+
return 0
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == '__main__':
|
|
113
|
+
sys.exit(main())
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
4
4
|
import os as _o, sys as _s
|
|
5
|
-
|
|
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
|
|
6
11
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
7
12
|
from bootstrap import setup; setup()
|
|
13
|
+
from foundation.core.paths import get_repo_root
|
|
8
14
|
|
|
9
15
|
"""
|
|
10
16
|
setup.py - 一键就绪 (小而美)
|
|
@@ -41,7 +47,7 @@ except (AttributeError, TypeError, OSError):
|
|
|
41
47
|
pass
|
|
42
48
|
|
|
43
49
|
THIS_DIR = Path(__file__).resolve().parent
|
|
44
|
-
BASE =
|
|
50
|
+
BASE = get_repo_root()
|
|
45
51
|
|
|
46
52
|
|
|
47
53
|
# ============================================================
|
|
@@ -641,16 +647,21 @@ def offer_cron(skip=False):
|
|
|
641
647
|
return
|
|
642
648
|
|
|
643
649
|
if ask('注册周五 18:00 自动更新知识图谱? (团队只需一台机器注册)', 'y'):
|
|
650
|
+
# cron 脚本在 scripts/ 根 (THIS_DIR = scripts/deployment/setup/, 上两级)
|
|
651
|
+
cron_dir = THIS_DIR.parent.parent
|
|
644
652
|
if sys.platform == 'win32':
|
|
645
|
-
r = run(['cmd', '/c', str(
|
|
653
|
+
r = run(['cmd', '/c', str(cron_dir / 'setup_weekly_cron.bat')], cwd=str(BASE))
|
|
646
654
|
else:
|
|
647
|
-
r = run(['bash', str(
|
|
655
|
+
r = run(['bash', str(cron_dir / 'setup_weekly_cron.sh')], cwd=str(BASE))
|
|
648
656
|
if r.returncode == 0:
|
|
649
657
|
ok('cron 已注册 (周五 18:00)')
|
|
650
658
|
else:
|
|
651
659
|
warn(f'cron 注册失败: {(r.stderr or "").strip()[:100]}')
|
|
652
660
|
else:
|
|
653
|
-
|
|
661
|
+
if sys.platform == 'win32':
|
|
662
|
+
print(' 跳过。以后可手动跑 (双击或命令行): .qoder\\scripts\\setup_weekly_cron.bat')
|
|
663
|
+
else:
|
|
664
|
+
print(' 跳过。以后可手动跑: bash .qoder/scripts/setup_weekly_cron.sh')
|
|
654
665
|
|
|
655
666
|
|
|
656
667
|
# ============================================================
|
|
@@ -764,13 +775,25 @@ def print_ready(name, role):
|
|
|
764
775
|
if projects:
|
|
765
776
|
ok(f'源码仓库: {len(projects)} 个项目 ({", ".join(projects[:3])})')
|
|
766
777
|
|
|
767
|
-
#
|
|
768
|
-
|
|
769
|
-
if
|
|
778
|
+
# 知识图谱 (DuckDB 是唯一事实源; 旧 code-keyword.json 已废弃)
|
|
779
|
+
kg = BASE / 'data' / 'index' / 'kg.duckdb'
|
|
780
|
+
if kg.is_file():
|
|
770
781
|
try:
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
782
|
+
size_kb = kg.stat().st_size // 1024
|
|
783
|
+
# 尝试读关键词行数作为"有内容"的证据 (读不到只报大小)
|
|
784
|
+
kw_n = None
|
|
785
|
+
try:
|
|
786
|
+
import duckdb as _ddb
|
|
787
|
+
con = _ddb.connect(str(kg), read_only=True)
|
|
788
|
+
row = con.execute('SELECT COUNT(*) FROM keywords').fetchone()
|
|
789
|
+
con.close()
|
|
790
|
+
kw_n = row[0] if row else None
|
|
791
|
+
except Exception:
|
|
792
|
+
pass
|
|
793
|
+
if kw_n:
|
|
794
|
+
ok(f'知识图谱: {kw_n} keywords (kg.duckdb {size_kb} KB)')
|
|
795
|
+
else:
|
|
796
|
+
ok(f'知识图谱: kg.duckdb {size_kb} KB')
|
|
774
797
|
except Exception:
|
|
775
798
|
pass
|
|
776
799
|
|
|
@@ -793,7 +816,7 @@ def print_ready(name, role):
|
|
|
793
816
|
|
|
794
817
|
print()
|
|
795
818
|
print(' 现在可以开始了:')
|
|
796
|
-
print(' /wl-prd
|
|
819
|
+
print(' /wl-prd 写需求 /wl-search 查代码 /wl-task 建任务')
|
|
797
820
|
print(' /wl-status 看进度 /wl-report 出日报 /wl-commit 提交')
|
|
798
821
|
print()
|
|
799
822
|
print(' 或直接用自然语言:')
|