@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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""盲区消解票据(阶段三 §5.4):BLINDSPOT/DEFER 盲区 → 四类消解票据(任务卡形态)挂认知图。
|
|
3
|
+
|
|
4
|
+
四类分类判据(确定性、声明式、可审计,不做语义猜测):
|
|
5
|
+
task — 盲区 query 精确命中某 unresolved 层节点正文首行 → 直接立工程任务卡
|
|
6
|
+
grilling — defer 主导(defer > blindspot,信息不完整须澄清);执行通道=宿主侧
|
|
7
|
+
访谈(grill),md_cg 库内无访谈工具,本模块只建卡不越权代答(边界如实)
|
|
8
|
+
research — blindspot >= 3(反复未知)→ 研究议题(检索/调研补证)
|
|
9
|
+
prototype — 其余 → 最小探针实验验证
|
|
10
|
+
|
|
11
|
+
幂等:tasks.upsert 同 slug 即同任务,重复生成不新建卡(updated 计数)。
|
|
12
|
+
依赖挂接:票据即任务节点(认知图节点天然在图上、可检索)。「升级为正式工程
|
|
13
|
+
任务时的机械 depends_on 边」由使用者在该卡更新时显式填写——本模块不伪造
|
|
14
|
+
工程边,消解路径以正文声明。
|
|
15
|
+
预演:apply=False 只出清单不落库(与 learn/reconstruct 的 opt-in 同构,
|
|
16
|
+
默认链路零变更)。
|
|
17
|
+
"""
|
|
18
|
+
from . import metacognition, tasks
|
|
19
|
+
|
|
20
|
+
TICKET_TYPES = ("research", "prototype", "grilling", "task")
|
|
21
|
+
|
|
22
|
+
_RESOLVE = {
|
|
23
|
+
"research": "检索/调研补证(外部研究系列吸收流程),产出知识节点后复核 gap_hint",
|
|
24
|
+
"prototype": "构造最小探针实验验证,结论回写认知图",
|
|
25
|
+
"grilling": "澄清缺位:执行通道=宿主侧访谈(grill);库内无访谈工具,不越权代答",
|
|
26
|
+
"task": "直接立工程任务推进(关联 unresolved 悬挂线索)",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_JUDGE = {
|
|
30
|
+
"research": "blindspot>=3(反复未知 → 研究议题)",
|
|
31
|
+
"prototype": "其余(偶发未知 → 最小探针)",
|
|
32
|
+
"grilling": "defer 主导(信息不完整 → 须澄清)",
|
|
33
|
+
"task": "query 精确命中 unresolved 节点正文首行",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def classify(item, unresolved_first_lines):
|
|
38
|
+
"""按确定性判据给盲区分派票据类型。unresolved_first_lines={首行: node_id}。"""
|
|
39
|
+
q = str(item.get("query") or "").strip()
|
|
40
|
+
if q and q in unresolved_first_lines:
|
|
41
|
+
return "task"
|
|
42
|
+
b = int(item.get("blindspot") or 0)
|
|
43
|
+
d = int(item.get("defer") or 0)
|
|
44
|
+
if d > b:
|
|
45
|
+
return "grilling"
|
|
46
|
+
if b >= 3:
|
|
47
|
+
return "research"
|
|
48
|
+
return "prototype"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _plan_text(item, ttype, unresolved_first_lines):
|
|
52
|
+
q = str(item.get("query") or "").strip()
|
|
53
|
+
lines = [
|
|
54
|
+
"来源:盲区簇 key=%s(blindspot=%s defer=%s samples=%s)" % (
|
|
55
|
+
metacognition._key(q), item.get("blindspot"), item.get("defer"),
|
|
56
|
+
item.get("samples")),
|
|
57
|
+
"分类判据:%s" % _JUDGE[ttype],
|
|
58
|
+
]
|
|
59
|
+
if ttype == "task" and q in unresolved_first_lines:
|
|
60
|
+
lines.append("关联悬挂:unresolved 节点 %s" % unresolved_first_lines[q])
|
|
61
|
+
lines.append("消解路径:%s" % _RESOLVE[ttype])
|
|
62
|
+
lines.append("完成判据:盲区簇后续反思记录中 BLINDSPOT/DEFER 归零(gap_hint 复核)")
|
|
63
|
+
return "\n".join(lines)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def make_tickets(cg, *, types=None, limit=10, min_blindspot=0,
|
|
67
|
+
apply=False, actor=None) -> dict:
|
|
68
|
+
"""盲区 → 消解票据。apply=False 预演(零落库);apply=True 经 tasks.upsert 落卡。"""
|
|
69
|
+
want = tuple(t for t in (types or TICKET_TYPES) if str(t).strip())
|
|
70
|
+
bad = [t for t in want if str(t).strip().lower() not in TICKET_TYPES]
|
|
71
|
+
if bad:
|
|
72
|
+
return {"ok": False,
|
|
73
|
+
"error": "未知票据类型:%s(可选 %s)" % (bad, list(TICKET_TYPES))}
|
|
74
|
+
|
|
75
|
+
mp = metacognition.blindspots(cg, limit=max(int(limit), 20))
|
|
76
|
+
items = []
|
|
77
|
+
for it in mp.get("items") or []:
|
|
78
|
+
b = int(it.get("blindspot") or 0)
|
|
79
|
+
d = int(it.get("defer") or 0)
|
|
80
|
+
if b >= int(min_blindspot) or d >= 1:
|
|
81
|
+
items.append(it)
|
|
82
|
+
|
|
83
|
+
unresolved_first_lines = {}
|
|
84
|
+
for u in mp.get("unresolved") or []:
|
|
85
|
+
first = str(u.get("content") or "").strip().splitlines()
|
|
86
|
+
if first and first[0].strip():
|
|
87
|
+
unresolved_first_lines.setdefault(first[0].strip(), u.get("node_id"))
|
|
88
|
+
|
|
89
|
+
out, created, updated, errors = [], 0, 0, 0
|
|
90
|
+
for it in items[:int(limit)]:
|
|
91
|
+
q = str(it.get("query") or "").strip()
|
|
92
|
+
if not q:
|
|
93
|
+
continue
|
|
94
|
+
ttype = classify(it, unresolved_first_lines)
|
|
95
|
+
if ttype not in [str(t).strip().lower() for t in want]:
|
|
96
|
+
out.append({"type": ttype, "query": q, "skipped": "types 过滤"})
|
|
97
|
+
continue
|
|
98
|
+
name = "票据:%s:%s" % (ttype, q[:24])
|
|
99
|
+
if not apply:
|
|
100
|
+
out.append({"type": ttype, "query": q, "name": name, "dry_run": True})
|
|
101
|
+
continue
|
|
102
|
+
r = tasks.upsert(
|
|
103
|
+
cg, name, plan=_plan_text(it, ttype, unresolved_first_lines),
|
|
104
|
+
status="active",
|
|
105
|
+
note="盲区簇 key=%s|blindspot=%s|defer=%s" % (
|
|
106
|
+
metacognition._key(q), it.get("blindspot"), it.get("defer")),
|
|
107
|
+
tags=["blindspot-ticket", "ticket:%s" % ttype],
|
|
108
|
+
actor=actor or "blindspot_tickets")
|
|
109
|
+
if r.get("ok"):
|
|
110
|
+
if r.get("created"):
|
|
111
|
+
created += 1
|
|
112
|
+
else:
|
|
113
|
+
updated += 1
|
|
114
|
+
out.append({"node_id": r.get("node_id"), "type": ttype,
|
|
115
|
+
"query": q, "created": bool(r.get("created"))})
|
|
116
|
+
else:
|
|
117
|
+
errors += 1
|
|
118
|
+
out.append({"type": ttype, "query": q, "error": r.get("error")})
|
|
119
|
+
|
|
120
|
+
return {"ok": errors == 0, "action": "tickets", "op": "insight",
|
|
121
|
+
"scanned": len(items), "created": created, "updated": updated,
|
|
122
|
+
"errors": errors, "applied": bool(apply), "tickets": out,
|
|
123
|
+
"unresolved_count": len(unresolved_first_lines)}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""记忆演化分支(Pi 机制移植④,交接文档 §3④「记忆演化 fork」,P0)。
|
|
3
|
+
|
|
4
|
+
pi:会话 = entry 树,任意历史节点可 fork;被放弃旁支由 branch_summary
|
|
5
|
+
归档定长摘要。灵枢映射(单一演化线 → 假设分支实验场):
|
|
6
|
+
|
|
7
|
+
- fork:把主支节点复制成分支实验副本(fm.branch_id / branched_from),
|
|
8
|
+
副本 derived_from=[主支]、relation="split_from"——血缘单向可回溯;
|
|
9
|
+
- 分支节点默认从主支检索隐身(_candidates 按 branch 过滤,一处生效
|
|
10
|
+
全链路穿透)——实验不污染主支(验收:召回主支时分支节点零命中);
|
|
11
|
+
- merge:按 branched_from 溯源回写主支(derived_from=[分支 nid] 追加进
|
|
12
|
+
主支原链、relation="merged_from"),override 走快照——合并后链完整;
|
|
13
|
+
- discard:校验 BRANCH_MARKS 必填 → 写教训节点(knowledge 层、可检索)
|
|
14
|
+
→ 分支文件移入冷区 _branches/<id>/(物理保留、索引摘除、永不删除)。
|
|
15
|
+
|
|
16
|
+
与 writepipe 同哲学:库层函数收 cg,权限闸保持库层强制——
|
|
17
|
+
fork/merge 走 add 的 require_layer_write 自动覆盖;
|
|
18
|
+
discard 改变库可见性,需 can_admin(principal.require_admin)。
|
|
19
|
+
生命周期事件走 _audit.jsonl(③ 两段式载体,零新日志格式)。
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import os
|
|
23
|
+
import re
|
|
24
|
+
import uuid
|
|
25
|
+
|
|
26
|
+
#: discard 的 branch_summary 必填标记(复用 NEG_MEMORY_MARKS 的必填防呆模式:
|
|
27
|
+
#: 「假设 + 结果 + 教训」缺一不收——放弃分支必须留下可复用的教训)。
|
|
28
|
+
BRANCH_MARKS = ("分支假设", "实验结果", "教训")
|
|
29
|
+
|
|
30
|
+
#: 分支文件冷区(LAYERS 之外,_scan_nodes 不扫——天然不进索引与检索)。
|
|
31
|
+
COLD_DIR = "_branches"
|
|
32
|
+
|
|
33
|
+
_BRANCH_RE = re.compile(r"^[a-z0-9][a-z0-9_-]{0,63}$")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# 生效条件:调用 branch_tag(branch_id) 时,返回 "branch:" 拼接 str(branch_id or "").strip().lower()(branch_id 为假值时以空串参与拼接)。
|
|
37
|
+
def branch_tag(branch_id: str) -> str:
|
|
38
|
+
"""分支节点的标注 tag(fork 时写入;branch_summary 也带它以便反查)。"""
|
|
39
|
+
return "branch:" + str(branch_id or "").strip().lower()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# 生效条件:调用 branch_node_id(orig, branch_id) 时,返回 orig 与 str(branch_id or "").strip().lower() 以 @ 拼接的字符串(branch_id 为假值时用空串)。
|
|
43
|
+
def branch_node_id(orig: str, branch_id: str) -> str:
|
|
44
|
+
"""分支副本 id:`<主支nid>@<branch_id>`(@ 文件名合法、撞名不可能)。"""
|
|
45
|
+
return "%s@%s" % (orig, str(branch_id or "").strip().lower())
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# 生效条件:调用 _audit(cg, op, **meta) 时,仅当 getattr(cg, "_audit", None) 不为 None 才用 op 等调用之,且该调用抛出的任何 Exception 被静默吞掉;否则直接返回。
|
|
49
|
+
def _audit(cg, op: str, **meta) -> None:
|
|
50
|
+
"""生命周期留痕;审计失败绝不阻断主流程(G8 同哲学)。"""
|
|
51
|
+
a = getattr(cg, "_audit", None)
|
|
52
|
+
if a is None:
|
|
53
|
+
return
|
|
54
|
+
try:
|
|
55
|
+
a(op, None, **meta)
|
|
56
|
+
except Exception:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# 生效条件:调用 _iter_branch_nodes(cg, branch_id) 时,返回 cg.index 的 "nodes" 字典(假值则视为空字典)中所有 v.get("branch_id") 等于 str(branch_id or "").strip().lower() 的 (k, v) 列表。
|
|
61
|
+
def _iter_branch_nodes(cg, branch_id: str):
|
|
62
|
+
bid = str(branch_id or "").strip().lower()
|
|
63
|
+
return [(k, v) for k, v in (cg.index.get("nodes") or {}).items()
|
|
64
|
+
if v.get("branch_id") == bid]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# 生效条件:调用 _fm_of(rec) 时,若 rec 为假值返回 {};否则返回 rec.get("frontmatter")(若该值真)或 rec 本身。
|
|
68
|
+
def _fm_of(rec):
|
|
69
|
+
"""get 返回形态兼容:{'frontmatter': fm, 'content': c} 或平铺 fm。"""
|
|
70
|
+
if not rec:
|
|
71
|
+
return {}
|
|
72
|
+
return rec.get("frontmatter") or rec
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# 生效条件:调用 fork(cg, node_ids, branch_id=None, note=None) 时,先将 node_ids 去空转字符串,为空则返回 {"ok": False, "error": ...};否则 branch_id 为 None 时生成 "br_"+uuid4().hex[:8],再 str(branch_id).strip().lower(),若不匹配模块常量 _BRANCH_RE 则返回错误;然后对每个 nid 跳过含 "@"、cg.get(nid) 为假值或 cg.get(branch_node_id(nid, branch_id)) 已存在者,其余经 cg.add 复制并记入 forked,最终返回 ok=bool(forked) 及 branch_id/tag/forked/skipped。
|
|
76
|
+
def fork(cg, node_ids, branch_id=None, note=None) -> dict:
|
|
77
|
+
"""把主支节点复制成分支实验副本。
|
|
78
|
+
|
|
79
|
+
返回 {ok, branch_id, tag, forked:[{from,to}], skipped:[{id,why}]}。
|
|
80
|
+
幂等:同 (主支节点, branch_id) 的副本已存在则 skipped,不重复复制。
|
|
81
|
+
"""
|
|
82
|
+
ids = [str(x).strip() for x in (node_ids or []) if str(x).strip()]
|
|
83
|
+
if not ids:
|
|
84
|
+
return {"ok": False, "error": "node_ids 为空(至少指定一个主支节点)"}
|
|
85
|
+
if branch_id is None:
|
|
86
|
+
branch_id = "br_" + uuid.uuid4().hex[:8]
|
|
87
|
+
branch_id = str(branch_id).strip().lower()
|
|
88
|
+
if not _BRANCH_RE.match(branch_id):
|
|
89
|
+
return {"ok": False, "error": "branch_id 非法(%s):%r"
|
|
90
|
+
% (_BRANCH_RE.pattern, branch_id)}
|
|
91
|
+
forked, skipped = [], []
|
|
92
|
+
for nid in ids:
|
|
93
|
+
if "@" in nid:
|
|
94
|
+
skipped.append({"id": nid, "why": "已是分支节点,不支持再 fork"})
|
|
95
|
+
continue
|
|
96
|
+
rec = cg.get(nid)
|
|
97
|
+
if not rec:
|
|
98
|
+
skipped.append({"id": nid, "why": "主支节点不存在或不可见"})
|
|
99
|
+
continue
|
|
100
|
+
fm = _fm_of(rec)
|
|
101
|
+
bid = branch_node_id(nid, branch_id)
|
|
102
|
+
if cg.get(bid):
|
|
103
|
+
skipped.append({"id": nid, "why": "副本已存在:%s" % bid})
|
|
104
|
+
continue
|
|
105
|
+
cg.add(bid, rec.get("content") or "",
|
|
106
|
+
layer=fm.get("layer") or "knowledge",
|
|
107
|
+
role=fm.get("role"),
|
|
108
|
+
tags=list(fm.get("tags") or []),
|
|
109
|
+
condition_space=fm.get("condition_space"),
|
|
110
|
+
importance=float(fm.get("importance", 0.5)),
|
|
111
|
+
verification_basis=fm.get("verification_basis") or "test",
|
|
112
|
+
non_applicable_conditions=fm.get("non_applicable_conditions"),
|
|
113
|
+
consistency=False,
|
|
114
|
+
derived_from=[nid], relation="split_from",
|
|
115
|
+
branch_id=branch_id, branched_from=nid, branch_note=note,
|
|
116
|
+
actor="branch_fork")
|
|
117
|
+
forked.append({"from": nid, "to": bid})
|
|
118
|
+
_audit(cg, "branch_fork", branch_id=branch_id,
|
|
119
|
+
forked=[f["to"] for f in forked])
|
|
120
|
+
return {"ok": bool(forked), "branch_id": branch_id,
|
|
121
|
+
"tag": branch_tag(branch_id), "forked": forked, "skipped": skipped}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# 生效条件:调用 search(cg, query, branch_id, **kw) 时,以 branch=str(branch_id or "").strip().lower() 为参数转调 cg.search,并原样返回其结果。
|
|
125
|
+
def search(cg, query: str, branch_id: str, **kw):
|
|
126
|
+
"""分支内检索:主支 + 本分支可见、其他分支隐身(_candidates branch 过滤)。"""
|
|
127
|
+
return cg.search(query, branch=str(branch_id or "").strip().lower(), **kw)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# 生效条件:当 node_id 经 str 转换并 strip 后含 '@'、cg.index['nodes'] 中存在该 id 且其 branch_id 非空、content 不是 dict 且不是 None 时返回 {'ok': True, 'node': nid, 'branch_id': ...},否则返回 {'ok': False, 'error': ...}。
|
|
131
|
+
def rewrite(cg, node_id, content, tags=None, importance=None,
|
|
132
|
+
actor="branch_rewrite", **extra) -> dict:
|
|
133
|
+
"""分支实验改写的**唯一正路**(防裸 add 丢分支归属)。
|
|
134
|
+
|
|
135
|
+
背景:add 是全量重建 fm——裸 add 改写分支节点而不重传 branch_id,
|
|
136
|
+
节点会在索引里退化成主支(实验内容直接泄漏进主支检索)。本帮手:
|
|
137
|
+
- 只接受在册分支节点(含 @ 且 entry.branch_id 在册);
|
|
138
|
+
- 归属与血缘(branch_id / branched_from / branch_note / derived_from /
|
|
139
|
+
derived_relation)一律从旧 fm 继承,调用方**不可改**(extra 里
|
|
140
|
+
同名键静默剥离)——「分支上怎么改内容都行,改不了它是谁的实验」;
|
|
141
|
+
- 层/条件空间/验证基底默认继承旧 fm(tags/importance 可显式覆盖);
|
|
142
|
+
- override=True → 旧内容自动快照留痕(③ 快照机制,零新日志)。
|
|
143
|
+
写权限由 add 的 require_layer_write 库层强制,不在此重复设闸。
|
|
144
|
+
"""
|
|
145
|
+
nid = str(node_id or "").strip()
|
|
146
|
+
if "@" not in nid:
|
|
147
|
+
return {"ok": False,
|
|
148
|
+
"error": "非分支节点(须为 <主支>@<branch_id> 形态):%s" % nid}
|
|
149
|
+
e = (cg.index.get("nodes") or {}).get(nid)
|
|
150
|
+
if not e or not e.get("branch_id"):
|
|
151
|
+
return {"ok": False, "error": "分支节点不存在或无分支归属:%s" % nid}
|
|
152
|
+
rec = cg.get(nid)
|
|
153
|
+
fm = _fm_of(rec)
|
|
154
|
+
if isinstance(content, dict) or content is None:
|
|
155
|
+
return {"ok": False, "error": "content 须为字符串"}
|
|
156
|
+
for k in ("branch_id", "branched_from", "branch_note", "derived_from",
|
|
157
|
+
"relation", "merged_from_branch", "override", "consistency"):
|
|
158
|
+
extra.pop(k, None) # 归属/血缘/写法闸不可经 extra 篡改
|
|
159
|
+
cg.add(nid, str(content or ""),
|
|
160
|
+
layer=fm.get("layer") or e.get("layer") or "knowledge",
|
|
161
|
+
tags=list(tags if tags is not None else (fm.get("tags") or [])),
|
|
162
|
+
importance=float(importance if importance is not None
|
|
163
|
+
else (fm.get("importance") or 0.5)),
|
|
164
|
+
condition_space=fm.get("condition_space"),
|
|
165
|
+
verification_basis=fm.get("verification_basis") or "test",
|
|
166
|
+
non_applicable_conditions=fm.get("non_applicable_conditions"),
|
|
167
|
+
override=True, consistency=False,
|
|
168
|
+
derived_from=list(fm.get("derived_from") or []),
|
|
169
|
+
relation=fm.get("derived_relation") or "split_from",
|
|
170
|
+
branch_id=fm.get("branch_id") or e.get("branch_id"),
|
|
171
|
+
branched_from=fm.get("branched_from") or e.get("branched_from"),
|
|
172
|
+
branch_note=fm.get("branch_note"),
|
|
173
|
+
actor=actor, **extra)
|
|
174
|
+
_audit(cg, "branch_rewrite", branch_id=e.get("branch_id"), node=nid)
|
|
175
|
+
return {"ok": True, "node": nid, "branch_id": e.get("branch_id")}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# 生效条件:调用 merge(cg, branch_id, reason=None) 时,先取 bid=str(branch_id or "").strip().lower() 与 _iter_branch_nodes(cg, bid),若结果为空返回 {"ok": False, "error": ...};否则遍历每个分支节点,若其 branched_from 取不到主支节点则记 skipped,否则把分支内容用 cg.add 回写主支(override=True、derived_from 追加分支 nid、relation="merged_from" 等),最终返回 ok=bool(merged) 等。
|
|
179
|
+
def merge(cg, branch_id, reason=None) -> dict:
|
|
180
|
+
"""把分支上的改写按 branched_from 溯源回写主支。
|
|
181
|
+
|
|
182
|
+
- 主支内容 = 分支内容;层/tags/重要性继承主支(实验元数据不带回去);
|
|
183
|
+
- 主支 derived_from 追加分支 nid(原链保留)、relation="merged_from";
|
|
184
|
+
- override=True → 主支旧内容自动快照留痕;
|
|
185
|
+
- 分支节点保留(merge 不自动删——显式两步、可逆、诚实)。
|
|
186
|
+
"""
|
|
187
|
+
bid = str(branch_id or "").strip().lower()
|
|
188
|
+
ents = _iter_branch_nodes(cg, bid)
|
|
189
|
+
if not ents:
|
|
190
|
+
return {"ok": False, "error": "分支不存在或无节点:%s" % bid}
|
|
191
|
+
merged, skipped = [], []
|
|
192
|
+
for nid, e in ents:
|
|
193
|
+
orig = e.get("branched_from")
|
|
194
|
+
rec = cg.get(orig) if orig else None
|
|
195
|
+
if not rec:
|
|
196
|
+
skipped.append({"id": nid, "why": "主支节点不存在:%s" % orig})
|
|
197
|
+
continue
|
|
198
|
+
src = cg.get(nid)
|
|
199
|
+
old_fm = _fm_of(rec)
|
|
200
|
+
src_fm = _fm_of(src)
|
|
201
|
+
chain = list(old_fm.get("derived_from") or [])
|
|
202
|
+
if nid not in chain:
|
|
203
|
+
chain.append(nid)
|
|
204
|
+
cg.add(orig, (src or {}).get("content") or "",
|
|
205
|
+
layer=old_fm.get("layer") or e.get("layer") or "knowledge",
|
|
206
|
+
tags=list(old_fm.get("tags") or e.get("tags") or []),
|
|
207
|
+
condition_space=src_fm.get("condition_space"),
|
|
208
|
+
importance=float(old_fm.get("importance", 0.5)),
|
|
209
|
+
verification_basis=old_fm.get("verification_basis") or "test",
|
|
210
|
+
non_applicable_conditions=old_fm.get("non_applicable_conditions"),
|
|
211
|
+
override=True, consistency=False,
|
|
212
|
+
derived_from=chain, relation="merged_from",
|
|
213
|
+
merged_from_branch=bid, actor="branch_merge")
|
|
214
|
+
merged.append({"branch_node": nid, "target": orig})
|
|
215
|
+
_audit(cg, "branch_merge", branch_id=bid,
|
|
216
|
+
merged=[m["target"] for m in merged], reason=reason)
|
|
217
|
+
return {"ok": bool(merged), "branch_id": bid, "merged": merged,
|
|
218
|
+
"skipped": skipped,
|
|
219
|
+
"hint": "分支节点保留:可 branch_search 继续实验,或 discard 冷归档"}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# 生效条件:调用 discard(cg, branch_id, summary) 时,若 cg.principal 存在则先 require_admin("branch_discard");取 bid=str(branch_id or "").strip().lower(),若 summary 缺少模块常量 BRANCH_MARKS 中任一标记则返回错误,若 _iter_branch_nodes(cg, bid) 为空也返回错误;否则写 "branch_summary_"+bid 知识节点,把分支节点文件移入 COLD_DIR/bid 并从 cg.index["nodes"] 弹出,最后返回 ok=True 等。
|
|
223
|
+
def discard(cg, branch_id, summary: str) -> dict:
|
|
224
|
+
"""放弃分支:校验教训必填 → 写 branch_summary 教训节点 → 分支冷归档。
|
|
225
|
+
|
|
226
|
+
- summary 必须含 BRANCH_MARKS 三标记(缺一不收,防「无声放弃」);
|
|
227
|
+
- 教训节点进 knowledge 层、tags 带 branch:<id>——可被正常检索召回;
|
|
228
|
+
- 分支节点文件移入 _branches/<id>/(物理保留不违背永不删除,
|
|
229
|
+
LAYERS 之外故 _scan_nodes 不再扫到——索引与主支检索天然干净);
|
|
230
|
+
- 需 can_admin(改变库可见性属高危操作)。
|
|
231
|
+
"""
|
|
232
|
+
p = getattr(cg, "principal", None)
|
|
233
|
+
if p is not None:
|
|
234
|
+
p.require_admin("branch_discard")
|
|
235
|
+
bid = str(branch_id or "").strip().lower()
|
|
236
|
+
missing = [m for m in BRANCH_MARKS if m not in (summary or "")]
|
|
237
|
+
if missing:
|
|
238
|
+
return {"ok": False, "error": "branch_summary 缺必填标记",
|
|
239
|
+
"missing": missing, "required": list(BRANCH_MARKS)}
|
|
240
|
+
ents = _iter_branch_nodes(cg, bid)
|
|
241
|
+
if not ents:
|
|
242
|
+
return {"ok": False, "error": "分支不存在或无节点:%s" % bid}
|
|
243
|
+
body = summary if summary.lstrip().startswith("#") else \
|
|
244
|
+
"# branch_summary:%s\n\n%s" % (bid, summary)
|
|
245
|
+
sid = cg.add("branch_summary_%s" % bid, body, layer="knowledge",
|
|
246
|
+
tags=["branch_summary", branch_tag(bid)],
|
|
247
|
+
verification_basis="test", consistency=False,
|
|
248
|
+
actor="branch_discard")
|
|
249
|
+
cold = os.path.join(cg.root, COLD_DIR, bid)
|
|
250
|
+
os.makedirs(cold, exist_ok=True)
|
|
251
|
+
moved = 0
|
|
252
|
+
for nid, e in ents:
|
|
253
|
+
path = e.get("path")
|
|
254
|
+
if path:
|
|
255
|
+
src = os.path.join(cg.root, str(path).replace("/", os.sep))
|
|
256
|
+
if os.path.exists(src):
|
|
257
|
+
os.replace(src, os.path.join(cold, os.path.basename(src)))
|
|
258
|
+
moved += 1
|
|
259
|
+
(cg.index.get("nodes") or {}).pop(nid, None)
|
|
260
|
+
fl = getattr(cg, "flush", None)
|
|
261
|
+
if fl is not None:
|
|
262
|
+
try:
|
|
263
|
+
fl()
|
|
264
|
+
except Exception:
|
|
265
|
+
pass
|
|
266
|
+
_audit(cg, "branch_discard", branch_id=bid, moved=moved, summary_node=sid)
|
|
267
|
+
return {"ok": True, "branch_id": bid, "moved": moved,
|
|
268
|
+
"summary_node": sid, "cold_dir": "%s/%s" % (COLD_DIR, bid)}
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
# 生效条件:调用 list_branches(cg) 时,遍历 cg.index 的 "nodes"(假值则空字典),仅对 e.get("branch_id") 为真值的节点按 bid 分组,收集节点 id 和 branched_from,返回 ok=True 与按 branch_id 排序的分组列表。
|
|
272
|
+
def list_branches(cg) -> dict:
|
|
273
|
+
"""按 branch_id 聚合现存分支(节点清单 + 溯源主支)。"""
|
|
274
|
+
groups = {}
|
|
275
|
+
for nid, e in (cg.index.get("nodes") or {}).items():
|
|
276
|
+
bid = e.get("branch_id")
|
|
277
|
+
if not bid:
|
|
278
|
+
continue
|
|
279
|
+
g = groups.setdefault(bid, {"branch_id": bid, "tag": branch_tag(bid),
|
|
280
|
+
"nodes": [], "branched_from": []})
|
|
281
|
+
g["nodes"].append(nid)
|
|
282
|
+
bf = e.get("branched_from")
|
|
283
|
+
if bf and bf not in g["branched_from"]:
|
|
284
|
+
g["branched_from"].append(bf)
|
|
285
|
+
return {"ok": True,
|
|
286
|
+
"branches": sorted(groups.values(), key=lambda g: g["branch_id"])}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""倒排发布表构建/查看(S7 候选层)。
|
|
3
|
+
|
|
4
|
+
用法:
|
|
5
|
+
python -X utf8 -m md_cg.build_postings --root <库根> # 全量重建(幂等)
|
|
6
|
+
python -X utf8 -m md_cg.build_postings --root <库根> --stats # 只看现状
|
|
7
|
+
python -X utf8 -m md_cg.build_postings --root <库根> --limit 500 # 抽样构建(冒烟用,永不算新鲜)
|
|
8
|
+
python -X utf8 -m md_cg.build_postings --root <库根> --if-stale # 过期才重建(守候环用)
|
|
9
|
+
|
|
10
|
+
说明:发布表是**派生索引**(<root>/_postings.json + _postings_meta.json),
|
|
11
|
+
不修改任何节点内容;节点新增/修改后需重建(v1 不做增量维护)。
|
|
12
|
+
"""
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
from . import postings
|
|
18
|
+
from .mdcg import MdCG
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# 生效条件:st 为 dict 时返回其摘要——保留 schema/built_at/nodes/terms/postings/partial/rebuilt/rebuilt_from,
|
|
22
|
+
# 并把 snapshot 折成 dirs/root_files 计数(快照本体含上千个目录键,直接打印会淹没日志);st 非 dict 时原样返回。
|
|
23
|
+
def _brief(st):
|
|
24
|
+
if not isinstance(st, dict):
|
|
25
|
+
return st
|
|
26
|
+
keys = ("schema", "built_at", "nodes", "terms", "postings", "partial",
|
|
27
|
+
"rebuilt", "rebuilt_from")
|
|
28
|
+
out = {k: st.get(k) for k in keys if k in st}
|
|
29
|
+
snap = st.get("snapshot")
|
|
30
|
+
if isinstance(snap, dict):
|
|
31
|
+
out["dirs"] = len(snap.get("dir_mtimes") or {})
|
|
32
|
+
out["root_files"] = len(snap.get("file_mtimes") or {})
|
|
33
|
+
return out
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# 生效条件:无条件解析参数(root 必填;stats/limit/if-stale 可选;if-stale 与 limit 互斥则 argparse 报错并退出 2);
|
|
37
|
+
# stats 为真时打开库打印 stats 摘要(含 stale_reason)并返回 0;if-stale 为真且快照新鲜时打印 {"rebuilt": false} 返回 0、
|
|
38
|
+
# 过期时重建并打印摘要(附 rebuilt_from=过期原因);否则一律重建并打印摘要,返回 0。
|
|
39
|
+
# 三条路径打印的都是 _brief 摘要——不打印快照指纹本体。
|
|
40
|
+
def main(argv=None):
|
|
41
|
+
ap = argparse.ArgumentParser()
|
|
42
|
+
ap.add_argument("--root", required=True)
|
|
43
|
+
ap.add_argument("--stats", action="store_true")
|
|
44
|
+
ap.add_argument("--limit", type=int, default=None)
|
|
45
|
+
ap.add_argument("--if-stale", action="store_true", dest="if_stale")
|
|
46
|
+
a = ap.parse_args(argv)
|
|
47
|
+
if a.if_stale and a.limit:
|
|
48
|
+
ap.error("--if-stale 与 --limit 互斥(抽样表不可当作新鲜快照)")
|
|
49
|
+
cg = MdCG(a.root)
|
|
50
|
+
nodes = cg.index.get("nodes") or {}
|
|
51
|
+
if a.stats:
|
|
52
|
+
st = postings.stats(a.root, nodes)
|
|
53
|
+
print(json.dumps({"terms": st.get("terms"), "postings": st.get("postings"),
|
|
54
|
+
"stale_reason": st.get("stale_reason"),
|
|
55
|
+
"meta": _brief(st.get("meta"))}, ensure_ascii=False))
|
|
56
|
+
return 0
|
|
57
|
+
if a.if_stale:
|
|
58
|
+
sr = postings.stale_reason(a.root, nodes)
|
|
59
|
+
if not sr:
|
|
60
|
+
print(json.dumps({"rebuilt": False, "reason": "fresh"}, ensure_ascii=False))
|
|
61
|
+
return 0
|
|
62
|
+
st = postings.build(cg)
|
|
63
|
+
print(json.dumps(_brief(dict(st, rebuilt_from=sr)), ensure_ascii=False))
|
|
64
|
+
return 0
|
|
65
|
+
st = postings.build(cg, limit=a.limit)
|
|
66
|
+
print(json.dumps(_brief(st), ensure_ascii=False))
|
|
67
|
+
return 0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
72
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
73
|
+
sys.exit(main())
|