@furongjun1999/dsh-memory 0.4.8 → 0.4.10
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/README.md +54 -26
- package/codebuddy/CODEBUDDY.md +196 -195
- package/codebuddy/README.md +13 -1
- package/codebuddy/mcp.json +9 -0
- package/docs/GBrain/345/217/257/345/200/237/351/211/264/347/202/271_/347/201/265/346/236/242/350/220/275/347/202/271/344/272/244/346/216/245_20260919.md +169 -0
- package/docs/README.md +1 -1
- package/docs/discipline/harnesses.yaml +18 -7
- package/docs/discipline/templates/full.md.tmpl +4 -3
- package/docs/experiments/linkref_backfill/candidates_20260917.json +726 -0
- package/docs/experiments/linkref_backfill/candidates_internal_20260917.json +602 -0
- package/docs/experiments/linkref_backfill/candidates_internal_v2.json +603 -0
- package/docs/experiments/linkref_backfill/candidates_secret_20260917.json +884 -0
- package/docs/experiments/linkref_backfill/candidates_secret_v2.json +789 -0
- package/docs/hive//345/244/232/347/253/257harness/351/200/232/344/277/241/345/245/221/347/272/246_v0.1.md +42 -0
- package/docs/hive//346/243/200/347/264/242/346/224/266/346/225/233/345/256/236/346/265/213/344/270/216S1b/350/256/276/350/256/241_v0.1.md +43 -0
- package/docs/hive//346/243/200/347/264/242/350/267/257/345/276/204/344/270/216/350/256/244/347/237/245/347/273/223/346/236/204/345/245/221/347/272/246_v0.1.md +102 -0
- package/docs/hive//347/234/237/345/256/236/345/272/223/347/253/257/345/210/260/347/253/257/345/256/236/346/265/213_S1b/344/270/216/345/217/254/345/233/236/346/235/203/350/241/241_v0.1.md +57 -0
- package/docs/hive//347/234/237/345/256/236/345/272/223/347/253/257/345/210/260/347/253/257/345/256/236/346/265/213_S7/345/200/222/346/216/222/345/200/231/351/200/211/345/261/202_v0.1.md +126 -0
- package/docs/hive//350/234/202/345/267/242/345/217/214/345/256/236/344/276/213/344/272/222/351/252/214_/350/256/276/350/256/241/345/256/232/347/250/277.md +503 -0
- package/docs/mdcg/D_meta_/345/267/245/347/250/213/345/214/226/346/226/271/346/241/210_v0.2.md +216 -0
- package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.5.md +631 -625
- package/docs/mdcg//344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/345/245/221/347/272/246_v0.1.md +82 -0
- package/docs/mdcg//345/205/250/345/272/223/344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/350/256/241/345/210/222_v0.1.md +600 -0
- package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +47 -45
- package/docs/mdcg//345/255/220/344/273/243/347/220/206/351/205/215/347/275/256/346/240/207/345/207/{206_v0.4.md → 206_v0.5.md} +92 -4
- package/docs/mdcg//347/201/265/346/236/242/350/256/260/345/277/206/345/212/250/350/257/215/345/215/217/350/256/256_v1.0-draft.md +172 -0
- package/docs/mdcg//347/216/257/344/272/214_/347/231/275/347/256/261/345/241/253/345/205/205/346/265/201/346/260/264/347/272/277_v0.1.md +31 -0
- package/docs/mdcg//350/267/250/347/253/257/351/252/214/350/257/201/344/270/216/345/220/214/346/255/245/345/215/217/350/256/256_v0.1.md +93 -0
- package/docs/theory//345/271/266/345/217/221/345/277/205/347/204/266/346/200/247/347/220/206/350/256/272_v0.2.md +2 -2
- package/docs/theory//347/220/206/350/256/272_/346/234/272/345/210/266_/344/273/243/347/240/201_/345/256/236/351/252/214_/347/274/272/345/217/243/347/237/251/351/230/265_v0.1.md +3 -3
- package/docs/theory//350/256/244/347/237/245/344/273/243/347/220/206/344/270/216/346/224/266/346/225/233/347/273/223/346/236/204_/346/235/241/344/273/266/350/256/272/351/207/215/346/236/204_v0.1.md +2 -2
- package/docs//345/267/245/344/275/234/347/272/252/345/276/213_/350/256/244/347/237/245/345/233/276/346/235/241/347/233/256_v1.1.json +434 -433
- package/docs//347/201/265/346/236/242/350/207/252/346/210/221/346/224/271/350/277/233/345/267/245/344/275/234/350/256/241/345/210/222_/345/244/226/351/203/250/347/240/224/347/251/266/347/263/273/345/210/227/345/220/270/346/224/266_v1_20260919.md +286 -0
- package/dsh/README.md +33 -0
- package/dsh/cordis.yml.example +13 -7
- package/dsh/hive-mcp-probe.mjs +94 -0
- package/dsh/hive-mcp.example.yml +62 -0
- package/dsh/update-lingshu.bat +11 -0
- package/dsh/update-lingshu.ps1 +337 -0
- package/lib/hooks.d.ts +3 -0
- package/lib/hooks.js +17 -23
- package/lib/index.d.ts +4 -2
- package/lib/index.js +29 -6
- package/lib/lib/datapath.d.ts +76 -1
- package/lib/lib/datapath.js +199 -13
- package/lib/lib/mdcg_client.d.ts +40 -3
- package/lib/lib/mdcg_client.js +46 -22
- package/lib/lib/mutual.js +4 -4
- package/lib/lib/token_store.js +4 -5
- package/md_cg/audit.py +17 -2
- package/md_cg/autonomy.py +86 -15
- package/md_cg/backfill.py +36 -1
- package/md_cg/backfill_bigdomain.py +34 -0
- package/md_cg/bench6_arms.py +28 -1
- package/md_cg/bench6_common.py +10 -1
- package/md_cg/bench6_competitors.py +6 -1
- package/md_cg/bench_axis_domain.py +9 -1
- package/md_cg/bench_blind_comp.py +7 -1
- package/md_cg/bench_en_atoms_public.py +9 -0
- package/md_cg/bench_governance.py +348 -0
- package/md_cg/bench_lme_zh.py +16 -1
- package/md_cg/bench_locomo.py +2 -1
- package/md_cg/bench_locomo_zh.py +16 -1
- package/md_cg/bench_locomo_zh_public.py +4 -1
- package/md_cg/bench_longmem.py +2 -1
- package/md_cg/bench_membench.py +27 -1
- package/md_cg/bench_p0.py +4 -1
- package/md_cg/bench_progressive.py +13 -1
- package/md_cg/bench_role_views.py +238 -0
- package/md_cg/bench_task_ab.py +8 -1
- package/md_cg/bench_task_ab_llm.py +13 -1
- package/md_cg/bench_unified_en.py +6 -1
- package/md_cg/bench_zh_mad.py +20 -1
- package/md_cg/blindspot_tickets.py +123 -0
- package/md_cg/branches.py +12 -1
- package/md_cg/build_postings.py +73 -0
- package/md_cg/ccgc.py +67 -2
- package/md_cg/census.py +5 -1
- package/md_cg/chain.py +24 -3
- package/md_cg/codeindex.py +134 -17
- package/md_cg/coldverify.py +265 -0
- package/md_cg/comment_gate.py +338 -0
- package/md_cg/cond_compose.py +190 -0
- package/md_cg/cond_facts.py +155 -0
- package/md_cg/cond_template.json +107 -0
- package/md_cg/condition_anchor.py +143 -0
- package/md_cg/conformance.py +69 -4
- package/md_cg/consistency.py +24 -1
- package/md_cg/consolidate.py +53 -2
- package/md_cg/corpus.py +4 -0
- package/md_cg/crosscheck.py +42 -2
- package/md_cg/crypto.py +35 -1
- package/md_cg/d_meta.py +310 -0
- package/md_cg/datapath.py +201 -26
- package/md_cg/docindex.py +122 -1
- package/md_cg/eval_common.py +29 -1
- package/md_cg/evidence.py +27 -1
- package/md_cg/evolution.py +21 -1
- package/md_cg/export.py +11 -1
- package/md_cg/forgetting.py +23 -1
- package/md_cg/fsutil.py +18 -1
- package/md_cg/hotcache.py +214 -0
- package/md_cg/hyperedge.py +251 -0
- package/md_cg/identity.py +18 -1
- package/md_cg/insight.py +17 -1
- package/md_cg/lexicon/build_cedict_en_zh.py +9 -0
- package/md_cg/lexicon/build_standard_en.py +171 -168
- package/md_cg/lexicon/expand_en_zh.py +6 -0
- package/md_cg/lifecycle.py +12 -1
- package/md_cg/linkref.py +281 -0
- package/md_cg/links.py +29 -1
- package/md_cg/mcp_server.py +362 -43
- package/md_cg/md_whitebox.py +53 -1
- package/md_cg/mdcg.py +1003 -27
- package/md_cg/mdcos.py +558 -36
- package/md_cg/metacognition.py +37 -2
- package/md_cg/migrate.py +4 -0
- package/md_cg/migrate_aeis.py +221 -213
- package/md_cg/migrate_roleplay.py +8 -0
- package/md_cg/migrate_wisdom_graph.py +14 -1
- package/md_cg/mreview/__main__.py +3 -0
- package/md_cg/mreview/bundle.py +8 -0
- package/md_cg/mreview/candidates.py +9 -0
- package/md_cg/mreview/govern.py +21 -1
- package/md_cg/mreview/locate.py +34 -0
- package/md_cg/mreview/pipeline.py +29 -1
- package/md_cg/mreview/ruleset.py +16 -1
- package/md_cg/nodefile.py +233 -3
- package/md_cg/pooling.py +23 -1
- package/md_cg/postings.py +298 -0
- package/md_cg/predict.py +89 -9
- package/md_cg/progressive.py +3 -0
- package/md_cg/protect.py +14 -1
- package/md_cg/protocol.py +372 -0
- package/md_cg/provenance.py +262 -0
- package/md_cg/reach.py +453 -0
- package/md_cg/refindex.py +47 -2
- package/md_cg/refine.py +20 -1
- package/md_cg/roleviews.py +89 -0
- package/md_cg/routing.py +76 -0
- package/md_cg/scrub.py +63 -2
- package/md_cg/security.py +26 -1
- package/md_cg/self_state.py +64 -1
- package/md_cg/selfreport.py +151 -0
- package/md_cg/semantic/canonical.py +5 -0
- package/md_cg/semantic/en_normalizer.py +364 -355
- package/md_cg/semantic/zh_en_atoms.py +139 -136
- package/md_cg/signer.py +41 -1
- package/md_cg/sources.py +583 -547
- package/md_cg/statushdr.py +179 -0
- package/md_cg/stg.py +59 -18
- package/md_cg/subgraph.py +23 -0
- package/md_cg/sustain.py +56 -1
- package/md_cg/tasks.py +26 -2
- package/md_cg/test_autonomy.py +26 -0
- package/md_cg/test_bench_governance.py +102 -0
- package/md_cg/test_blindspot_tickets.py +166 -0
- package/md_cg/test_ccgc.py +10 -0
- package/md_cg/test_codeindex.py +338 -0
- package/md_cg/test_comment_gate.py +187 -0
- package/md_cg/test_cond_compose_anchors.py +76 -0
- package/md_cg/test_condition_anchor.py +82 -0
- package/md_cg/test_d_meta.py +412 -0
- package/md_cg/test_datapath_root.py +188 -0
- package/md_cg/test_gain_gate.py +47 -1
- package/md_cg/test_hot_cold.py +187 -0
- package/md_cg/test_hyperedge.py +245 -0
- package/md_cg/test_linkref.py +306 -0
- package/md_cg/test_md_access_parity.py +15 -3
- package/md_cg/test_mr_m1.py +108 -18
- package/md_cg/test_mr_m3.py +8 -1
- package/md_cg/test_p26_refindex.py +49 -20
- package/md_cg/test_p27_docindex.py +236 -2
- package/md_cg/test_p2_mcp.py +1 -1
- package/md_cg/test_p31_insight.py +24 -0
- package/md_cg/test_p44_md_whitebox.py +14 -1
- package/md_cg/test_protocol.py +243 -0
- package/md_cg/test_reach.py +378 -0
- package/md_cg/test_reach_keys.py +201 -0
- package/md_cg/test_reach_meta_exits.py +145 -0
- package/md_cg/test_read_clip.py +8 -4
- package/md_cg/test_retr_s1.py +340 -0
- package/md_cg/test_retr_s1b.py +209 -0
- package/md_cg/test_retr_s3.py +194 -0
- package/md_cg/test_retr_s4.py +163 -0
- package/md_cg/test_retr_s5.py +200 -0
- package/md_cg/test_retr_s6.py +157 -0
- package/md_cg/test_retr_s7.py +385 -0
- package/md_cg/test_retr_s8_time.py +316 -0
- package/md_cg/test_retr_s9_edges.py +286 -0
- package/md_cg/test_retr_s9_entity_ctx.py +175 -0
- package/md_cg/test_review_conformance.py +59 -2
- package/md_cg/test_role_views.py +354 -0
- package/md_cg/test_subproc_encoding.py +188 -0
- package/md_cg/test_trust.py +361 -0
- package/md_cg/test_units_poll.py +71 -0
- package/md_cg/test_v14_fixes.py +397 -0
- package/md_cg/test_validity_filter.py +280 -0
- package/md_cg/test_wisdom_md_store.py +7 -3
- package/md_cg/test_writepipe.py +5 -1
- package/md_cg/theory.py +16 -1
- package/md_cg/tokens.py +40 -8
- package/md_cg/tool_face.py +13 -2
- package/md_cg/trust.py +943 -0
- package/md_cg/twophase.py +12 -1
- package/md_cg/units.py +132 -10
- package/md_cg/vision_evidence.py +24 -1
- package/md_cg/weights.py +24 -1
- package/md_cg/whitebox.py +32 -1
- package/md_cg/whitebox_kb/data/verify_cache.json +21210 -365
- package/md_cg/whitebox_kb/data/verify_savings.jsonl +5078 -0
- package/md_cg/whitebox_kb/wisdom/audit_log/chain_heat.json +10 -10
- package/md_cg/whitebox_kb/wisdom/code_compose.py +113 -6
- package/md_cg/whitebox_kb/wisdom/code_solidified.json +1 -1
- package/md_cg/whitebox_kb/wisdom/verifier.py +340 -55
- package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db +0 -0
- package/md_cg/writelimit.py +18 -4
- package/md_cg/writepipe.py +178 -7
- package/package.json +2 -2
- package/skills/skills/designer-perspective/scripts/__pycache__/designer.cpython-310.pyc +0 -0
- package/skills/skills/designer-perspective/scripts/designer.py +17 -1
- package/skills/skills/designer-perspective/tests/selftest.py +3 -1
- package/src/hooks.ts +17 -21
- package/src/index.ts +33 -6
- package/src/lib/datapath.ts +211 -13
- package/src/lib/mdcg_client.ts +64 -25
- package/src/lib/mutual.ts +411 -411
- package/src/lib/token_store.ts +4 -5
- package/zcode/AGENTS.md +196 -195
- package/zcode/README.md +4 -0
- package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db-shm +0 -0
- package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db-wal +0 -0
package/md_cg/migrate_aeis.py
CHANGED
|
@@ -1,213 +1,221 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""md_cg · 本地记忆迁移(AEIS sqlite → md 认知图)
|
|
3
|
-
|
|
4
|
-
把 `AEIS/data/aeis_memory.db` 的认知图(nodes + edges)迁到 md_cg 目录,
|
|
5
|
-
供 dsh / zcode 共同读写。**这是本地私有记忆**:默认 sensitivity=private。
|
|
6
|
-
|
|
7
|
-
用法:
|
|
8
|
-
python -m md_cg.migrate_aeis --db <sqlite> --root <md_root> [选项]
|
|
9
|
-
|
|
10
|
-
选项:
|
|
11
|
-
--layers knowledge,anchor,self 只迁这些层(默认全部)
|
|
12
|
-
--limit N 只迁前 N 条(调试)
|
|
13
|
-
--dry-run 只统计不写
|
|
14
|
-
--clearance private 调用方密级(默认 private)
|
|
15
|
-
|
|
16
|
-
校验(全量,非抽样):节点数等价 + content/tags/importance/confidence/
|
|
17
|
-
condition_space/edges/access_count/modality/created_at 逐字段等价。
|
|
18
|
-
|
|
19
|
-
层映射:context→contextual;knowledge/anchor/self/structural 同名。
|
|
20
|
-
幂等:按 id 原子覆盖写,可反复执行。
|
|
21
|
-
"""
|
|
22
|
-
from __future__ import annotations
|
|
23
|
-
|
|
24
|
-
import collections
|
|
25
|
-
import io
|
|
26
|
-
import json
|
|
27
|
-
import os
|
|
28
|
-
import sqlite3
|
|
29
|
-
import sys
|
|
30
|
-
import time
|
|
31
|
-
|
|
32
|
-
from . import subgraph
|
|
33
|
-
from .mdcos import MdCGSecure
|
|
34
|
-
from .security import Principal, DEFAULT_SENSITIVITY
|
|
35
|
-
|
|
36
|
-
# AEIS layer → md_cg layer
|
|
37
|
-
LAYER_MAP = {
|
|
38
|
-
"anchor": "anchor",
|
|
39
|
-
"structural": "structural",
|
|
40
|
-
"knowledge": "knowledge",
|
|
41
|
-
"context": "contextual",
|
|
42
|
-
"contextual": "contextual",
|
|
43
|
-
"self": "self",
|
|
44
|
-
"rejected": "rejected",
|
|
45
|
-
"unresolved": "unresolved",
|
|
46
|
-
}
|
|
47
|
-
MDCG_LAYERS = ("anchor", "structural", "knowledge", "contextual", "self",
|
|
48
|
-
"rejected", "unresolved")
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
return
|
|
69
|
-
|
|
70
|
-
return
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
sql
|
|
88
|
-
if
|
|
89
|
-
sql +=
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
con.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
("
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
("
|
|
167
|
-
("
|
|
168
|
-
("
|
|
169
|
-
("
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
"
|
|
184
|
-
"
|
|
185
|
-
"
|
|
186
|
-
"
|
|
187
|
-
"
|
|
188
|
-
"
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""md_cg · 本地记忆迁移(AEIS sqlite → md 认知图)
|
|
3
|
+
|
|
4
|
+
把 `AEIS/data/aeis_memory.db` 的认知图(nodes + edges)迁到 md_cg 目录,
|
|
5
|
+
供 dsh / zcode 共同读写。**这是本地私有记忆**:默认 sensitivity=private。
|
|
6
|
+
|
|
7
|
+
用法:
|
|
8
|
+
python -m md_cg.migrate_aeis --db <sqlite> --root <md_root> [选项]
|
|
9
|
+
|
|
10
|
+
选项:
|
|
11
|
+
--layers knowledge,anchor,self 只迁这些层(默认全部)
|
|
12
|
+
--limit N 只迁前 N 条(调试)
|
|
13
|
+
--dry-run 只统计不写
|
|
14
|
+
--clearance private 调用方密级(默认 private)
|
|
15
|
+
|
|
16
|
+
校验(全量,非抽样):节点数等价 + content/tags/importance/confidence/
|
|
17
|
+
condition_space/edges/access_count/modality/created_at 逐字段等价。
|
|
18
|
+
|
|
19
|
+
层映射:context→contextual;knowledge/anchor/self/structural 同名。
|
|
20
|
+
幂等:按 id 原子覆盖写,可反复执行。
|
|
21
|
+
"""
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import collections
|
|
25
|
+
import io
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
import sqlite3
|
|
29
|
+
import sys
|
|
30
|
+
import time
|
|
31
|
+
|
|
32
|
+
from . import subgraph
|
|
33
|
+
from .mdcos import MdCGSecure
|
|
34
|
+
from .security import Principal, DEFAULT_SENSITIVITY
|
|
35
|
+
|
|
36
|
+
# AEIS layer → md_cg layer
|
|
37
|
+
LAYER_MAP = {
|
|
38
|
+
"anchor": "anchor",
|
|
39
|
+
"structural": "structural",
|
|
40
|
+
"knowledge": "knowledge",
|
|
41
|
+
"context": "contextual",
|
|
42
|
+
"contextual": "contextual",
|
|
43
|
+
"self": "self",
|
|
44
|
+
"rejected": "rejected",
|
|
45
|
+
"unresolved": "unresolved",
|
|
46
|
+
}
|
|
47
|
+
MDCG_LAYERS = ("anchor", "structural", "knowledge", "contextual", "self",
|
|
48
|
+
"rejected", "unresolved")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# 生效条件:s 为假值(None/空串)时返回 s or ""(即空串),否则返回把 "\r\n" 与 "\r" 依次替换为 "\n" 后的字符串。
|
|
52
|
+
def _norm_text(s: str) -> str:
|
|
53
|
+
"""统一换行:md 是 LF 文本格式,把 CRLF/CR 规范化为 LF。
|
|
54
|
+
|
|
55
|
+
源 sqlite 里的内容常含 \\r\\n(Windows 剪贴板/网页抓取),而 md 文件按 LF 存;
|
|
56
|
+
不规范化会让「content 全量等价」校验出现假失败(实测 24/4523)。
|
|
57
|
+
"""
|
|
58
|
+
if not s:
|
|
59
|
+
return s or ""
|
|
60
|
+
return s.replace("\r\n", "\n").replace("\r", "\n")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# 生效条件:v 为 None 或 v == "" 时返回 default;v 是 dict/list 时原样返回 v;其余值经 json.loads(v) 解析成功则返回解析结果,抛 ValueError/TypeError 时返回 default。
|
|
64
|
+
def _j(v, default):
|
|
65
|
+
if v is None or v == "":
|
|
66
|
+
return default
|
|
67
|
+
if isinstance(v, (dict, list)):
|
|
68
|
+
return v
|
|
69
|
+
try:
|
|
70
|
+
return json.loads(v)
|
|
71
|
+
except (ValueError, TypeError):
|
|
72
|
+
return default
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# 生效条件:float(v) 转换成功时返回该浮点值,抛 TypeError/ValueError 时返回 default(未传则取默认实参 0.0)。
|
|
76
|
+
def _f(v, default=0.0):
|
|
77
|
+
try:
|
|
78
|
+
return float(v)
|
|
79
|
+
except (TypeError, ValueError):
|
|
80
|
+
return default
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# 生效条件:db 以只读 URI 打开 nodes 表;layers 为真值时加 "layer IN (...)" 过滤(None 或空列表不过滤),limit 为真值时拼接 LIMIT int(limit)(None/0/"" 等假值不加 LIMIT),返回按 created_at 排序的行转成的 dict 列表 rows。
|
|
84
|
+
def load_nodes(db: str, layers=None, limit=None):
|
|
85
|
+
con = sqlite3.connect(f"file:{db}?mode=ro", uri=True)
|
|
86
|
+
con.row_factory = sqlite3.Row
|
|
87
|
+
sql, params = "SELECT * FROM nodes", []
|
|
88
|
+
if layers:
|
|
89
|
+
sql += " WHERE layer IN (%s)" % ",".join("?" * len(layers))
|
|
90
|
+
params = list(layers)
|
|
91
|
+
sql += " ORDER BY created_at"
|
|
92
|
+
if limit:
|
|
93
|
+
sql += f" LIMIT {int(limit)}"
|
|
94
|
+
rows = [dict(r) for r in con.execute(sql, params)]
|
|
95
|
+
con.close()
|
|
96
|
+
return rows
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# 生效条件:db 以只读 URI 打开,遍历 edges 表全部行,按 source_id 聚合为 defaultdict(list),每项取 normalize_edge(target_id, relation_type, _f(confidence, 0.7), int(verified or 0)),返回该 out。
|
|
100
|
+
def load_edges(db: str):
|
|
101
|
+
con = sqlite3.connect(f"file:{db}?mode=ro", uri=True)
|
|
102
|
+
out = collections.defaultdict(list)
|
|
103
|
+
for src, tgt, rel, conf, ver in con.execute(
|
|
104
|
+
"SELECT source_id, target_id, relation_type, confidence, verified FROM edges"):
|
|
105
|
+
out[src].append(subgraph.normalize_edge(tgt, rel, _f(conf, 0.7), int(ver or 0)))
|
|
106
|
+
con.close()
|
|
107
|
+
return out
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# 生效条件:以 db、root 建库后,dry_run 为真则跳过写入与回读校验(written=0、count_equal 恒为真、health 为 None),为假则按 rows 逐条 override 写入并做 10 项字段回读比对累计 field_mismatches;clearance 非 "private" 时 sensitivity 取 DEFAULT_SENSITIVITY、否则为 "private";layer 不在 LAYER_MAP 的记入 unknown_layers 并按 knowledge 写入;verbose 为真时打印 report;最终返回该 report。
|
|
111
|
+
def migrate(db: str, root: str, layers=None, limit=None, dry_run=False,
|
|
112
|
+
clearance: str = "private", verbose=True):
|
|
113
|
+
rows = load_nodes(db, layers, limit)
|
|
114
|
+
edges = load_edges(db)
|
|
115
|
+
principal = Principal(tenant="aeis-local", actor="migrate",
|
|
116
|
+
clearance=clearance, can_write=True, can_admin=True)
|
|
117
|
+
cg = MdCGSecure(root, principal=principal, autoflush=500)
|
|
118
|
+
|
|
119
|
+
unknown_layers, written = set(), 0
|
|
120
|
+
t0 = time.time()
|
|
121
|
+
if not dry_run:
|
|
122
|
+
for i, r in enumerate(rows, 1):
|
|
123
|
+
raw_layer = (r.get("layer") or "knowledge")
|
|
124
|
+
layer = LAYER_MAP.get(raw_layer)
|
|
125
|
+
if layer is None:
|
|
126
|
+
unknown_layers.add(raw_layer)
|
|
127
|
+
layer = "knowledge"
|
|
128
|
+
cg.add(
|
|
129
|
+
r["id"], _norm_text(r["content"] or ""), layer=layer,
|
|
130
|
+
override=True, # 迁移是受控整库写入:按 id 幂等覆盖,显式越权
|
|
131
|
+
sensitivity=DEFAULT_SENSITIVITY if clearance != "private" else "private",
|
|
132
|
+
tags=_j(r.get("tags"), []),
|
|
133
|
+
condition_space=_j(r.get("condition_space"), {}),
|
|
134
|
+
importance=_f(r.get("importance"), 0.5),
|
|
135
|
+
confidence=_f(r.get("confidence"), 0.6),
|
|
136
|
+
edges=edges.get(r["id"], []),
|
|
137
|
+
created_at=_f(r.get("created_at"), 0),
|
|
138
|
+
modality=r.get("modality") or "text",
|
|
139
|
+
temporal=r.get("temporal_coordinate"),
|
|
140
|
+
spatial=_j(r.get("spatial_coordinates"), {}),
|
|
141
|
+
semantic_coordinates=_j(r.get("semantic_coordinates"), {}),
|
|
142
|
+
state_attributes=_j(r.get("state_attributes"), {}),
|
|
143
|
+
entity_id=r.get("entity_id"),
|
|
144
|
+
access_count=int(r.get("access_count") or 0),
|
|
145
|
+
last_access=_f(r.get("last_access"), 0),
|
|
146
|
+
# legacy 标记:迁移进来的历史记忆无 CCG 5 要素,
|
|
147
|
+
# 资格判定据此判 DEFER(可检索、待补条件)而非 BLINDSPOT。
|
|
148
|
+
ccg_exempt=True,
|
|
149
|
+
migrated_from="aeis_memory.db",
|
|
150
|
+
)
|
|
151
|
+
written += 1
|
|
152
|
+
if verbose and i % 2000 == 0:
|
|
153
|
+
print(f" …已写入 {i}/{len(rows)}({time.time()-t0:.0f}s)", flush=True)
|
|
154
|
+
cg.flush()
|
|
155
|
+
|
|
156
|
+
# ---------- 全量等价校验 ----------
|
|
157
|
+
bad = []
|
|
158
|
+
if not dry_run:
|
|
159
|
+
for r in rows:
|
|
160
|
+
got = cg.get(r["id"])
|
|
161
|
+
if not got:
|
|
162
|
+
bad.append((r["id"], "missing"))
|
|
163
|
+
continue
|
|
164
|
+
fm = got["frontmatter"]
|
|
165
|
+
checks = [
|
|
166
|
+
("content", (got["content"] or "").rstrip("\n") != _norm_text(r["content"] or "").rstrip("\n")),
|
|
167
|
+
("tags", _j(fm.get("tags"), []) != _j(r.get("tags"), [])),
|
|
168
|
+
("importance", abs(_f(fm.get("importance")) - _f(r.get("importance"))) > 1e-9),
|
|
169
|
+
("confidence", abs(_f(fm.get("confidence")) - _f(r.get("confidence"))) > 1e-9),
|
|
170
|
+
("condition_space", _j(fm.get("condition_space"), {}) != _j(r.get("condition_space"), {})),
|
|
171
|
+
("edges", len(fm.get("edges") or []) != len(edges.get(r["id"], []))),
|
|
172
|
+
("access_count", int(fm.get("access_count") or 0) != int(r.get("access_count") or 0)),
|
|
173
|
+
("modality", (fm.get("modality") or "text") != (r.get("modality") or "text")),
|
|
174
|
+
("created_at", abs(_f(fm.get("created_at")) - _f(r.get("created_at"))) > 1e-6),
|
|
175
|
+
("entity_id", (fm.get("entity_id") or None) != (r.get("entity_id") or None)),
|
|
176
|
+
]
|
|
177
|
+
for name, is_bad in checks:
|
|
178
|
+
if is_bad:
|
|
179
|
+
bad.append((r["id"], name))
|
|
180
|
+
break
|
|
181
|
+
|
|
182
|
+
report = {
|
|
183
|
+
"db": db, "root": root, "dry_run": dry_run,
|
|
184
|
+
"layers_filter": layers,
|
|
185
|
+
"sqlite_nodes": len(rows),
|
|
186
|
+
"md_nodes_total": len(cg.index["nodes"]),
|
|
187
|
+
"written": written,
|
|
188
|
+
"count_equal": (dry_run or len(rows) == written),
|
|
189
|
+
"field_mismatches": len(bad),
|
|
190
|
+
"samples": bad[:5],
|
|
191
|
+
"edges_total": sum(len(v) for v in edges.values()),
|
|
192
|
+
"unknown_layers": sorted(unknown_layers),
|
|
193
|
+
"elapsed_sec": round(time.time() - t0, 1),
|
|
194
|
+
"health": cg.health() if not dry_run else None,
|
|
195
|
+
}
|
|
196
|
+
if verbose:
|
|
197
|
+
print(json.dumps(report, ensure_ascii=False, indent=2))
|
|
198
|
+
cg.close()
|
|
199
|
+
return report
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
# 生效条件:从 argv 取 --db/--root,二者任一为假值时打印 __doc__ 并返回 1;二者均真值时 --layers 为真值则按逗号切分并 strip 成列表(否则 None),再以 limit=--limit、dry_run=("--dry-run" in argv)、clearance=--clearance 或 "private" 调用 migrate 并返回 0(表达式 0 if migrate(...) else 0 恒为 0)。
|
|
203
|
+
def main(argv):
|
|
204
|
+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
|
|
205
|
+
# 生效条件:外层 main 作用域的 argv 中若含 name,则返回其后的下一个元素 argv[argv.index(name)+1],否则返回 default(未传则 None)。
|
|
206
|
+
def opt(name, default=None):
|
|
207
|
+
return argv[argv.index(name) + 1] if name in argv else default
|
|
208
|
+
db = opt("--db")
|
|
209
|
+
root = opt("--root")
|
|
210
|
+
if not db or not root:
|
|
211
|
+
print(__doc__)
|
|
212
|
+
return 1
|
|
213
|
+
layers = opt("--layers")
|
|
214
|
+
layers = [x.strip() for x in layers.split(",")] if layers else None
|
|
215
|
+
return 0 if migrate(db, root, layers=layers, limit=opt("--limit"),
|
|
216
|
+
dry_run="--dry-run" in argv,
|
|
217
|
+
clearance=opt("--clearance", "private")) else 0
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
sys.exit(main(sys.argv))
|
|
@@ -54,6 +54,7 @@ TURN_ROLE = {"user": "user", "bot": "assistant", "assistant": "assistant"}
|
|
|
54
54
|
# 读取源数据
|
|
55
55
|
# --------------------------------------------------------------------------
|
|
56
56
|
|
|
57
|
+
# 生效条件:path 能被 io.open 以 encoding="utf-8" 打开且内容为合法 JSON 时返回 json.load(f),否则在 OSError 或 JSON 解析的 ValueError 时返回 default(仅这两类被捕获,其余异常不返回 default)。
|
|
57
58
|
def _read_json(path, default):
|
|
58
59
|
try:
|
|
59
60
|
with io.open(path, encoding="utf-8") as f:
|
|
@@ -62,6 +63,7 @@ def _read_json(path, default):
|
|
|
62
63
|
return default
|
|
63
64
|
|
|
64
65
|
|
|
66
|
+
# 生效条件:roleplay_dir 下 _roles.json 读出的 raw 是 dict 且 raw.get("meta") 也是 dict 时返回 raw["meta"],raw 是 dict 但 "meta" 非 dict(缺键或非 dict 值)时返回 raw,raw 不是 dict 时返回 {}。
|
|
65
67
|
def load_roles(roleplay_dir):
|
|
66
68
|
"""读取 `_roles.json`,归一化根/嵌套两种格式 → {role_id: meta}。"""
|
|
67
69
|
raw = _read_json(os.path.join(roleplay_dir, "_roles.json"), {})
|
|
@@ -70,6 +72,7 @@ def load_roles(roleplay_dir):
|
|
|
70
72
|
return raw if isinstance(raw, dict) else {}
|
|
71
73
|
|
|
72
74
|
|
|
75
|
+
# 生效条件:os.path.isdir(transcripts_dir) 为真时返回 out(按文件名排序只取 .jsonl,stem 以 "__" 切出 role_id/client_id 且 client_id 为空串时回落 "shared",逐行 strip 后跳过空行与 json.loads 的 ValueError 行,成功 append 后 idx 递增,单个文件 OSError 则跳过该文件);os.path.isdir 为假时直接返回空 out;transcripts_dir 为 None 时 os.path.isdir 会抛 TypeError。
|
|
73
76
|
def load_transcripts(transcripts_dir):
|
|
74
77
|
"""读取全部 `*.jsonl` 转录 → [(role_id, client_id, idx, entry)]。"""
|
|
75
78
|
out = []
|
|
@@ -100,6 +103,7 @@ def load_transcripts(transcripts_dir):
|
|
|
100
103
|
return out
|
|
101
104
|
|
|
102
105
|
|
|
106
|
+
# 生效条件:mutual_dir 为真值且 os.path.isdir(join(mutual_dir,"tasks")) 为真时,先按文件名序对 result-*.json 追加 (tid, claim, result) 并记入 seen(claim 取 task-{tid}.json 的 payload.claim,缺 payload/claim 或为假值时 strip 前回落 "",task 文件读出为假值则回落 {}),再对未出现在 seen 的 task-*.json 追加 (tid, claim, None),返回 out;mutual_dir 为假值(""/None 等)或 tasks 非目录时返回空 out。
|
|
103
107
|
def load_mutual(mutual_dir):
|
|
104
108
|
"""读取互维任务/裁决 → [(task_id, claim, result|None)]。"""
|
|
105
109
|
out, seen = [], set()
|
|
@@ -131,6 +135,7 @@ def load_mutual(mutual_dir):
|
|
|
131
135
|
# 迁移
|
|
132
136
|
# --------------------------------------------------------------------------
|
|
133
137
|
|
|
138
|
+
# 生效条件:对 role_id 与 meta,标题角色名取 meta.get("name") 为真值时的该值、为假值或缺失时回落 role_id,随后仅对 scenario/first_mes/nsfw 中 meta.get(key) 不属于 (None, "", False) 的键各追加一行后返回 "\n".join(lines)。
|
|
134
139
|
def _role_content(role_id, meta):
|
|
135
140
|
name = meta.get("name") or role_id
|
|
136
141
|
lines = [f"# 角色 {name}({role_id})"]
|
|
@@ -140,6 +145,7 @@ def _role_content(role_id, meta):
|
|
|
140
145
|
return "\n".join(lines)
|
|
141
146
|
|
|
142
147
|
|
|
148
|
+
# 生效条件:以 data_dir 的 roleplay、transcripts 子目录收集计划节点,mutual_dir 为假值(None/空串)时不加载互维数据;按 tenant、actor 派生 principal 后,dry_run 为真则只汇总、written=0 且不回读,为假则逐条 override 写入并回读校验 content/layer/tags;clearance 非 "private" 时 sensitivity 取 DEFAULT_SENSITIVITY、否则为 "private";verbose 为真时打印 report;最终返回该 report。
|
|
143
149
|
def migrate(data_dir, root, mutual_dir=None, dry_run=False,
|
|
144
150
|
clearance="private", tenant="default", actor="dsh-memory", verbose=True):
|
|
145
151
|
"""把角色扮演 / 互维数据迁入认知图。
|
|
@@ -264,9 +270,11 @@ def migrate(data_dir, root, mutual_dir=None, dry_run=False,
|
|
|
264
270
|
return report
|
|
265
271
|
|
|
266
272
|
|
|
273
|
+
# 生效条件:argv 中同时出现 "--data-dir" 与 "--root" 且各自后一元素的取值为真值(非空串)时,以 opt("--mutual-dir")、"--dry-run" in argv、clearance 缺省 "private"、tenant 缺省 "default"、actor 缺省 "dsh-memory" 调用 migrate 并返回 0;二者任一缺失或取到空串时打印 __doc__ 并返回 1;若 "--data-dir"/"--root" 位于 argv 末尾则取后一元素时抛 IndexError,而非走返回 1 分支。
|
|
267
274
|
def main(argv):
|
|
268
275
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
|
|
269
276
|
|
|
277
|
+
# 生效条件:name 出现在外层 main 的形参 argv(闭包读取)中且其后还有元素时返回 argv[argv.index(name)+1],name 不在 argv 时返回 default(默认 None),name 位于 argv 末尾时 argv[index+1] 抛 IndexError 而不返回 default。
|
|
270
278
|
def opt(name, default=None):
|
|
271
279
|
return argv[argv.index(name) + 1] if name in argv else default
|
|
272
280
|
|
|
@@ -43,6 +43,7 @@ DEFAULT_DB = os.path.join(_HERE, "whitebox_kb", "wisdom", "wisdom-book-cloud.db"
|
|
|
43
43
|
DEFAULT_ROOT = os.path.join(os.path.dirname(_HERE), "_md_cg_wisdom_graph")
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
# 生效条件:s 为假值(None/""/0 等)时返回 s or ""(None→""、0→""),否则返回把 "\r\n"、"\r" 依次替换为 "\n" 的字符串。
|
|
46
47
|
def _norm_text(s):
|
|
47
48
|
"""统一换行:md 按 LF 存,源库常含 CRLF,不规范化会造成假失败。"""
|
|
48
49
|
if not s:
|
|
@@ -50,6 +51,7 @@ def _norm_text(s):
|
|
|
50
51
|
return s.replace("\r\n", "\n").replace("\r", "\n")
|
|
51
52
|
|
|
52
53
|
|
|
54
|
+
# 生效条件:v 为 None 或等于 "" 时返回 default;v 是 dict 或 list 时原样返回 v;否则 json.loads(v),遇 ValueError/TypeError 时返回 default。
|
|
53
55
|
def _j(v, default):
|
|
54
56
|
if v is None or v == "":
|
|
55
57
|
return default
|
|
@@ -61,6 +63,7 @@ def _j(v, default):
|
|
|
61
63
|
return default
|
|
62
64
|
|
|
63
65
|
|
|
66
|
+
# 生效条件:float(v) 成功时返回该浮点值(含 v="" 之外的数值串),抛 TypeError/ValueError 时返回 default,default 缺省为 0.0。
|
|
64
67
|
def _f(v, default=0.0):
|
|
65
68
|
try:
|
|
66
69
|
return float(v)
|
|
@@ -68,10 +71,12 @@ def _f(v, default=0.0):
|
|
|
68
71
|
return default
|
|
69
72
|
|
|
70
73
|
|
|
74
|
+
# 生效条件:任何传入的 db 都拼成 f"file:{db}?mode=ro" 并 uri=True 返回 sqlite3.connect 的连接(源码未对 db 做存在性或类型校验)。
|
|
71
75
|
def _connect(db):
|
|
72
76
|
return sqlite3.connect(f"file:{db}?mode=ro", uri=True)
|
|
73
77
|
|
|
74
78
|
|
|
79
|
+
# 生效条件:db 经 _connect 只读打开,limit 为真值(非 None/0/"")时 SQL 追加 f" LIMIT {int(limit)}",limit 为假值时无 LIMIT、返回按 created_at 排序的全部 nodes 字典列表。
|
|
75
80
|
def load_nodes(db, limit=None):
|
|
76
81
|
con = _connect(db)
|
|
77
82
|
con.row_factory = sqlite3.Row
|
|
@@ -83,6 +88,7 @@ def load_nodes(db, limit=None):
|
|
|
83
88
|
return rows
|
|
84
89
|
|
|
85
90
|
|
|
91
|
+
# 生效条件:db 只读打开后逐条 edges 按 rel=(relation_type or "").strip() 分派——等于 LEVEL_REL 的记入 children[source_id],其余记入 relations[source_id] 的边字典(target、relation_type、confidence=_f(conf,0.7)、verified=int(ver or 0),且仅当 _j(cs,None) 为真值时加 condition_space、仅当 weight 不为 None 时加 weight=_f(weight,1.0)),返回 (children, relations)。
|
|
86
92
|
def load_graph(db):
|
|
87
93
|
"""返回 (children_of, relations_of)。
|
|
88
94
|
|
|
@@ -115,6 +121,7 @@ def load_graph(db):
|
|
|
115
121
|
# 写:sqlite → md
|
|
116
122
|
# --------------------------------------------------------------------------
|
|
117
123
|
|
|
124
|
+
# 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传);dry_run 为真值时不做写入,rep 只有统计字段而无 verify/ok;dry_run 为假值时以 MdCGOS(root) 把 load_nodes(db, limit)(limit 真值才加 LIMIT)的节点按 id 覆盖写入,并令 rep["verify"]=verify(db, root, verbose=verbose)、rep["ok"]=bool(rep["verify"]["ok"]);verbose 为真值时打印 rep。
|
|
118
125
|
def export(db=DEFAULT_DB, root=DEFAULT_ROOT, limit=None, dry_run=False,
|
|
119
126
|
verbose=True):
|
|
120
127
|
rows = load_nodes(db, limit)
|
|
@@ -180,6 +187,7 @@ def export(db=DEFAULT_DB, root=DEFAULT_ROOT, limit=None, dry_run=False,
|
|
|
180
187
|
# 校验:md 侧 vs sqlite 侧(逐节点全量,不抽样)
|
|
181
188
|
# --------------------------------------------------------------------------
|
|
182
189
|
|
|
190
|
+
# 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传),在 md_ids 与 load_nodes(db) 的交集上做 L1 子/父集合比对、L2 非层级边 target 集合比对、L3 字段比对(condition_space 经 _cs_same 剔除 time_window)后,out["ok"] 仅当无缺失节点、无 child_bad/parent_bad/rel_bad/field_bad、roots_equal 为真且 sg.validate(cg, limit=5) 的 issues==0;verbose 为真值时打印去掉 tree_validate 键的 out。
|
|
183
191
|
def verify(db=DEFAULT_DB, root=DEFAULT_ROOT, verbose=True):
|
|
184
192
|
from . import subgraph as sg
|
|
185
193
|
|
|
@@ -219,6 +227,7 @@ def verify(db=DEFAULT_DB, root=DEFAULT_ROOT, verbose=True):
|
|
|
219
227
|
rel_bad.append({"id": nid, "db": want, "md": got})
|
|
220
228
|
|
|
221
229
|
# ---- L3 字段等价 ----
|
|
230
|
+
# 生效条件:a、b 各自经 _j(a, {}) or {} 转成字典(None/"" 得空 dict)后 pop("time_window"),仅当剔除该槽后的两字典相等才返回 True,否则 False。
|
|
222
231
|
def _cs_same(a, b):
|
|
223
232
|
"""md 写入侧按条件论纪律自动补 time_window(`mdcg.add` 的观测时间窗),
|
|
224
233
|
比对时剔除该槽——它是有意增强,不是迁移失真。"""
|
|
@@ -278,6 +287,7 @@ REC_SUBTREE_SQL = (
|
|
|
278
287
|
"WHERE e.relation_type = ?) SELECT id FROM sub")
|
|
279
288
|
|
|
280
289
|
|
|
290
|
+
# 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传),仅遍历 sg.roots(cg)∩md_ids 的前 n_roots 个根(n_roots 为 0 时切片为空、不做子树比对),每根比对 db 递归 CTE 子树与 sg.flatten(cg, nid, max_nodes=10**9) 的 nodes,out["ok"] 仅当该样本无失配且 forest_partition_ok(n_db==n_md==len(md_ids))成立;verbose 为真值时打印 out。
|
|
281
291
|
def bench_graph(db=DEFAULT_DB, root=DEFAULT_ROOT, n_roots=30, verbose=True):
|
|
282
292
|
"""L4 子树展开等价 + 森林完整性(回答「图**查询**能否由 md 承担」)。
|
|
283
293
|
|
|
@@ -295,6 +305,7 @@ def bench_graph(db=DEFAULT_DB, root=DEFAULT_ROOT, n_roots=30, verbose=True):
|
|
|
295
305
|
con = _connect(db)
|
|
296
306
|
roots_md = sorted(set(sg.roots(cg)) & md_ids)
|
|
297
307
|
|
|
308
|
+
# 生效条件:用外层闭包的 con 执行 REC_SUBTREE_SQL、参数为 (nid, LEVEL_REL),返回结果各行第 0 列构成的集合。
|
|
298
309
|
def _db_subtree(nid):
|
|
299
310
|
return {r[0] for r in con.execute(REC_SUBTREE_SQL, (nid, LEVEL_REL)).fetchall()}
|
|
300
311
|
|
|
@@ -323,10 +334,12 @@ def bench_graph(db=DEFAULT_DB, root=DEFAULT_ROOT, n_roots=30, verbose=True):
|
|
|
323
334
|
return out
|
|
324
335
|
|
|
325
336
|
|
|
337
|
+
# 生效条件:argv 含 "--verify-only" 时返回 0/1 取决于 verify(db, root)["ok"],含 "--bench-graph" 时返回 0/1 取决于 bench_graph(db, root)["ok"],否则以 opt 取的 --db/--root/--limit 调 export(opt("--limit") 缺失或为空串时 limit=None,否则 int(lim);dry_run="--dry-run" in argv),rep.get("dry_run") 为真时直接返回 0,否则按 rep.get("ok") 真→0、假→1。
|
|
326
338
|
def main(argv):
|
|
327
339
|
if hasattr(sys.stdout, "reconfigure"):
|
|
328
340
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
329
341
|
|
|
342
|
+
# 生效条件:name 出现在外层 argv 中时返回 argv[argv.index(name) + 1](即首次出现位置的后一个元素),name 不在 argv 中时返回 default,default 缺省为 None。
|
|
330
343
|
def opt(name, default=None):
|
|
331
344
|
return argv[argv.index(name) + 1] if name in argv else default
|
|
332
345
|
|
|
@@ -345,4 +358,4 @@ def main(argv):
|
|
|
345
358
|
|
|
346
359
|
|
|
347
360
|
if __name__ == "__main__":
|
|
348
|
-
sys.exit(main(sys.argv))
|
|
361
|
+
sys.exit(main(sys.argv))
|
|
@@ -20,6 +20,7 @@ from . import candidates as CD
|
|
|
20
20
|
from . import ruleset as RS
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
# 生效条件:root 为假值(None/空串)时回落 mdcg_root(),sources 缺省取模块常量 CD.SOURCES 并透传给 CD.generate,返回 dict out,且仅当 full 为真值时额外带上 candidates_full、bundles_full、packages_full 三键。
|
|
23
24
|
def run(root=None, *, sources=CD.SOURCES, cold_limit=500, patrol_window=200,
|
|
24
25
|
max_per_bundle=50, limit=None, patrol_offset=None, rules_dir=None,
|
|
25
26
|
full=False) -> dict:
|
|
@@ -55,6 +56,7 @@ def run(root=None, *, sources=CD.SOURCES, cold_limit=500, patrol_window=200,
|
|
|
55
56
|
return out
|
|
56
57
|
|
|
57
58
|
|
|
59
|
+
# 生效条件:d 必须已含 candidates、bundle_stats、assemble_stats、root、content_missing、llm_checks 这些键(直接下标取值,缺键即 KeyError),且仅当 d.get("assertions") 为真值(非空映射)时才追加断言集一行,其 failed 空或缺失时回落显示「无」。
|
|
58
60
|
def _fmt_summary(d: dict) -> str:
|
|
59
61
|
c, b, a = d["candidates"], d["bundle_stats"], d["assemble_stats"]
|
|
60
62
|
lines = ["", "== M1 机械层(候选 → 捆绑 → 规则装配) ==",
|
|
@@ -77,6 +79,7 @@ def _fmt_summary(d: dict) -> str:
|
|
|
77
79
|
return "\n".join(lines)
|
|
78
80
|
|
|
79
81
|
|
|
82
|
+
# 生效条件:argv 为 None 时 argparse 改从 sys.argv[1:] 取参,--sources 按逗号切分并丢弃空串后组成元组传入 run,仅当 --out 为非空串时才以 UTF-8 落盘 JSON dump,各分支之后统一 return 0。
|
|
80
83
|
def main(argv=None) -> int:
|
|
81
84
|
ap = argparse.ArgumentParser(prog="python -m md_cg.mreview",
|
|
82
85
|
description="M1 机械层:候选生成→捆绑→规则装配(只读零写入)")
|