@furongjun1999/dsh-memory 0.4.7 → 0.4.9
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 +130 -47
- package/codebuddy/CODEBUDDY.md +21 -10
- 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/Pi/345/217/257/345/255/246/344/271/240/344/274/230/347/202/271_/347/201/265/346/236/242/345/244/247/350/204/221/346/224/271/350/277/233/344/272/244/346/216/245_20260915.md +144 -0
- package/docs/README.md +111 -0
- package/docs/discipline/harnesses.yaml +226 -152
- package/docs/discipline/templates/full.md.tmpl +61 -58
- package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_LoCoMo_/347/201/265/346/236/242_.md +127 -0
- package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_LoCoMo_/347/201/265/346/236/242_.png +0 -0
- package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_/347/201/265/346/236/242_vs_dejavu_/347/273/237/344/270/200/350/257/204/345/210/206_v7.md +202 -0
- 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/experiments/m4-role-probe/census.py +86 -0
- package/docs/experiments/m4-role-probe/probe.py +89 -0
- package/docs/experiments/mapped_confidence/bench_mapped_conf.py +216 -0
- package/docs/experiments/mapped_confidence/post_check.py +75 -0
- package/docs/experiments/mapped_confidence/repro_thirdparty_tol.py +83 -0
- package/docs/experiments/mapped_confidence/result_mapped_conf.json +215 -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/{ → hive/}/350/234/202/345/267/242/345/267/245/344/275/234/350/256/260/345/277/206_/351/241/271/347/233/256/350/256/241/345/210/222.md +14 -2
- 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/{README → mdcg/README}/350/257/246/347/273/206/347/211/210_v0.4.5.md +631 -625
- package/docs/{ → mdcg/}/344/270/273/344/273/243/347/220/206/345/255/220/344/273/243/347/220/206/350/256/260/345/277/206/346/236/266/346/236/204/350/256/276/350/256/241.md +1 -1
- 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 +263 -0
- package/docs/{ → mdcg/}/345/215/225/345/205/203/350/207/252/346/210/221/351/224/232/347/202/271_/347/263/273/347/273/237/346/217/220/347/244/272/350/257/215/346/240/207/345/207/206_v0.3.md +1 -1
- 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.5.md +236 -0
- package/docs/{ → mdcg/}/346/272/220/347/240/201/347/272/247/346/236/266/346/236/204/345/256/241/350/256/241_GPT/346/211/271/350/257/204/345/257/271/347/205/247_v1.0.md +2 -2
- package/docs/{ → mdcg/}/347/201/265/346/236/242/344/270/211/345/261/202/346/213/206/345/210/206/350/247/204/345/210/222_v0.1.md +181 -181
- 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/}/347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +2 -2
- package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_G4-G8/347/274/272/345/217/243/350/243/201/345/256/232/345/215/225_v0.1.md +1 -1
- package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_/347/264/242/345/274/225/344/270/216/345/267/245/347/250/213/350/247/204/350/214/203/345/214/226_/350/256/241/345/210/222_v0.1.md +4 -4
- package/docs/{ → mdcg/}/350/256/260/345/277/206/346/223/215/344/275/234/347/263/273/347/273/237_MdCGOS/344/270/216MCP/346/216/245/345/205/245_v0.1.md +2 -2
- 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/plans/GridWorld/346/234/200/345/260/217/351/227/255/347/216/257/350/247/204/346/240/274_v0.1.md +176 -0
- package/docs/{ → swarm/}/350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +3 -3
- package/docs/swarm//350/234/202/347/276/244/345/220/214/351/224/231/346/243/200/346/265/213/345/256/236/351/252/214/345/215/217/350/256/256_v0.1.md +242 -0
- package/docs/theory//345/215/225/347/272/277/347/250/213/344/270/216/346/263/250/346/204/217/345/212/233/351/233/206/344/270/255_/346/227/240/344/272/211/350/256/256/347/220/206/350/256/272/346/226/207/346/241/243_v1.0.md +129 -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 +134 -0
- package/docs/theory//346/246/202/345/277/265/345/210/206/345/261/202/345/257/271/351/275/220/350/241/250_v0.1.md +145 -0
- 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 +6 -6
- package/docs/{ → theory/}/347/220/206/350/256/272/344/273/223/346/213/206/345/210/206/344/270/216/347/231/275/347/256/261/347/237/245/350/257/206/345/272/223/345/206/205/350/277/201_v0.1.md +1 -1
- 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 +221 -0
- package/docs/world_model//344/270/226/347/225/214/346/250/241/345/236/213_/347/245/236/347/273/217/347/275/221/347/273/234/345/272/225/345/261/202/346/236/266/346/236/204_v1.0.md +237 -0
- package/docs//345/255/230/347/256/227/344/270/200/344/275/223/346/236/266/346/236/204/345/255/246/344/271/240_/345/244/226/351/203/250/347/220/206/350/256/272/345/257/271/347/205/247/344/270/216/350/267/257/347/272/277/344/272/244/346/216/245_20260916.md +98 -0
- package/docs//345/255/230/347/256/227/344/270/200/344/275/223/347/245/236/347/273/217/347/275/221/347/273/234/346/236/266/346/236/204_/346/200/273/347/272/262/344/270/216/344/272/244/346/216/245_20260916.md +109 -0
- 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 -405
- 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/docs//347/231/275/347/256/261/345/214/226/347/272/262/351/242/206_/344/270/211/351/241/271/347/233/256/345/255/246/344/271/240/346/200/273/346/236/266/346/236/204/344/270/216Ghidra/344/272/244/346/216/245_20260916.md +104 -0
- package/docs//350/256/260/345/277/206/350/257/204/345/256/241/347/263/273/347/273/237_/347/253/213/351/241/271/350/256/276/350/256/241/344/270/216/346/226/275/345/267/245/344/272/244/346/216/245_20260915.md +183 -0
- package/dsh/README.md +34 -1
- 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 +8 -0
- package/lib/hooks.js +27 -24
- 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 +6 -3
- package/lib/lib/mdcg_client.js +6 -5
- package/lib/lib/mutual.js +4 -4
- package/lib/lib/prompt_safety.d.ts +48 -0
- package/lib/lib/prompt_safety.js +62 -0
- package/lib/lib/token_store.js +4 -5
- package/md_cg/audit.py +91 -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 +37 -6
- package/md_cg/bench_p0.py +4 -1
- package/md_cg/bench_progressive.py +61 -10
- 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 +286 -0
- package/md_cg/build_postings.py +73 -0
- package/md_cg/ccgc.py +949 -0
- 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 +727 -0
- package/md_cg/consistency.py +25 -2
- package/md_cg/consolidate.py +53 -2
- package/md_cg/corpus.py +5 -1
- 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 +35 -6
- 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 +34 -4
- package/md_cg/fsutil.py +81 -2
- package/md_cg/hotcache.py +214 -0
- package/md_cg/hyperedge.py +251 -0
- package/md_cg/identity.py +20 -3
- package/md_cg/insight.py +19 -3
- 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 +273 -0
- package/md_cg/linkref.py +281 -0
- package/md_cg/links.py +29 -1
- package/md_cg/mcp_server.py +894 -168
- package/md_cg/md_whitebox.py +53 -1
- package/md_cg/mdcg.py +1205 -41
- package/md_cg/mdcos.py +1060 -76
- package/md_cg/metacognition.py +39 -4
- 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/__init__.py +25 -0
- package/md_cg/mreview/__main__.py +110 -0
- package/md_cg/mreview/bundle.py +178 -0
- package/md_cg/mreview/candidates.py +262 -0
- package/md_cg/mreview/govern.py +694 -0
- package/md_cg/mreview/locate.py +939 -0
- package/md_cg/mreview/pipeline.py +729 -0
- package/md_cg/mreview/rules/duplication.json +21 -0
- package/md_cg/mreview/rules/field_coverage.json +54 -0
- package/md_cg/mreview/rules/source_license.json +21 -0
- package/md_cg/mreview/rules/template_flow.json +21 -0
- package/md_cg/mreview/ruleset.py +253 -0
- package/md_cg/nodefile.py +269 -1
- package/md_cg/pooling.py +23 -1
- package/md_cg/postings.py +298 -0
- package/md_cg/predict.py +113 -15
- package/md_cg/progressive.py +3 -0
- package/md_cg/protect.py +18 -5
- 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 +88 -4
- 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 +68 -3
- package/md_cg/security.py +26 -1
- package/md_cg/self_state.py +65 -2
- package/md_cg/selfreport.py +151 -0
- package/md_cg/semantic/canonical.py +5 -0
- package/md_cg/semantic/en_normalizer.py +364 -295
- 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 +74 -1
- package/md_cg/tasks.py +471 -0
- package/md_cg/test_action_derive.py +203 -0
- package/md_cg/test_audit_rotate.py +270 -0
- 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_branches.py +249 -0
- package/md_cg/test_ccg_perturb.py +1 -1
- package/md_cg/test_ccgc.py +433 -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_conformance.py +343 -0
- package/md_cg/test_d_meta.py +412 -0
- package/md_cg/test_datapath_root.py +188 -0
- package/md_cg/test_en_pipeline.py +24 -0
- package/md_cg/test_gain_gate.py +47 -1
- package/md_cg/test_health_scale.py +173 -0
- package/md_cg/test_hot_cold.py +187 -0
- package/md_cg/test_hyperedge.py +245 -0
- package/md_cg/test_identity_attribution.py +6 -0
- package/md_cg/test_index_durability.py +224 -0
- package/md_cg/test_lifecycle.py +309 -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 +769 -0
- package/md_cg/test_mr_m2.py +587 -0
- package/md_cg/test_mr_m3.py +710 -0
- package/md_cg/test_mr_m4.py +485 -0
- package/md_cg/test_p1.py +1 -1
- package/md_cg/test_p11_consistency.py +1 -1
- package/md_cg/test_p12_metacognition.py +2 -2
- package/md_cg/test_p16_self_state.py +1 -1
- package/md_cg/test_p26_refindex.py +50 -21
- package/md_cg/test_p27_docindex.py +258 -4
- package/md_cg/test_p28_refcheck.py +1 -1
- package/md_cg/test_p29_session_ingest_export.py +1 -1
- package/md_cg/test_p2_mcp.py +7 -1
- package/md_cg/test_p31_insight.py +24 -0
- package/md_cg/test_p38_contextualize.py +1 -1
- package/md_cg/test_p39_vision_evidence.py +1 -1
- package/md_cg/test_p40_refine_worklist.py +1 -1
- package/md_cg/test_p41_evolve_patrol.py +1 -1
- package/md_cg/test_p42_provenance.py +1 -1
- package/md_cg/test_p43_pooling.py +41 -13
- 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 +141 -0
- 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 +367 -0
- package/md_cg/test_role_views.py +354 -0
- package/md_cg/test_tasks.py +409 -0
- package/md_cg/test_tool_face.py +189 -0
- package/md_cg/test_trust.py +361 -0
- package/md_cg/test_twophase.py +286 -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 +214 -0
- package/md_cg/theory.py +17 -2
- package/md_cg/tokens.py +134 -12
- package/md_cg/tool_face.py +261 -0
- package/md_cg/trust.py +943 -0
- package/md_cg/twophase.py +232 -0
- package/md_cg/units.py +665 -0
- package/md_cg/vision_evidence.py +25 -2
- package/md_cg/weights.py +25 -2
- package/md_cg/whitebox.py +33 -2
- package/md_cg/whitebox_kb/data/verify_cache.json +21233 -360
- package/md_cg/whitebox_kb/data/verify_savings.jsonl +5124 -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 +37 -7
- package/md_cg/writepipe.py +543 -0
- 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 +27 -22
- package/src/index.ts +33 -6
- package/src/lib/datapath.ts +211 -13
- package/src/lib/mdcg_client.ts +12 -8
- package/src/lib/mutual.ts +411 -411
- package/src/lib/prompt_safety.ts +62 -0
- package/src/lib/token_store.ts +4 -5
- package/zcode/AGENTS.md +21 -10
- package/zcode/README.md +4 -0
- package/docs//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +0 -221
- /package/docs/{AGI → eval/AGI}/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v1.0.md" +0 -0
- /package/docs/{AGI → eval/AGI}/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v2.0.md" +0 -0
- /package/docs/{ → eval/}/345/256/236/351/252/214/346/226/271/346/241/210_/345/255/246/344/271/240/351/227/255/347/216/257AB/344/270/216/346/250/252/350/257/204_v1.0.md" +0 -0
- /package/docs/{ → eval/}/346/250/252/350/257/204_/345/205/255/345/256/266100/351/242/230/344/270/255/350/213/261/345/217/214/346/237/245_v1.0.md" +0 -0
- /package/docs/{guardrail-charter.md → mdcg/guardrail-charter.md} +0 -0
- /package/docs/{lingshu_tutorial.html → mdcg/lingshu_tutorial.html} +0 -0
- /package/docs/{memory-assessment.html → mdcg/memory-assessment.html} +0 -0
- /package/docs/{memory_score.html → mdcg/memory_score.html} +0 -0
- /package/docs/{memory_score.png → mdcg/memory_score.png} +0 -0
- /package/docs/{release_v0.3.0.md → mdcg/release_v0.3.0.md} +0 -0
- /package/docs/{release_v0.4.5.md → mdcg/release_v0.4.5.md} +0 -0
- /package/docs/{tool_table_v0.3.0.md → mdcg/tool_table_v0.3.0.md} +0 -0
- /package/docs/{ → mdcg/}/344/273/244/347/211/214/344/270/216/350/247/222/350/211/262/346/235/203/350/201/214/345/210/206/347/246/273_v0.1.md" +0 -0
- /package/docs/{ → mdcg/}/347/201/265/346/236/24282/345/267/245/345/205/267_/345/212/237/350/203/275/346/225/264/347/220/206/344/270/216/350/277/201/347/247/273/346/230/240/345/260/204_v0.1.md" +0 -0
- /package/docs/{ → mdcg/}/347/201/265/346/236/242MCP/345/267/245/345/205/267/346/200/273/350/241/250_v3.4.md" +0 -0
- /package/docs/{ → mdcg/}/347/201/265/346/236/242_/350/207/252/346/210/221/345/261/202/345/256/232/344/271/211.md" +0 -0
- /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_MD/347/233/256/345/275/225/346/226/271/346/241/210_v0.1.md" +0 -0
- /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_/346/235/241/344/273/266/347/251/272/351/227/264/345/220/210/346/210/220/344/270/216/347/224/237/346/225/210/346/235/241/344/273/266/345/217/243/345/276/204_v0.1.md" +0 -0
- /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276/344/275/234/344/270/272/350/256/260/345/277/206/346/223/215/344/275/234/347/263/273/347/273/237_/350/257/204/344/274/260/344/270/216/350/267/257/347/272/277_v0.1.md" +0 -0
- /package/docs/{ → plans/}/345/221/275/345/220/215/346/262/273/347/220/206_/351/241/271/347/233/256/350/256/241/345/210/222.md" +0 -0
- /package/docs/{ → plans/}/347/237/245/350/257/206/345/233/276/350/260/261/351/241/271/347/233/256_/344/272/244/346/216/245/346/226/207/346/241/243_20260914.md" +0 -0
- /package/docs/{ → swarm/}/350/234/202/347/276/244/345/244/232/346/231/272/350/203/275/344/275/223_/344/275/277/347/224/250/346/212/245/345/221/212_20260913.md" +0 -0
- /package/docs/{ → swarm/}/350/234/202/347/276/244/345/244/232/346/231/272/350/203/275/344/275/223_/345/212/237/350/203/275/350/257/264/346/230/216_v0.6.md" +0 -0
- /package/docs/{ → swarm/}/350/234/202/347/276/244/347/233/262/345/214/272/346/240/207/350/256/260_v1.0.md" +0 -0
- /package/docs/{ → theory/}/344/277/241/346/201/257/345/267/256/344/270/272/344/273/200/344/271/210/345/277/205/347/204/266/345/255/230/345/234/250/344/270/224/350/207/252/347/204/266/346/211/251/345/244/247.md" +0 -0
- /package/docs/{ → theory/}/346/231/272/350/203/275/347/232/204/345/205/254/347/220/206/345/214/226/345/237/272/347/237/263.md" +0 -0
- /package/docs/{ → theory/}/346/231/272/350/203/275/347/232/204/350/256/244/347/237/245/350/277/207/347/250/213.md" +0 -0
- /package/docs/{ → theory/}/346/231/272/350/203/275/350/256/2723.4.md" +0 -0
- /package/docs/{ → theory/}/347/231/275/347/256/261/346/231/272/350/203/275/346/230/257/344/273/200/344/271/210/357/274/237.md" +0 -0
- /package/docs/{ → theory/}/347/231/275/347/256/261/346/231/272/350/203/275/347/263/273/345/210/227/302/267/347/254/254/344/272/224/347/257/207/357/274/232/350/256/251AI/347/234/237/346/255/243/350/243/205/344/270/212/350/256/260/345/277/206.md" +0 -0
package/md_cg/d_meta.py
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""md_cg · D_meta 投影:边界压力向量(三代理,各自 [0,1],**不合成单值**)
|
|
3
|
+
|
|
4
|
+
理论约束(智能论3.4 §2.7.0 DEV-002 / DEV-002a;工程方案
|
|
5
|
+
`docs/mdcg/D_meta_工程化方案_v0.2.md`):
|
|
6
|
+
|
|
7
|
+
- DEV-002:`D_task` = 图上操作性距离;`D_meta` = 未被建模的现实总量。
|
|
8
|
+
**两者对象不同、数值不互换**。本模块**不参与** `MdCG._compute_d`——
|
|
9
|
+
`D_task` 口径零变更("双 D 落盘"= 并列新增,不是打通)。
|
|
10
|
+
- DEV-002a:可新增 `D_meta` 投影链路,但不能并入 `D_task` 计算公式。
|
|
11
|
+
- 增定律 `d(D_meta)/dt ≥ 0`:本模块只**观测**压力与其趋势,不做"缩小"运算。
|
|
12
|
+
- **不合成单一数值**:任何把三代理加权成一个 `D_meta` 数的企图都违反
|
|
13
|
+
DEV-002a。上层若需单值,只允许**指定单一代理**(见 `pressure()`)。
|
|
14
|
+
|
|
15
|
+
诚实边界(随代码同行,不可省略):
|
|
16
|
+
|
|
17
|
+
1. 三代理只计「**已进入本系统、但未被消化**」的可观测量——**不是**「世界真实
|
|
18
|
+
未发生的事件」,后者不可观测。全部数据来自**已落盘留痕与索引**,
|
|
19
|
+
不重放检索、不读全库正文(热路径约束)。
|
|
20
|
+
2. 本模块是**叶子只读**模块:不 import `mdcg` / `mdcos`(防循环依赖),
|
|
21
|
+
只依赖 `fsutil` 原语与注入的 `cg` 对象(duck-typing);`metacognition`
|
|
22
|
+
惰性导入(调用点内),理由同 `self_state._prediction_face`。
|
|
23
|
+
3. 只读:本模块**没有任何写路径**。
|
|
24
|
+
|
|
25
|
+
开关(三面隔离之一,方案 §2.1/§3):
|
|
26
|
+
|
|
27
|
+
- `MDCG_D_META`:D_meta 计算总闸,**默认开启**;置 `0/false/off/no`
|
|
28
|
+
显式回退(关闭计算 → 上层加分退化为 0,回到旧排序)。
|
|
29
|
+
|
|
30
|
+
三个代理的口径(各自 [0,1],可核验、可复算):
|
|
31
|
+
|
|
32
|
+
| 代理 | 口径 | 数据源(已落盘) |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `events_pressure` | 窗口内新增未消化事件密度 = (近期事件条数 + 探索留痕条数) / (2×window) | `_recent.jsonl` + `_explore.jsonl` 尾部窗口 |
|
|
35
|
+
| `unmodeled_growth` | 0.5×存量饱和率 + 0.5×反思窗口未消化率(BLINDSPOT+DEFER 占比) | 索引 `rejected`/`unresolved` 层计数 + `_reflection.jsonl` 窗口 |
|
|
36
|
+
| `boundary_violation_rate` | 反思窗口内 (REJECT+BLINDSPOT) / 全部资格态 | `_reflection.jsonl` 窗口 `states` 分布 |
|
|
37
|
+
|
|
38
|
+
**query-relative 口径不在本模块**:`_neg_coverage` 之类的命中率需要
|
|
39
|
+
query+results 现场,留在 `MdCG.reflect`(彼处两者都有)。本模块口径
|
|
40
|
+
**库侧 query 无关**,故可在 `autonomy.proposals` 里"每轮一次、循环内复用"。
|
|
41
|
+
"""
|
|
42
|
+
from __future__ import annotations
|
|
43
|
+
|
|
44
|
+
import json
|
|
45
|
+
import os
|
|
46
|
+
|
|
47
|
+
from .fsutil import count_jsonl
|
|
48
|
+
|
|
49
|
+
# ---------------------------------------------------------------- 常量
|
|
50
|
+
|
|
51
|
+
_ENV_FLAG = "MDCG_D_META"
|
|
52
|
+
_FALSY = ("0", "false", "off", "no")
|
|
53
|
+
DEFAULT_WINDOW = 200
|
|
54
|
+
|
|
55
|
+
#: `rejected`/`unresolved` 存量的归一化饱和基准(达到即视为压力 1.0)。
|
|
56
|
+
STOCK_FULL = 100
|
|
57
|
+
|
|
58
|
+
EXPLORE_LOG = "_explore.jsonl"
|
|
59
|
+
RECENT_LOG = "_recent.jsonl"
|
|
60
|
+
REFLECTION_LOG = "_reflection.jsonl"
|
|
61
|
+
|
|
62
|
+
#: 未建模层(负记忆两类:失败/否决 + 未解问题)。
|
|
63
|
+
UNMODELED_LAYERS = ("rejected", "unresolved")
|
|
64
|
+
|
|
65
|
+
#: 资格四态(`judge_qualification` 的 states 取值域)。
|
|
66
|
+
JUDGE_STATES = ("ACCEPT", "REJECT", "DEFER", "BLINDSPOT")
|
|
67
|
+
|
|
68
|
+
PROXY_KEYS = ("events_pressure", "unmodeled_growth", "boundary_violation_rate")
|
|
69
|
+
|
|
70
|
+
_TAIL_BLOCK = 1 << 16 # 尾部反向扫描块(64KiB)
|
|
71
|
+
_CACHE_MAX = 64 # 进程内缓存条目上限(超出即清空,无后台线程)
|
|
72
|
+
_CACHE = {}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# 生效条件:读取环境变量 MDCG_D_META(大小写不敏感、去首尾空白),其值属于 _FALSY 时返回 False,其余(含未设置)返回 True;
|
|
76
|
+
def _enabled() -> bool:
|
|
77
|
+
"""D_meta 计算总闸(默认开启)。"""
|
|
78
|
+
return str(os.environ.get(_ENV_FLAG, "")).strip().lower() not in _FALSY
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# 生效条件:path 不存在或不是文件、或 window<=0 时返回 [];否则从文件末尾按 _TAIL_BLOCK 分块反向读取,直到累计换行数超过 window 或到达文件头,再按行 json.loads 解析尾部 window 条非空记录(解析失败的行跳过、块首半截行跳过);
|
|
82
|
+
def tail_jsonl(path: str, window: int) -> list:
|
|
83
|
+
"""只读 JSONL **尾部最多 window 条**(反向分块,避免全文件 IO)。
|
|
84
|
+
|
|
85
|
+
与 `fsutil.read_jsonl` 的区别:不流式扫全文件,读盘量 ≈ O(window)。
|
|
86
|
+
日志文件可能末尾无换行(写者被杀死),此时最后一行会被解析失败丢弃——
|
|
87
|
+
与 `read_jsonl` 同语义(不猜内容)。
|
|
88
|
+
"""
|
|
89
|
+
window = int(window)
|
|
90
|
+
if window <= 0:
|
|
91
|
+
return []
|
|
92
|
+
try:
|
|
93
|
+
size = os.path.getsize(path)
|
|
94
|
+
except OSError:
|
|
95
|
+
return []
|
|
96
|
+
if size <= 0:
|
|
97
|
+
return []
|
|
98
|
+
data = b""
|
|
99
|
+
pos = size
|
|
100
|
+
try:
|
|
101
|
+
with open(path, "rb") as f:
|
|
102
|
+
while pos > 0 and data.count(b"\n") <= window:
|
|
103
|
+
step = min(_TAIL_BLOCK, pos)
|
|
104
|
+
pos -= step
|
|
105
|
+
f.seek(pos)
|
|
106
|
+
data = f.read(step) + data
|
|
107
|
+
except OSError:
|
|
108
|
+
return []
|
|
109
|
+
out = []
|
|
110
|
+
for raw in data.split(b"\n")[-(window + 1):]:
|
|
111
|
+
raw = raw.strip()
|
|
112
|
+
if not raw:
|
|
113
|
+
continue
|
|
114
|
+
try:
|
|
115
|
+
out.append(json.loads(raw.decode("utf-8", "replace")))
|
|
116
|
+
except ValueError:
|
|
117
|
+
continue
|
|
118
|
+
return out[-window:]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# 生效条件:cg.index 缺失或不是 dict 时返回 0;否则统计其 "nodes" 中各条目 layer 属于 UNMODELED_LAYERS 的条数(entry 非 dict 或 layer 缺失的条目不计);
|
|
122
|
+
def _layer_stock(cg) -> int:
|
|
123
|
+
"""未建模存量:索引中 rejected / unresolved 两层的条目计数(零正文 IO)。"""
|
|
124
|
+
idx = getattr(cg, "index", None)
|
|
125
|
+
nodes = (idx or {}).get("nodes") if isinstance(idx, dict) else None
|
|
126
|
+
if not nodes:
|
|
127
|
+
return 0
|
|
128
|
+
n = 0
|
|
129
|
+
for e in nodes.values():
|
|
130
|
+
if isinstance(e, dict) and e.get("layer") in UNMODELED_LAYERS:
|
|
131
|
+
n += 1
|
|
132
|
+
return n
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# 生效条件:cg 的 reflection_log 属性缺失或为假值时回落 os.path.join(cg.root, REFLECTION_LOG);该文件不存在时返回计数 0;
|
|
136
|
+
def _reflection_count(cg) -> int:
|
|
137
|
+
path = getattr(cg, "reflection_log", "") or os.path.join(
|
|
138
|
+
str(getattr(cg, "root", "") or ""), REFLECTION_LOG)
|
|
139
|
+
try:
|
|
140
|
+
return int(count_jsonl(path))
|
|
141
|
+
except OSError:
|
|
142
|
+
return 0
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# 生效条件:惰性导入 metacognition 并取窗口内资格态分布;metacognition.trace 返回 ok 为假(无反思留痕)或抛异常时返回 {"total": 0, "states": {}};
|
|
146
|
+
def _state_dist(cg, window: int) -> dict:
|
|
147
|
+
"""反思窗口内的资格态分布(复用 metacognition.trace,不重算)。"""
|
|
148
|
+
try:
|
|
149
|
+
from . import metacognition
|
|
150
|
+
tr = metacognition.trace(cg, window=int(window))
|
|
151
|
+
except Exception: # noqa: BLE001
|
|
152
|
+
return {"total": 0, "states": {}}
|
|
153
|
+
if not tr.get("ok"):
|
|
154
|
+
return {"total": 0, "states": {}}
|
|
155
|
+
states = {k: int(v) for k, v in (tr.get("states") or {}).items()}
|
|
156
|
+
return {"total": sum(states.values()), "states": states}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# 生效条件:给定 cg 与 window,返回窗口内新增未消化事件的密度代理([0,1]),= min(1.0, (recent 尾部条数 + explore 尾部条数) / (2*window));
|
|
160
|
+
def events_pressure(cg, window: int = DEFAULT_WINDOW) -> float:
|
|
161
|
+
"""代理一:未被建模的现实总量 → 窗口内新增未消化事件密度。"""
|
|
162
|
+
window = max(1, int(window or DEFAULT_WINDOW))
|
|
163
|
+
recent_path = (getattr(cg, "recent_log", "") or
|
|
164
|
+
os.path.join(str(getattr(cg, "root", "") or ""), RECENT_LOG))
|
|
165
|
+
explore_path = os.path.join(str(getattr(cg, "root", "") or ""), EXPLORE_LOG)
|
|
166
|
+
n = len(tail_jsonl(recent_path, window)) + len(tail_jsonl(explore_path,
|
|
167
|
+
window))
|
|
168
|
+
return round(min(1.0, n / float(2 * window)), 4)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# 生效条件:给定存量 stock 与资格态分布 dist,返回未建模信号增长的归一化代理([0,1]),= min(1.0, 0.5*min(1.0, stock/STOCK_FULL) + 0.5*((BLINDSPOT+DEFER)/max(1,total)));
|
|
172
|
+
def unmodeled_growth(stock: int, dist: dict) -> float:
|
|
173
|
+
"""代理二:未建模信号持续增长 → 存量饱和率 + 反思窗口未消化率 的均值。"""
|
|
174
|
+
stock_rate = min(1.0, max(0, int(stock)) / float(STOCK_FULL))
|
|
175
|
+
states = (dist or {}).get("states") or {}
|
|
176
|
+
total = int((dist or {}).get("total") or 0)
|
|
177
|
+
bad = 0
|
|
178
|
+
for k in ("BLINDSPOT", "DEFER"):
|
|
179
|
+
try:
|
|
180
|
+
bad += int(states.get(k) or 0)
|
|
181
|
+
except (TypeError, ValueError):
|
|
182
|
+
continue
|
|
183
|
+
return round(min(1.0, 0.5 * stock_rate + 0.5 * bad / float(max(1, total))), 4)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
# 生效条件:给定资格态分布 dist,返回边界违反速率代理([0,1]),= (REJECT+BLINDSPOT)/max(1,total)(无分布即 0.0);
|
|
187
|
+
def boundary_violation_rate(dist: dict) -> float:
|
|
188
|
+
"""代理三:边界违反速率 → 反思窗口内 REJECT/BLINDSPOT 占比。"""
|
|
189
|
+
states = (dist or {}).get("states") or {}
|
|
190
|
+
total = int((dist or {}).get("total") or 0)
|
|
191
|
+
bad = 0
|
|
192
|
+
for k in ("REJECT", "BLINDSPOT"):
|
|
193
|
+
try:
|
|
194
|
+
bad += int(states.get(k) or 0)
|
|
195
|
+
except (TypeError, ValueError):
|
|
196
|
+
continue
|
|
197
|
+
return round(bad / float(max(1, total)), 4)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# 生效条件:cg 必需;MDCG_D_META 属于 _FALSY 时三代理恒 0.0、enabled=False 且 note 声明已回退;否则按 (root, 反思条数, 存量, recent 条数, explore 条数, window) 查进程内缓存,未命中则计算三代理并回填(缓存超 _CACHE_MAX 条即清空),返回含四键(三代理 + enabled/window/note);query/results 仅透传留痕于 note(本轮口径为库侧 query 无关,不计入数值);
|
|
201
|
+
def compute(cg, query=None, results=None, window: int = DEFAULT_WINDOW,
|
|
202
|
+
now=None) -> dict:
|
|
203
|
+
"""边界压力向量(三代理各自 [0,1],**不合成单一 D_meta 数值**)。
|
|
204
|
+
|
|
205
|
+
返回:`{"events_pressure", "unmodeled_growth", "boundary_violation_rate",
|
|
206
|
+
"enabled", "window", "note"}`。
|
|
207
|
+
|
|
208
|
+
- `enabled=False`(`MDCG_D_META` 显式关闭)时三值为 0.0 且 `note` 声明已回退。
|
|
209
|
+
- `query` / `results` 为**接口对称性**保留:query-relative 的 `_neg_coverage`
|
|
210
|
+
命中留 `reflect`(彼处有现场);本模块口径库侧 query 无关,
|
|
211
|
+
故可在 `proposals` 每轮一次、循环内复用。
|
|
212
|
+
- 纯读 + 进程内缓存(key 含两日志条数),无写路径、无后台线程、无网络。
|
|
213
|
+
"""
|
|
214
|
+
window = max(1, int(window or DEFAULT_WINDOW))
|
|
215
|
+
if not _enabled():
|
|
216
|
+
return {"events_pressure": 0.0, "unmodeled_growth": 0.0,
|
|
217
|
+
"boundary_violation_rate": 0.0, "enabled": False,
|
|
218
|
+
"window": window,
|
|
219
|
+
"note": ("MDCG_D_META 已显式关闭:D_meta 计算回退,三代理恒 0.0"
|
|
220
|
+
"(上层加分退化 → 旧排序)")}
|
|
221
|
+
root = str(getattr(cg, "root", "") or "")
|
|
222
|
+
refl_n = _reflection_count(cg)
|
|
223
|
+
stock = _layer_stock(cg)
|
|
224
|
+
recent_path = (getattr(cg, "recent_log", "") or
|
|
225
|
+
os.path.join(root, RECENT_LOG))
|
|
226
|
+
explore_path = os.path.join(root, EXPLORE_LOG)
|
|
227
|
+
recent_n = count_jsonl(recent_path)
|
|
228
|
+
explore_n = count_jsonl(explore_path)
|
|
229
|
+
key = (root, refl_n, stock, recent_n, explore_n, window)
|
|
230
|
+
hit = _CACHE.get(key)
|
|
231
|
+
if hit is None:
|
|
232
|
+
dist = _state_dist(cg, window)
|
|
233
|
+
hit = {
|
|
234
|
+
"events_pressure": events_pressure(cg, window=window),
|
|
235
|
+
"unmodeled_growth": unmodeled_growth(stock, dist),
|
|
236
|
+
"boundary_violation_rate": boundary_violation_rate(dist),
|
|
237
|
+
}
|
|
238
|
+
if len(_CACHE) >= _CACHE_MAX:
|
|
239
|
+
_CACHE.clear()
|
|
240
|
+
_CACHE[key] = hit
|
|
241
|
+
note = ("边界压力向量:三代理各自 [0,1]、**不合成单值**(DEV-002a);"
|
|
242
|
+
"只计「进入系统但未被消化」的事件,不是世界真实未发生事件;"
|
|
243
|
+
"不参与 _compute_d(D_task 口径零变更)")
|
|
244
|
+
if query is not None:
|
|
245
|
+
note += ";query 已透传(本轮口径为库侧 query 无关,不计入数值)"
|
|
246
|
+
return {
|
|
247
|
+
"events_pressure": hit["events_pressure"],
|
|
248
|
+
"unmodeled_growth": hit["unmodeled_growth"],
|
|
249
|
+
"boundary_violation_rate": hit["boundary_violation_rate"],
|
|
250
|
+
"enabled": True, "window": window,
|
|
251
|
+
"note": note,
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
# 生效条件:vec 为 dict 且其 key(缺省 "unmodeled_growth")的值为 int/float 时返回裁剪到 [0,1] 的 float,否则返回 0.0;
|
|
256
|
+
def pressure(vec, key: str = "unmodeled_growth") -> float:
|
|
257
|
+
"""取**单一指定代理**作单值用途(禁止三代理加权合成,DEV-002a)。"""
|
|
258
|
+
if not isinstance(vec, dict):
|
|
259
|
+
return 0.0
|
|
260
|
+
v = vec.get(key)
|
|
261
|
+
if isinstance(v, bool) or not isinstance(v, (int, float)):
|
|
262
|
+
return 0.0
|
|
263
|
+
return round(max(0.0, min(1.0, float(v))), 4)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
# 生效条件:prev 或 cur 为假值时返回 None;否则返回三代理的逐字段差(cur-prev,round 4)字典;
|
|
267
|
+
def diff(prev, cur) -> dict:
|
|
268
|
+
"""逐字段差(供 `reflect` 落 `d_meta_delta`;首条无前值时返回 None)。"""
|
|
269
|
+
if not prev or not cur:
|
|
270
|
+
return None
|
|
271
|
+
out = {}
|
|
272
|
+
for k in PROXY_KEYS:
|
|
273
|
+
try:
|
|
274
|
+
out[k] = round(float(cur.get(k) or 0.0) - float(prev.get(k) or 0.0), 4)
|
|
275
|
+
except (TypeError, ValueError):
|
|
276
|
+
out[k] = 0.0
|
|
277
|
+
return out
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
# 生效条件:不适用(无必需形参与分支),恒定返回本模块的自描述 dict(module/role/theory/proxies/constraints/knobs);
|
|
281
|
+
def catalog() -> dict:
|
|
282
|
+
"""自描述:三代理口径、诚实边界与开关(防文档与实现漂移)。"""
|
|
283
|
+
return {
|
|
284
|
+
"module": "d_meta",
|
|
285
|
+
"role": "D_meta 结构性投影(边界压力向量,三代理各自 [0,1],不合成单值)",
|
|
286
|
+
"theory": {
|
|
287
|
+
"dev_002": "D_task=图上操作性距离;D_meta=未被建模的现实总量——不互换",
|
|
288
|
+
"dev_002a": "可新增投影链路,不得并入 _compute_d;不得加权合成单值",
|
|
289
|
+
"increasing": "d(D_meta)/dt ≥ 0 → 只观测趋势,不做缩小运算",
|
|
290
|
+
"boundary": "审美/创造/非任务探索不由 ΔD·σ(Gain) 定价 → 只做排序加分",
|
|
291
|
+
},
|
|
292
|
+
"proxies": {
|
|
293
|
+
"events_pressure": "窗口内新增未消化事件密度(_recent + _explore 尾窗)",
|
|
294
|
+
"unmodeled_growth": ("0.5×存量饱和率(rejected+unresolved / %d)"
|
|
295
|
+
" + 0.5×反思窗口未消化率(BLINDSPOT+DEFER)"
|
|
296
|
+
% STOCK_FULL),
|
|
297
|
+
"boundary_violation_rate": "反思窗口内 (REJECT+BLINDSPOT)/全部资格态",
|
|
298
|
+
},
|
|
299
|
+
"default_proxy_for_single_value": "unmodeled_growth",
|
|
300
|
+
"knobs": {"env_gate": _ENV_FLAG, "default_enabled": True,
|
|
301
|
+
"default_window": DEFAULT_WINDOW,
|
|
302
|
+
"stock_full": STOCK_FULL},
|
|
303
|
+
"constraints": [
|
|
304
|
+
"只读:无写路径;不 import mdcg / mdcos(叶子模块,防循环依赖)",
|
|
305
|
+
"不参与 _compute_d(D_task 口径零变更)",
|
|
306
|
+
"不合成单一 D_meta 数值(DEV-002a);单值只允许指定单一代理",
|
|
307
|
+
"代理只计「进入系统但未被消化」的事件,不是世界真实未发生事件",
|
|
308
|
+
],
|
|
309
|
+
"faces": ["compute", "pressure", "diff", "tail_jsonl", "catalog"],
|
|
310
|
+
}
|
package/md_cg/datapath.py
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""datapath.py · 灵枢数据根解析(记忆写入路径可配置)
|
|
3
3
|
|
|
4
|
+
与 node 侧 `src/lib/datapath.ts` **同口径**——两侧读同一份
|
|
5
|
+
`<用户级状态根>/paths.json`(旧 `<插件仓>/data/paths.json` 兼容读)。
|
|
6
|
+
|
|
4
7
|
解析优先级(高 → 低):
|
|
5
8
|
1. 环境变量 `MDCG_DATA_ROOT`(数据根)/ `MDCG_ROOT`(认知图根)
|
|
6
|
-
2. 用户可编辑的路径文件
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
2. 用户可编辑的路径文件 `paths.json` 的 "data_root" / "root"
|
|
10
|
+
(位置:`<用户级状态根>/paths.json`;旧 `<插件仓>/data/paths.json` 兼容读)
|
|
11
|
+
3. 默认:`<用户级状态根>/data`(**插件包目录之外**,与进程 cwd 解耦)
|
|
12
|
+
|
|
13
|
+
为什么默认**不**锚定「插件仓自身 data/」(issue #18 相邻问题,数据丢失级):
|
|
14
|
+
DSH 插件按 hoisted 布局装在 `<profile>/node_modules/<pkg>`,`pnpm` 更新该包会
|
|
15
|
+
**整个替换包目录**——运行时数据落在包内时,每次更新成功即连目录一起删掉
|
|
16
|
+
(实机实证:`data/` 54 文件 → 0,46 条记忆节点靠人工备份回填);`paths.json`
|
|
17
|
+
同址,用户配置一并丢失。故默认数据根与配置文件一律落**用户级状态根**
|
|
18
|
+
(见 state_root()),与包目录彻底解耦。
|
|
19
|
+
|
|
20
|
+
为什么默认不锚定 `data/mdcg` 相对路径:
|
|
10
21
|
相对路径随进程 cwd 漂移——node 侧插件与 python 侧脚本 cwd 不同
|
|
11
|
-
(历史事故:DSH 进程 cwd
|
|
12
|
-
与插件仓内的 `data/`
|
|
22
|
+
(历史事故:DSH 进程 cwd 在私有库目录时,记忆真源落到 `[私有库]/data/mdcg`,
|
|
23
|
+
与插件仓内的 `data/` 分裂成两处)。
|
|
13
24
|
|
|
14
25
|
设计边界:
|
|
15
|
-
-
|
|
16
|
-
|
|
26
|
+
- 本模块只决定「**新写入去哪**」。唯一的搬运是 `migrate_legacy_data()`:
|
|
27
|
+
默认数据根生效且旧包内位置仍有内容时,一次性**复制**(不删除、不覆盖)
|
|
28
|
+
到用户级位置——见该函数注释。
|
|
17
29
|
- 纯标准库、无包内相对导入——可被 `sys.path` 以顶层模块方式加载,
|
|
18
30
|
绕开 `md_cg/__init__.py` 的重依赖。
|
|
19
31
|
|
|
@@ -21,30 +33,82 @@
|
|
|
21
33
|
from datapath import data_root, mdcg_root, state_dir # scripts/ 内
|
|
22
34
|
python md_cg/datapath.py # 打印当前解析结果
|
|
23
35
|
python md_cg/datapath.py --set-root D:/x/data # 写入 paths.json(用户可改)
|
|
36
|
+
python md_cg/datapath.py --migrate-legacy # 把旧包内数据复制到用户级根
|
|
24
37
|
"""
|
|
25
38
|
from __future__ import annotations
|
|
26
39
|
|
|
27
40
|
import json
|
|
28
41
|
import os
|
|
42
|
+
import shutil
|
|
29
43
|
|
|
30
44
|
ENV_DATA_ROOT = "MDCG_DATA_ROOT"
|
|
31
45
|
ENV_MDCG_ROOT = "MDCG_ROOT"
|
|
46
|
+
ENV_STATE_ROOT = "MDCG_STATE_ROOT"
|
|
32
47
|
|
|
33
48
|
|
|
49
|
+
# 生效条件:无入参,恒返回本文件 __file__ 绝对路径上溯两级得到的插件仓根目录。
|
|
34
50
|
def plugin_root() -> str:
|
|
35
51
|
"""插件仓根目录(本文件位于 <root>/md_cg/datapath.py)。"""
|
|
36
52
|
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
37
53
|
|
|
38
54
|
|
|
55
|
+
# 生效条件:无入参;ENV_STATE_ROOT 环境变量为非空真值时返回其 abspath,为空串/未设时若 DSH_HOME 为非空真值则返回其 abspath 下 ".dsh-memory",两者皆无则返回 ~/.dsh/.dsh-memory 的 abspath。
|
|
56
|
+
def state_root() -> str:
|
|
57
|
+
"""用户级状态根(**插件包目录之外**):路径配置与默认数据根的落点。
|
|
58
|
+
|
|
59
|
+
`DSH_HOME` **未必**由宿主注入(本仓 `dsh/dsh-web-start.bat` 自行 set),
|
|
60
|
+
故家目录兜底;`~/.dsh` 是本插件既有约定(node 侧调试日志同址)。
|
|
61
|
+
"""
|
|
62
|
+
env = os.environ.get(ENV_STATE_ROOT)
|
|
63
|
+
if env:
|
|
64
|
+
return os.path.abspath(env)
|
|
65
|
+
dsh_home = os.environ.get("DSH_HOME")
|
|
66
|
+
if dsh_home:
|
|
67
|
+
return os.path.join(os.path.abspath(dsh_home), ".dsh-memory")
|
|
68
|
+
return os.path.join(os.path.expanduser("~"), ".dsh", ".dsh-memory")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# 生效条件:无入参,恒返回 plugin_root() 下 "data" 的拼接路径(旧版落点,更新时被整目录替换,只作兼容读与迁移源)。
|
|
72
|
+
def legacy_data_root() -> str:
|
|
73
|
+
"""旧版落点(插件包内 `data/`)——更新时会被整个替换。"""
|
|
74
|
+
return os.path.join(plugin_root(), "data")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# 生效条件:无入参,恒返回 legacy_data_root() 下 "paths.json" 的拼接路径。
|
|
78
|
+
def legacy_paths_file() -> str:
|
|
79
|
+
"""旧版路径配置文件位置(包内,兼容读)。"""
|
|
80
|
+
return os.path.join(legacy_data_root(), "paths.json")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# 生效条件:两个路径参数经 normpath+normcase 规范化后相等时返回 True,否则 False(Windows 大小写不敏感)。
|
|
84
|
+
def _same_path(a: str, b: str) -> bool:
|
|
85
|
+
return (os.path.normcase(os.path.normpath(a)) ==
|
|
86
|
+
os.path.normcase(os.path.normpath(b)))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# 生效条件:无入参;<state_root()>/paths.json 存在(isfile)时返回之,不存在而 legacy_paths_file() 存在时返回旧件,两者皆不存在时返回新位置路径(首次写入时创建),不受 data_root() 取值影响。
|
|
39
90
|
def paths_file() -> str:
|
|
40
|
-
"""
|
|
91
|
+
"""用户可编辑的路径配置文件——用户级优先,旧包内位置兼容读。
|
|
41
92
|
|
|
42
|
-
|
|
43
|
-
|
|
93
|
+
新位置:`<用户级状态根>/paths.json`(随包更新不丢)。
|
|
94
|
+
旧位置:`<插件仓>/data/paths.json`(旧版约定,仅当新位置不存在时读它,
|
|
95
|
+
已存在新件则新件说了算——不做自动复制,避免旧件后续编辑静默失效)。
|
|
44
96
|
"""
|
|
45
|
-
|
|
97
|
+
current = os.path.join(state_root(), "paths.json")
|
|
98
|
+
if os.path.isfile(current):
|
|
99
|
+
return current
|
|
100
|
+
legacy = legacy_paths_file()
|
|
101
|
+
return legacy if os.path.isfile(legacy) else current
|
|
46
102
|
|
|
47
103
|
|
|
104
|
+
# 生效条件:无入参;paths_file() 的所在目录与 state_root() 同路径时返回 "user",否则返回 "legacy"(兼容读旧包内位置)。
|
|
105
|
+
def paths_file_source() -> str:
|
|
106
|
+
"""生效中的 paths.json 位置来源:`user` / `legacy`。"""
|
|
107
|
+
return "user" if _same_path(os.path.dirname(paths_file()),
|
|
108
|
+
state_root()) else "legacy"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# 生效条件:无入参;paths_file() 的 JSON 顶层为 dict 时返回该 dict,JSON 解析或读取抛任何异常、或顶层非 dict 时返回 {}。
|
|
48
112
|
def _user_paths() -> dict:
|
|
49
113
|
try:
|
|
50
114
|
with open(paths_file(), encoding="utf-8") as f:
|
|
@@ -54,11 +118,77 @@ def _user_paths() -> dict:
|
|
|
54
118
|
return {}
|
|
55
119
|
|
|
56
120
|
|
|
121
|
+
# 生效条件:无入参,恒返回 state_root() 下 "data" 的拼接路径(插件包目录之外,更新不触碰)。
|
|
57
122
|
def default_data_root() -> str:
|
|
58
|
-
"""默认数据根 =
|
|
59
|
-
return os.path.join(
|
|
123
|
+
"""默认数据根 = 用户级状态根下 data/。"""
|
|
124
|
+
return os.path.join(state_root(), "data")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# 生效条件:p 为目录且其下无任何条目时返回 True,p 不存在/是文件/OSError 时返回 False。
|
|
128
|
+
def _is_empty_dir(p: str) -> bool:
|
|
129
|
+
try:
|
|
130
|
+
return os.path.isdir(p) and not os.listdir(p)
|
|
131
|
+
except OSError:
|
|
132
|
+
return False
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# 生效条件:无入参;data_root() 与 default_data_root() 不同路径时返回 {ran:False, reason:"数据根为显式配置(env/paths.json),不迁移", from, to, copied:0, failed:[]};相同则继续——legacy_data_root() 非目录时返回 reason="旧位置不存在(多为更新时已随包目录被替换)",其下无条目(除 paths.json 外)时返回 reason="旧位置无数据",否则把其余顶层条目逐个复制到 default_data_root() 下(目标条目已存在且非空目录则跳过;只复制不删除、不覆盖;单个条目异常记入 failed 不抛),返回 ran=(copied>0)、copied、failed 与失败时的 reason("目标不可写" 或 "新位置已有数据,未覆盖")。
|
|
136
|
+
def migrate_legacy_data() -> dict:
|
|
137
|
+
"""一次性迁移:把旧版包内 `data/` 的数据面复制到用户级默认数据根。
|
|
60
138
|
|
|
139
|
+
触发条件(三条同时满足,缺一不动):
|
|
140
|
+
① 数据根未被显式配置(env `MDCG_DATA_ROOT` / paths.json 的 "data_root"
|
|
141
|
+
都未设,即 data_root() 恰为默认值)——显式配置是用户的决定;
|
|
142
|
+
② 旧位置存在;③ 目标顶层条目不存在或为空目录(不覆盖、不合并)。
|
|
61
143
|
|
|
144
|
+
`paths.json` 不复制(配置走 paths_file() 兼容读,复制会制造两说)。
|
|
145
|
+
任何异常逐项吞掉并记入 `failed`——迁移是增益,不该成为启动失败源。
|
|
146
|
+
|
|
147
|
+
边界(如实):pnpm 更新是**先替换包目录再启动新代码**,旧数据在升级瞬间即
|
|
148
|
+
已消失,本函数只能接手「旧位置那时仍在」的情形;已在升级中丢掉的数据无法
|
|
149
|
+
由此恢复——发布说明须提示 0.4.8 及更早用户升级前备份包内 `data/`。
|
|
150
|
+
"""
|
|
151
|
+
frm = legacy_data_root()
|
|
152
|
+
to = default_data_root()
|
|
153
|
+
out = {"ran": False, "reason": "", "from": frm, "to": to,
|
|
154
|
+
"copied": 0, "failed": []}
|
|
155
|
+
if not _same_path(data_root(), to):
|
|
156
|
+
out["reason"] = "数据根为显式配置(env/paths.json),不迁移"
|
|
157
|
+
return out
|
|
158
|
+
if not os.path.isdir(frm):
|
|
159
|
+
out["reason"] = "旧位置不存在(多为更新时已随包目录被替换)"
|
|
160
|
+
return out
|
|
161
|
+
try:
|
|
162
|
+
names = [n for n in os.listdir(frm) if n != "paths.json"]
|
|
163
|
+
except OSError:
|
|
164
|
+
out["reason"] = "旧位置不可读"
|
|
165
|
+
return out
|
|
166
|
+
if not names:
|
|
167
|
+
out["reason"] = "旧位置无数据"
|
|
168
|
+
return out
|
|
169
|
+
for name in names:
|
|
170
|
+
src = os.path.join(frm, name)
|
|
171
|
+
dst = os.path.join(to, name)
|
|
172
|
+
# 新位置已有实质内容 → 跳过(宁可少搬,不可覆盖)
|
|
173
|
+
if os.path.exists(dst) and not _is_empty_dir(dst):
|
|
174
|
+
continue
|
|
175
|
+
try:
|
|
176
|
+
os.makedirs(to, exist_ok=True)
|
|
177
|
+
if os.path.isdir(src):
|
|
178
|
+
shutil.copytree(src, dst, dirs_exist_ok=True)
|
|
179
|
+
else:
|
|
180
|
+
shutil.copy2(src, dst)
|
|
181
|
+
out["copied"] += 1
|
|
182
|
+
except Exception: # noqa: BLE001 —— 迁移不得成为启动失败源
|
|
183
|
+
out["failed"].append(name)
|
|
184
|
+
out["ran"] = out["copied"] > 0
|
|
185
|
+
if not out["ran"]:
|
|
186
|
+
out["reason"] = ("目标不可写" if out["failed"]
|
|
187
|
+
else "新位置已有数据,未覆盖")
|
|
188
|
+
return out
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# 生效条件:无入参;ENV_DATA_ROOT 环境变量为非空真值时返回其 abspath,为空串/未设时若 paths.json 的 "data_root" 为真值则按其是否为绝对路径决定直接 abspath 还是拼 plugin_root() 后 abspath,该键缺失或为假值时回落 default_data_root()。
|
|
62
192
|
def data_root() -> str:
|
|
63
193
|
"""数据根(记忆/账本/运行态的父目录)。"""
|
|
64
194
|
env = os.environ.get(ENV_DATA_ROOT)
|
|
@@ -71,6 +201,7 @@ def data_root() -> str:
|
|
|
71
201
|
return default_data_root()
|
|
72
202
|
|
|
73
203
|
|
|
204
|
+
# 生效条件:无入参;ENV_MDCG_ROOT 环境变量为非空真值时返回其 abspath,为空串/未设时若 paths.json 的 "root" 为真值则按其是否为绝对路径决定直接 abspath 还是拼 plugin_root() 后 abspath,该键缺失或为假值时返回 data_root() 下 "mdcg" 的拼接路径。
|
|
74
205
|
def mdcg_root() -> str:
|
|
75
206
|
"""认知图(记忆唯一真源)根目录。"""
|
|
76
207
|
env = os.environ.get(ENV_MDCG_ROOT)
|
|
@@ -83,6 +214,7 @@ def mdcg_root() -> str:
|
|
|
83
214
|
return os.path.join(data_root(), "mdcg")
|
|
84
215
|
|
|
85
216
|
|
|
217
|
+
# 生效条件:parts 非空时路径为 data_root() 与各 part 的 join,parts 为空时路径即 data_root();create 为真值(默认 True)时对该路径 makedirs(exist_ok=True),create 为假值时只返回路径不建目录。
|
|
86
218
|
def state_dir(*parts: str, create: bool = True) -> str:
|
|
87
219
|
"""运行态子目录(日志/队列/草稿…),默认挂在数据根下。"""
|
|
88
220
|
p = os.path.join(data_root(), *parts) if parts else data_root()
|
|
@@ -91,51 +223,88 @@ def state_dir(*parts: str, create: bool = True) -> str:
|
|
|
91
223
|
return p
|
|
92
224
|
|
|
93
225
|
|
|
226
|
+
# 生效条件:name 依次拼成 data_root()/name、plugin_root()/name、dirname(plugin_root())/[私有归档根]/_archive/ctp-aeis-data/name 三个候选,仅保留其中 os.path.isfile 为真的项并按此顺序返回列表。
|
|
227
|
+
def archive_root() -> str | None:
|
|
228
|
+
"""私有侧归档根(公开仓不含私有库名):本机配置提供,未配置则没有该候选。
|
|
229
|
+
|
|
230
|
+
取值顺序:环境变量 MDCG_ARCHIVE_ROOT -> 插件仓同级的 .mdcg_archive_root 文件内容。
|
|
231
|
+
"""
|
|
232
|
+
value = os.environ.get("MDCG_ARCHIVE_ROOT", "").strip()
|
|
233
|
+
if value:
|
|
234
|
+
return value
|
|
235
|
+
marker = os.path.join(os.path.dirname(plugin_root()), ".mdcg_archive_root")
|
|
236
|
+
if os.path.isfile(marker):
|
|
237
|
+
try:
|
|
238
|
+
with open(marker, "r", encoding="utf-8") as fh:
|
|
239
|
+
text = fh.read().strip()
|
|
240
|
+
except OSError:
|
|
241
|
+
return None
|
|
242
|
+
return text or None
|
|
243
|
+
return None
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# 生效条件:给定 name 时按 data_root()/name、plugin_root()/name 顺序拼接候选,仅当 archive_root() 不为 None 才追加其下 _archive/ctp-aeis-data/name,最终只返回其中 os.path.isfile 为真的路径(其余被过滤掉),故全都不满足时返回空列表。
|
|
94
247
|
def legacy_candidates(name: str) -> list:
|
|
95
248
|
"""历史位置候选(只读兼容:三仓分离前的校验缓存等)。
|
|
96
249
|
|
|
97
250
|
仅用于「读旧件」,顺序:数据根 → 插件仓根 → 归档区。
|
|
98
251
|
"""
|
|
99
252
|
out = [os.path.join(data_root(), name),
|
|
100
|
-
os.path.join(plugin_root(), name)
|
|
101
|
-
|
|
102
|
-
|
|
253
|
+
os.path.join(plugin_root(), name)]
|
|
254
|
+
archive = archive_root()
|
|
255
|
+
if archive is not None:
|
|
256
|
+
out.append(os.path.join(archive, "_archive", "ctp-aeis-data", name))
|
|
103
257
|
return [p for p in out if os.path.isfile(p)]
|
|
104
258
|
|
|
105
259
|
|
|
260
|
+
# 生效条件:name 对应的 legacy_candidates(name) 列表非空时返回其首个元素,为空列表时返回 None。
|
|
106
261
|
def find_existing(name: str) -> str | None:
|
|
107
262
|
"""在数据根/插件仓/归档区中找已存在的同名文件,找不到返回 None。"""
|
|
108
263
|
hits = legacy_candidates(name)
|
|
109
264
|
return hits[0] if hits else None
|
|
110
265
|
|
|
111
266
|
|
|
267
|
+
# 生效条件:无入参;恒返回含 plugin_root/state_root/data_root/mdcg_root/default_data_root/is_default/source/paths_file/paths_file_source/legacy_data_root/legacy_data_exists/data_root_exists/mdcg_root_exists 的字典,其中 source 按 ENV_DATA_ROOT 非空取 "env:MDCG_DATA_ROOT" → 否则 ENV_MDCG_ROOT 非空取 "env:MDCG_MDCG_ROOT" → 否则 _user_paths() 为非空 dict 取 "paths.json(用户级)" 或 "paths.json(兼容读旧包内位置)"(按 paths_file_source())→ 否则取 "default(用户级状态根 data/)"。
|
|
112
268
|
def describe() -> dict:
|
|
113
269
|
"""当前解析结果的完整快照(供心跳/日志留痕)。"""
|
|
114
270
|
dr = data_root()
|
|
115
271
|
mr = mdcg_root()
|
|
272
|
+
pf_src = paths_file_source()
|
|
116
273
|
return {
|
|
117
274
|
"plugin_root": plugin_root(),
|
|
275
|
+
"state_root": state_root(),
|
|
118
276
|
"data_root": dr,
|
|
119
277
|
"mdcg_root": mr,
|
|
120
278
|
"default_data_root": default_data_root(),
|
|
121
|
-
"is_default": (
|
|
122
|
-
os.path.normcase(default_data_root())),
|
|
279
|
+
"is_default": _same_path(dr, default_data_root()),
|
|
123
280
|
"source": ("env:" + ENV_DATA_ROOT if os.environ.get(ENV_DATA_ROOT)
|
|
124
281
|
else ("env:" + ENV_MDCG_ROOT if os.environ.get(ENV_MDCG_ROOT)
|
|
125
|
-
else ("paths.json" if
|
|
282
|
+
else (("paths.json(用户级)" if pf_src == "user"
|
|
283
|
+
else "paths.json(兼容读旧包内位置)")
|
|
284
|
+
if _user_paths()
|
|
285
|
+
else "default(用户级状态根 data/)"))),
|
|
126
286
|
"paths_file": paths_file(),
|
|
287
|
+
"paths_file_source": pf_src,
|
|
288
|
+
"legacy_data_root": legacy_data_root(),
|
|
289
|
+
"legacy_data_exists": os.path.isdir(legacy_data_root()),
|
|
127
290
|
"data_root_exists": os.path.isdir(dr),
|
|
128
291
|
"mdcg_root_exists": os.path.isdir(mr),
|
|
129
292
|
}
|
|
130
293
|
|
|
131
294
|
|
|
295
|
+
# 生效条件:path 为传入字符串(写入前反斜杠替换为 "/"),key 默认 "data_root"(传入时写入该键名);先确保 <state_root()> 存在,读取 _user_paths()(可能来自旧包内位置的兼容读,异常时为 {},故旧配置在首次改写时被带到新位置并从此由新件说了算)并补 "_comment",再以该内容覆写 <state_root()>/paths.json 并返回该路径。
|
|
132
296
|
def set_user_root(path: str, key: str = "data_root") -> str:
|
|
133
|
-
"""
|
|
134
|
-
|
|
297
|
+
"""把用户选择的路径写入**用户级** paths.json(不存在则创建)。返回文件路径。
|
|
298
|
+
|
|
299
|
+
永远写新位置(不写旧包内那件)——旧位置会随包更新被删除,写进去等于
|
|
300
|
+
用户设置迟早丢失;旧件的既有取值经 _user_paths() 带入新件,不丢配置。
|
|
301
|
+
"""
|
|
302
|
+
pf = os.path.join(state_root(), "paths.json")
|
|
135
303
|
os.makedirs(os.path.dirname(pf), exist_ok=True)
|
|
136
304
|
d = _user_paths()
|
|
137
305
|
d.setdefault("_comment",
|
|
138
|
-
"
|
|
306
|
+
"灵枢记忆写入路径(用户可改)。删掉本文件即回落到用户级默认数据根"
|
|
307
|
+
"(~/.dsh/.dsh-memory/data)。")
|
|
139
308
|
d[key] = path.replace("\\", "/")
|
|
140
309
|
with open(pf, "w", encoding="utf-8") as f:
|
|
141
310
|
json.dump(d, f, ensure_ascii=False, indent=2)
|
|
@@ -149,12 +318,18 @@ if __name__ == "__main__":
|
|
|
149
318
|
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
150
319
|
ap = argparse.ArgumentParser(description="灵枢数据根解析与设置")
|
|
151
320
|
ap.add_argument("--set-root", metavar="PATH",
|
|
152
|
-
help="把数据根写入
|
|
321
|
+
help="把数据根写入 <用户级状态根>/paths.json(用户可改)")
|
|
153
322
|
ap.add_argument("--set-mdcg-root", metavar="PATH",
|
|
154
|
-
help="把认知图根写入
|
|
323
|
+
help="把认知图根写入 <用户级状态根>/paths.json")
|
|
324
|
+
ap.add_argument("--migrate-legacy", action="store_true",
|
|
325
|
+
help="把旧版包内 data/ 的数据面复制到用户级默认数据根"
|
|
326
|
+
"(只复制不删除;默认数据根被显式配置时不动作)")
|
|
155
327
|
a = ap.parse_args()
|
|
156
328
|
if a.set_root:
|
|
157
329
|
print("written:", set_user_root(a.set_root, "data_root"))
|
|
158
330
|
if a.set_mdcg_root:
|
|
159
331
|
print("written:", set_user_root(a.set_mdcg_root, "root"))
|
|
160
|
-
|
|
332
|
+
if a.migrate_legacy:
|
|
333
|
+
print("migrate:", json.dumps(migrate_legacy_data(),
|
|
334
|
+
ensure_ascii=False))
|
|
335
|
+
print(json.dumps(describe(), ensure_ascii=False, indent=2))
|