@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
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
3
|
+
import os as _o, sys as _s
|
|
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
|
|
10
|
+
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
11
|
+
from bootstrap import setup; setup()
|
|
12
|
+
from foundation.core.paths import get_repo_root
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
perf_bench.py — 知识图谱关键路径性能基准
|
|
16
|
+
|
|
17
|
+
诊断"用了工作流反而更慢"的根因, 并验证常驻化(daemon)加速层的效果。
|
|
18
|
+
|
|
19
|
+
两种测量模式:
|
|
20
|
+
1. 冷启动 (subprocess 跑 kg.py) — 模拟真实用户体验: 起进程→import→连库→跑
|
|
21
|
+
2. daemon 热路径 (kgd_client) — daemon 常驻时的 IPC 调用, 模型/连接已就绪
|
|
22
|
+
|
|
23
|
+
用法:
|
|
24
|
+
python perf_bench.py # 默认: 测冷启动 (--no-daemon)
|
|
25
|
+
python perf_bench.py --with-daemon # 同时测 daemon 热路径 (需先 kgd.py start)
|
|
26
|
+
python perf_bench.py --quick # 跳过 semantic (26s), 只测轻量路径
|
|
27
|
+
"""
|
|
28
|
+
import io
|
|
29
|
+
import os
|
|
30
|
+
import subprocess
|
|
31
|
+
import sys
|
|
32
|
+
import time
|
|
33
|
+
|
|
34
|
+
# UTF-8 输出 (Windows 终端默认 GBK 会乱码)
|
|
35
|
+
try:
|
|
36
|
+
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
37
|
+
except Exception:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
KG_PY = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'kg.py')
|
|
41
|
+
REPO_ROOT = get_repo_root()
|
|
42
|
+
|
|
43
|
+
# ── 测试用例 (覆盖四层) ──────────────────────────────────────────────
|
|
44
|
+
# (名称, kg子命令, 参数列表, 预期层)
|
|
45
|
+
CASES = [
|
|
46
|
+
('search-考勤(web)', 'search', ['考勤', '--platform', 'web'], '结构层'),
|
|
47
|
+
('search-车辆(web)', 'search', ['车辆', '--platform', 'web'], '结构层'),
|
|
48
|
+
('search-报销(app)', 'search', ['报销', '--platform', 'app'], '结构层'),
|
|
49
|
+
('api-asset', 'api', ['asset'], '结构层'),
|
|
50
|
+
('context_pack-车辆', 'context', ['车辆', '--platform', 'web'], '①③+设计'),
|
|
51
|
+
('impact-/asset', 'impact', ['/asset'], '图谱层'),
|
|
52
|
+
('feature-资产管理', 'feature', ['资产管理'], '图谱层'),
|
|
53
|
+
('semantic-报销', 'semantic', ['报销'], '向量层'), # 26s 慢王
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _run_kg(args, use_daemon=True, timeout=120):
|
|
58
|
+
"""跑一次 kg.py 子命令, 返回 (耗时秒, 返回码)。
|
|
59
|
+
|
|
60
|
+
use_daemon=True : 走默认 (kg.py 内部会优先 daemon)
|
|
61
|
+
use_daemon=False : 加 --no-daemon 强制冷路径
|
|
62
|
+
"""
|
|
63
|
+
cmd = [sys.executable, KG_PY] + args
|
|
64
|
+
if not use_daemon:
|
|
65
|
+
cmd.append('--no-daemon')
|
|
66
|
+
env = dict(os.environ)
|
|
67
|
+
env['PYTHONIOENCODING'] = 'utf-8'
|
|
68
|
+
t0 = time.time()
|
|
69
|
+
try:
|
|
70
|
+
# stdout 重定向到 DEVNULL, 只测耗时, 不看内容
|
|
71
|
+
r = subprocess.run(cmd, stdout=subprocess.DEVNULL,
|
|
72
|
+
stderr=subprocess.DEVNULL, cwd=REPO_ROOT,
|
|
73
|
+
env=env, timeout=timeout)
|
|
74
|
+
return time.time() - t0, r.returncode
|
|
75
|
+
except subprocess.TimeoutExpired:
|
|
76
|
+
return float(timeout), -1
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _median(samples):
|
|
80
|
+
"""取中位数 (抗抖动)。"""
|
|
81
|
+
s = sorted(samples)
|
|
82
|
+
n = len(s)
|
|
83
|
+
return s[n // 2] if n % 2 else (s[n // 2 - 1] + s[n // 2]) / 2.0
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def bench_case(name, cmd, args, cold=True, daemon=False, repeats=3):
|
|
87
|
+
"""跑单个用例, 返回 (中位数耗时, 状态)。
|
|
88
|
+
|
|
89
|
+
cold=True : 测冷启动 (--no-daemon)
|
|
90
|
+
daemon=True: 测 daemon 热路径 (不加 --no-daemon, 但需 daemon 在线)
|
|
91
|
+
"""
|
|
92
|
+
if cold and daemon:
|
|
93
|
+
raise ValueError('cold 和 daemon 互斥')
|
|
94
|
+
# 重量级命令 (semantic 冷启动 ~27s) 只跑 1 次, 避免基准脚本本身过慢
|
|
95
|
+
if cmd == 'semantic' and cold:
|
|
96
|
+
repeats = 1
|
|
97
|
+
use_daemon = daemon
|
|
98
|
+
samples = []
|
|
99
|
+
status = 'ok'
|
|
100
|
+
for _ in range(repeats):
|
|
101
|
+
elapsed, rc = _run_kg([cmd] + args, use_daemon=use_daemon)
|
|
102
|
+
samples.append(elapsed)
|
|
103
|
+
if rc != 0:
|
|
104
|
+
status = 'rc=%d' % rc
|
|
105
|
+
return _median(samples), status
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def daemon_online():
|
|
109
|
+
"""探测 daemon 是否在线 (通过 kg.py status, 1s 超时)。"""
|
|
110
|
+
try:
|
|
111
|
+
from kgd import kgd_client
|
|
112
|
+
return kgd_client.ping(timeout=1.0)
|
|
113
|
+
except Exception:
|
|
114
|
+
return False
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def fmt_speedup(cold_s, hot_s):
|
|
118
|
+
"""格式化加速比。"""
|
|
119
|
+
if hot_s <= 0.001:
|
|
120
|
+
return '-'
|
|
121
|
+
return '%.0fx' % (cold_s / hot_s)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def main():
|
|
125
|
+
args = sys.argv[1:]
|
|
126
|
+
quick = '--quick' in args
|
|
127
|
+
want_daemon = '--with-daemon' in args
|
|
128
|
+
|
|
129
|
+
print('=' * 72)
|
|
130
|
+
print('知识图谱性能基准 (repo: %s)' % os.path.basename(REPO_ROOT))
|
|
131
|
+
print('=' * 72)
|
|
132
|
+
|
|
133
|
+
if quick:
|
|
134
|
+
print('[quick 模式] 跳过 semantic (向量层 26s), 只测轻量路径\n')
|
|
135
|
+
cases = [c for c in CASES if c[1] != 'semantic']
|
|
136
|
+
else:
|
|
137
|
+
cases = CASES
|
|
138
|
+
|
|
139
|
+
cold_results = [] # [(name, secs, status, layer)]
|
|
140
|
+
hot_results = {} # name -> (secs, status)
|
|
141
|
+
|
|
142
|
+
# ── 1. 冷启动基线 (真实用户体验: 每次起一个进程) ──
|
|
143
|
+
print('[1/2] 冷启动基线 (--no-daemon, 模拟现状) ...')
|
|
144
|
+
for name, cmd, cargs, layer in cases:
|
|
145
|
+
secs, status = bench_case(name, cmd, cargs, cold=True)
|
|
146
|
+
cold_results.append((name, secs, status, layer))
|
|
147
|
+
marker = ' ' if status == 'ok' else '! '
|
|
148
|
+
print(' %s%-22s %6.2fs [%s] %s' % (marker, name, secs, layer, status))
|
|
149
|
+
print()
|
|
150
|
+
|
|
151
|
+
# ── 2. daemon 热路径 (常驻加速层) ──
|
|
152
|
+
if want_daemon:
|
|
153
|
+
online = daemon_online()
|
|
154
|
+
if not online:
|
|
155
|
+
print('[2/2] daemon 未在线 — 跳过热路径测试。')
|
|
156
|
+
print(' (先启动: python .qoder/scripts/domain/kg/server/kgd.py start)')
|
|
157
|
+
else:
|
|
158
|
+
print('[2/2] daemon 在线, 测热路径 ...')
|
|
159
|
+
for name, cmd, cargs, layer in cases:
|
|
160
|
+
secs, status = bench_case(name, cmd, cargs, cold=False, daemon=True)
|
|
161
|
+
hot_results[name] = (secs, status)
|
|
162
|
+
marker = ' ' if status == 'ok' else '! '
|
|
163
|
+
print(' %s%-22s %6.2fs [%s] %s' % (marker, name, secs, layer, status))
|
|
164
|
+
print()
|
|
165
|
+
|
|
166
|
+
# ── 汇总对比表 ──
|
|
167
|
+
print('-' * 72)
|
|
168
|
+
print('%-22s %10s %10s %10s' % ('用例', '冷启动', 'daemon', '加速'))
|
|
169
|
+
print('%-22s %10s %10s %10s' % ('─' * 18, '─' * 8, '─' * 8, '─' * 6))
|
|
170
|
+
for name, cold_s, status, layer in cold_results:
|
|
171
|
+
hot_s = hot_results.get(name, (None, None))[0]
|
|
172
|
+
hot_str = '%.2fs' % hot_s if hot_s else '-'
|
|
173
|
+
speed = fmt_speedup(cold_s, hot_s) if hot_s else '-'
|
|
174
|
+
print('%-22s %8.2fs %10s %10s' % (name, cold_s, hot_str, speed))
|
|
175
|
+
print('-' * 72)
|
|
176
|
+
|
|
177
|
+
# ── 诊断结论 ──
|
|
178
|
+
print('\n诊断:')
|
|
179
|
+
semantic_s = next((s for n, s, _, _ in cold_results if 'semantic' in n), None)
|
|
180
|
+
if semantic_s and semantic_s > 10:
|
|
181
|
+
print(' 🔴 semantic %.1fs — 模型冷加载占 99%%, 是头号慢源' % semantic_s)
|
|
182
|
+
print(' 解法: kgd.py start 常驻模型 → <0.5s')
|
|
183
|
+
elif semantic_s:
|
|
184
|
+
print(' 🟢 semantic %.1fs — 在可接受范围' % semantic_s)
|
|
185
|
+
|
|
186
|
+
total_cold = sum(s for _, s, _, _ in cold_results)
|
|
187
|
+
print(' 冷启动累积: %.1fs (一次 PRD 流程的隐性等待)' % total_cold)
|
|
188
|
+
if hot_results:
|
|
189
|
+
total_hot = sum(hot_results[n][0] for n in hot_results)
|
|
190
|
+
print(' daemon 累积: %.1fs → 整体提速 %.0fx' %
|
|
191
|
+
(total_hot, total_cold / max(total_hot, 0.01)))
|
|
192
|
+
|
|
193
|
+
return 0
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
if __name__ == '__main__':
|
|
197
|
+
sys.exit(main())
|
|
File without changes
|
|
@@ -1,7 +1,12 @@
|
|
|
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()
|
|
7
12
|
|
|
@@ -27,16 +32,12 @@ import sys
|
|
|
27
32
|
|
|
28
33
|
import duckdb
|
|
29
34
|
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
# '.qoder/scripts/.qoder/scripts'(不存在), 只靠调用方提前 insert sys.path
|
|
33
|
-
# 才能侥幸 import common.paths —— 50 人团队不同安装路径/独立 import 时必崩。
|
|
34
|
-
SCRIPTS = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 子包→scripts/根
|
|
35
|
+
# 深度 4: scripts/ → domain/ → kg/ → storage/ → kg_duckdb.py
|
|
36
|
+
SCRIPTS = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) # storage→kg→domain→scripts/根
|
|
35
37
|
if SCRIPTS not in sys.path:
|
|
36
38
|
sys.path.insert(0, SCRIPTS)
|
|
37
|
-
from
|
|
38
|
-
|
|
39
|
-
DB_PATH = str(DATA_INDEX_DIR / 'kg.duckdb')
|
|
39
|
+
from foundation.core.paths import DATA_INDEX_DIR
|
|
40
|
+
from foundation.protocol.duckdb_conn import get_db, get_db_readonly, DB_PATH # L0 基础设施
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def _load_index_json(name):
|
|
@@ -53,10 +54,20 @@ def _load_index_json(name):
|
|
|
53
54
|
return {}
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
def
|
|
57
|
-
"""Open DuckDB connection
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
def get_db_readonly():
|
|
58
|
+
"""Open read-only DuckDB connection. Returns None if file missing.
|
|
59
|
+
|
|
60
|
+
语义检索 (semantic_search / semantic_search_files) 只读向量数据,
|
|
61
|
+
但 search_index.py 已用 read_only=True 打开了同一个 kg.duckdb。
|
|
62
|
+
DuckDB 不允许对同一文件混用 read_only 和 read_write 连接, 所以
|
|
63
|
+
只读路径必须全程用 read_only, 避免连接冲突。文件不存在则返回 None。
|
|
64
|
+
"""
|
|
65
|
+
if not os.path.isfile(DB_PATH):
|
|
66
|
+
return None
|
|
67
|
+
try:
|
|
68
|
+
return duckdb.connect(DB_PATH, read_only=True)
|
|
69
|
+
except Exception:
|
|
70
|
+
return None
|
|
60
71
|
|
|
61
72
|
|
|
62
73
|
def init_schema(con):
|
|
@@ -140,7 +151,7 @@ def init_schema(con):
|
|
|
140
151
|
# 自动补列: events.py 注册的新统计列, 表里没有就加 (ALTER ... ADD COLUMN IF NOT EXISTS)
|
|
141
152
|
# 这样 events.py 加埋点不用手动改表结构。
|
|
142
153
|
try:
|
|
143
|
-
from
|
|
154
|
+
from foundation.data.events import event_to_sql_filter
|
|
144
155
|
existing = {r[0] for r in con.execute(
|
|
145
156
|
"SELECT column_name FROM information_schema.columns "
|
|
146
157
|
"WHERE table_name = 'learning_stats'"
|
|
@@ -153,6 +164,19 @@ def init_schema(con):
|
|
|
153
164
|
)
|
|
154
165
|
except Exception:
|
|
155
166
|
pass # events.py 不可用 (循环导入等) = 退化为固定 5 列, 不影响
|
|
167
|
+
|
|
168
|
+
# 语义检索向量表 (v3.1: bge-small-zh embedding)
|
|
169
|
+
# entity_id 关联 entities.id; text 是被 embed 的文本 (canonical + cn);
|
|
170
|
+
# vec 存 FLOAT 数组 (DuckDB 用 list 类型, 运行时 cast)。
|
|
171
|
+
con.execute("""
|
|
172
|
+
CREATE TABLE IF NOT EXISTS embeddings (
|
|
173
|
+
entity_id TEXT NOT NULL,
|
|
174
|
+
text TEXT NOT NULL,
|
|
175
|
+
vec FLOAT[],
|
|
176
|
+
model TEXT DEFAULT 'bge-small-zh-v1.5'
|
|
177
|
+
)
|
|
178
|
+
""")
|
|
179
|
+
|
|
156
180
|
# Indexes
|
|
157
181
|
con.execute("CREATE INDEX IF NOT EXISTS idx_ent_type ON entities(type)")
|
|
158
182
|
con.execute("CREATE INDEX IF NOT EXISTS idx_alias ON aliases(alias)")
|
|
File without changes
|
|
@@ -18,7 +18,12 @@
|
|
|
18
18
|
"""
|
|
19
19
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
20
20
|
import os as _o, sys as _s
|
|
21
|
-
|
|
21
|
+
_f = _o.path.abspath(__file__)
|
|
22
|
+
for _ in range(10):
|
|
23
|
+
_f = _o.path.dirname(_f)
|
|
24
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
25
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
26
|
+
break
|
|
22
27
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
23
28
|
from bootstrap import setup; setup()
|
|
24
29
|
|
|
@@ -30,7 +35,7 @@ from datetime import datetime
|
|
|
30
35
|
SCRIPTS = os.path.dirname(os.path.abspath(__file__))
|
|
31
36
|
sys.path.insert(0, SCRIPTS)
|
|
32
37
|
|
|
33
|
-
from
|
|
38
|
+
from foundation.core.paths import get_developer, get_developer_journal_dir
|
|
34
39
|
|
|
35
40
|
|
|
36
41
|
def _feedback_path():
|
|
@@ -80,7 +85,7 @@ def _update_stats(event):
|
|
|
80
85
|
import yaml
|
|
81
86
|
except ImportError:
|
|
82
87
|
return # 无 yaml 库则跳过统计, 不阻塞埋点
|
|
83
|
-
from
|
|
88
|
+
from foundation.data.events import stats_event_map
|
|
84
89
|
key = stats_event_map().get(event)
|
|
85
90
|
if not key:
|
|
86
91
|
return
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# 子包初始化: 注入 scripts/根 + 所有子包到 sys.path
|
|
2
|
-
# 让跨包 import (旧式不带前缀) 仍可用, 兼容现有代码
|
|
3
|
-
import os as _os, sys as _sys
|
|
4
|
-
_root = _os.path.dirname(_os.path.dirname(_os.path.abspath(__file__)))
|
|
5
|
-
if _root not in _sys.path:
|
|
6
|
-
_sys.path.insert(0, _root)
|
|
7
|
-
# 注入所有子包目录 (兼容旧式 import xxx)
|
|
8
|
-
for _sub in ('kg', 'build', 'test', 'setup', 'io'):
|
|
9
|
-
_subdir = _os.path.join(_root, _sub)
|
|
10
|
-
if _os.path.isdir(_subdir) and _subdir not in _sys.path:
|
|
11
|
-
_sys.path.insert(0, _subdir)
|
|
1
|
+
# 子包初始化: 注入 scripts/根 + 所有子包到 sys.path
|
|
2
|
+
# 让跨包 import (旧式不带前缀) 仍可用, 兼容现有代码
|
|
3
|
+
import os as _os, sys as _sys
|
|
4
|
+
_root = _os.path.dirname(_os.path.dirname(_os.path.abspath(__file__)))
|
|
5
|
+
if _root not in _sys.path:
|
|
6
|
+
_sys.path.insert(0, _root)
|
|
7
|
+
# 注入所有子包目录 (兼容旧式 import xxx)
|
|
8
|
+
for _sub in ('kg', 'build', 'test', 'setup', 'io'):
|
|
9
|
+
_subdir = _os.path.join(_root, _sub)
|
|
10
|
+
if _os.path.isdir(_subdir) and _subdir not in _sys.path:
|
|
11
|
+
_sys.path.insert(0, _subdir)
|
|
@@ -20,9 +20,15 @@ from __future__ import annotations
|
|
|
20
20
|
|
|
21
21
|
# v3.0 路径自举: 引导到 common/bootstrap, 统一 sys.path 逻辑
|
|
22
22
|
import os as _o, sys as _s
|
|
23
|
-
|
|
23
|
+
_f = _o.path.abspath(__file__)
|
|
24
|
+
for _ in range(10):
|
|
25
|
+
_f = _o.path.dirname(_f)
|
|
26
|
+
_cp = _o.path.join(_f, 'foundation')
|
|
27
|
+
if _o.path.isfile(_o.path.join(_cp, 'bootstrap.py')):
|
|
28
|
+
break
|
|
24
29
|
if _cp not in _s.path: _s.path.insert(0, _cp)
|
|
25
30
|
from bootstrap import setup; setup()
|
|
31
|
+
from foundation.core.paths import get_repo_root
|
|
26
32
|
|
|
27
33
|
import argparse
|
|
28
34
|
import re
|
|
@@ -34,7 +40,7 @@ from pathlib import Path
|
|
|
34
40
|
|
|
35
41
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
36
42
|
|
|
37
|
-
from
|
|
43
|
+
from foundation.core.paths import (
|
|
38
44
|
FILE_JOURNAL_PREFIX,
|
|
39
45
|
get_repo_root,
|
|
40
46
|
get_developer,
|
|
@@ -42,7 +48,7 @@ from common.paths import (
|
|
|
42
48
|
get_active_journal_file,
|
|
43
49
|
count_lines,
|
|
44
50
|
)
|
|
45
|
-
from
|
|
51
|
+
from foundation.identity.developer import ensure_developer
|
|
46
52
|
|
|
47
53
|
|
|
48
54
|
# =============================================================================
|
|
@@ -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
|
|
|
@@ -39,9 +44,9 @@ except (AttributeError, TypeError, OSError):
|
|
|
39
44
|
|
|
40
45
|
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
41
46
|
sys.path.insert(0, THIS_DIR)
|
|
42
|
-
from
|
|
43
|
-
from
|
|
44
|
-
from
|
|
47
|
+
from foundation.core.paths import get_repo_root, get_developer, get_tasks_dir
|
|
48
|
+
from foundation.data.task_utils import load_task_json
|
|
49
|
+
from foundation.io.atomicio import safe_read_json
|
|
45
50
|
|
|
46
51
|
BASE = get_repo_root()
|
|
47
52
|
INDEX_DIR = BASE / 'data' / 'index'
|
|
@@ -413,7 +418,7 @@ def _build_callgraph():
|
|
|
413
418
|
|
|
414
419
|
# 持久化到 data/index/code-callgraph.json (供后续查询复用)
|
|
415
420
|
try:
|
|
416
|
-
from
|
|
421
|
+
from foundation.io.atomicio import atomic_write_json
|
|
417
422
|
atomic_write_json(str(INDEX_DIR / 'code-callgraph.json'), cg)
|
|
418
423
|
except Exception as e:
|
|
419
424
|
sys.stderr.write(f'[export] callgraph 持久化失败 (不影响导出): {e}\n')
|
|
@@ -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
|
|
|
@@ -34,8 +39,8 @@ except (AttributeError, TypeError, OSError):
|
|
|
34
39
|
|
|
35
40
|
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
36
41
|
sys.path.insert(0, THIS_DIR)
|
|
37
|
-
from
|
|
38
|
-
from
|
|
42
|
+
from foundation.core.paths import get_repo_root, get_developer, get_tasks_dir
|
|
43
|
+
from foundation.data.task_utils import load_task_json
|
|
39
44
|
|
|
40
45
|
BASE = get_repo_root()
|
|
41
46
|
|
|
@@ -253,7 +258,7 @@ def save_and_maybe_push(content: str, mode: str, push_feishu: bool):
|
|
|
253
258
|
|
|
254
259
|
if push_feishu:
|
|
255
260
|
try:
|
|
256
|
-
from
|
|
261
|
+
from foundation.integrations.feishu import send_card, is_enabled
|
|
257
262
|
if is_enabled():
|
|
258
263
|
# 报告作为长文本卡片推送
|
|
259
264
|
title = f'{dev} 的{"周报" if mode == "weekly" else "日报"} - {today}'
|