@furongjun1999/dsh-memory 0.4.11 → 0.5.1
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 +552 -465
- package/codebuddy/CODEBUDDY.md +11 -3
- package/codebuddy/README.md +92 -90
- package/codebuddy/mcp.json +27 -27
- 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 -169
- 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 -144
- package/docs/README.md +143 -111
- package/docs/discipline/harnesses.yaml +244 -226
- package/docs/discipline/templates/full.md.tmpl +61 -61
- package/docs/discipline/templates/rules.mdc.tmpl +68 -0
- package/docs/discipline/templates/skill.md.tmpl +23 -23
- package/docs/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 +299 -299
- package/docs/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 +239 -239
- package/docs/eval/bench_lingshu_self/bench_self.py +140 -0
- package/docs/eval/bench_lingshu_self/self_bench_result.json +404 -0
- package/docs/eval/bench_lingshu_self//347/201/265/346/236/242/350/207/252/345/272/223/347/253/257/345/210/260/347/253/257/346/243/200/347/264/242/345/256/236/346/265/213_v1.0.md +38 -0
- package/docs/eval//344/270/215/345/217/257/351/235/240/346/200/247/350/220/275/345/234/260_P0_v1.0.md +185 -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 +174 -174
- package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md +422 -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 +223 -223
- package/docs/eval//347/253/257/345/210/260/347/253/257LoCoMoQA/345/220/214/345/217/243/345/276/204/345/257/271/347/205/247_v1.0.md +100 -0
- package/docs/eval//347/253/257/345/210/260/347/253/257/345/271/262/346/211/260/346/261/240/350/257/204/346/265/213_/347/241/256/345/256/232/346/200/247/350/243/201/345/206/263vsLLM_judge_v1.1.md +197 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v1.md +156 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v10.md +210 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v11.md +227 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v12.md +203 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v13.md +233 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v14.md +191 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v15.md +213 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v16.md +214 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v17.md +199 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v2.md +156 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v3.md +152 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v4.md +128 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v5.md +114 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v6.md +192 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v7.md +187 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v8.md +207 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v9.md +203 -0
- package/docs/{mdcg → hive}//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 +165 -160
- package/docs/hive//344/273/244/347/211/214/350/257/255/344/271/211/344/277/256/346/255/243_/344/273/262/350/243/201/344/275/215_v0.1.md +76 -0
- package/docs/{mdcg → hive}//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 -236
- package/docs/hive//345/256/211/345/205/250/345/256/241/350/256/241/345/256/236/351/224/232_v0.1.md +202 -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 -43
- package/docs/hive//346/243/200/347/264/242/347/256/227/346/263/225/345/217/243/345/276/204/345/257/271/347/205/247_v0.1.md +85 -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 -102
- package/docs/hive//350/234/202/345/267/242M6_ingest/345/256/236/346/226/275/350/256/241/345/210/222_v0.1.md +47 -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 +519 -503
- 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 +85 -85
- package/docs/hive//350/234/202/345/267/242/350/256/276/350/256/241_/347/220/206/350/256/272/345/257/271/351/275/220_v0.1.md +191 -0
- package/docs/hive//350/234/202/345/267/242/350/277/255/344/273/243_/345/256/217/350/247/202/344/270/216/347/276/244/344/275/223/350/260/203/345/272/246_v0.1.md +90 -0
- package/docs/images/lingshu-moonlight-covenant-poster-preview.jpg +0 -0
- package/docs/images/lingshu-moonlight-covenant-poster.png +0 -0
- package/docs/mdcg/D_meta_/345/267/245/347/250/213/345/214/226/346/226/271/346/241/210_v0.2.md +216 -216
- package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +646 -646
- package/docs/mdcg/lingshu_tutorial.html +14449 -14449
- package/docs/mdcg/release_v0.4.11.md +49 -0
- package/docs/mdcg/release_v0.4.5.md +55 -55
- package/docs/mdcg/tool_table_v0.3.0.md +117 -117
- 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 -600
- 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 +40 -40
- 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 +275 -275
- package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +54 -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 +130 -130
- 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 +278 -278
- 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 -172
- package/docs/mdcg//347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +270 -270
- 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 +491 -491
- 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 +340 -340
- 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 +588 -588
- 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 -176
- 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 +81 -81
- package/docs/swarm//350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +704 -704
- 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 -242
- package/docs/theory//344/270/215/345/217/257/351/235/240/345/256/232/347/220/206/344/270/216/345/244/261/346/225/210/344/274/230/345/205/210/346/241/206/346/236/266_v0.3.md +365 -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 -129
- 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 -134
- package/docs/theory//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
- 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 -145
- 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 +144 -144
- 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 +198 -198
- 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 -221
- 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 -237
- package/docs//344/270/215/345/217/257/351/235/240/346/200/247/347/220/206/350/256/272_v0.1.md +343 -0
- package/docs//345/217/221/345/270/203/344/273/266/345/233/236/346/272/257/350/257/264/346/230/216_v0.1.md +82 -82
- 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 +28 -2
- package/dsh/README.md +82 -82
- package/dsh/cordis.yml.example +139 -139
- package/dsh/update-lingshu.bat +11 -11
- package/lib/bridge.d.ts +9 -0
- package/lib/bridge.js +35 -0
- package/lib/hooks.js +36 -2
- package/lib/index.js +7 -1
- package/lib/lib/roleplay_web.js +116 -29
- package/lib/lib/token_store.d.ts +7 -1
- package/lib/lib/token_store.js +12 -3
- package/md_cg/__init__.py +7 -7
- package/md_cg/audit.py +379 -368
- package/md_cg/autonomy.py +287 -287
- package/md_cg/backfill.py +1328 -1327
- package/md_cg/backfill_bigdomain.py +34 -34
- package/md_cg/backfill_bucket_zh.py +35 -0
- package/md_cg/bench6_arms.py +410 -410
- package/md_cg/bench6_common.py +230 -230
- package/md_cg/bench6_competitors.py +212 -212
- package/md_cg/bench_axis_domain.py +257 -257
- package/md_cg/bench_blind_comp.py +308 -308
- package/md_cg/bench_e2e_judge.py +532 -0
- package/md_cg/bench_e2e_locomo_qa.py +368 -0
- package/md_cg/bench_e2e_qa.py +256 -0
- package/md_cg/bench_en_atoms_public.py +230 -230
- package/md_cg/bench_governance.py +348 -348
- package/md_cg/bench_lme_zh.py +410 -410
- package/md_cg/bench_locomo.py +121 -121
- package/md_cg/bench_locomo_zh.py +450 -450
- package/md_cg/bench_locomo_zh_public.py +147 -147
- package/md_cg/bench_longmem.py +112 -112
- package/md_cg/bench_membench.py +632 -632
- package/md_cg/bench_p0.py +149 -149
- package/md_cg/bench_progressive.py +287 -287
- package/md_cg/bench_role_views.py +238 -238
- package/md_cg/bench_task_ab.py +243 -243
- package/md_cg/bench_task_ab_llm.py +408 -408
- package/md_cg/bench_unified_en.py +204 -204
- package/md_cg/bench_zh_mad.py +601 -601
- package/md_cg/blindspot_tickets.py +123 -123
- package/md_cg/branches.py +301 -285
- package/md_cg/build_postings.py +73 -73
- package/md_cg/ccgc.py +1006 -948
- package/md_cg/census.py +132 -132
- package/md_cg/chain.py +315 -300
- package/md_cg/codeindex.py +531 -531
- package/md_cg/coldverify.py +292 -292
- package/md_cg/comment_gate.py +337 -337
- package/md_cg/cond_compose.py +190 -190
- package/md_cg/cond_facts.py +154 -154
- package/md_cg/cond_template.json +106 -106
- package/md_cg/condition_anchor.py +142 -142
- package/md_cg/conformance.py +726 -726
- package/md_cg/consistency.py +717 -717
- package/md_cg/consolidate.py +1537 -1439
- package/md_cg/corpus.py +110 -110
- package/md_cg/crosscheck.py +1098 -1097
- package/md_cg/crypto.py +3 -1
- package/md_cg/d_meta.py +310 -310
- package/md_cg/datapath.py +78 -18
- package/md_cg/docindex.py +473 -473
- package/md_cg/eval_common.py +575 -575
- package/md_cg/evidence.py +4 -2
- package/md_cg/evolution.py +477 -477
- package/md_cg/export.py +222 -220
- package/md_cg/forgetting.py +581 -581
- package/md_cg/fsutil.py +377 -329
- package/md_cg/hotcache.py +48 -7
- package/md_cg/hyperedge.py +251 -251
- package/md_cg/identity.py +390 -390
- package/md_cg/insight.py +500 -500
- package/md_cg/interop.py +338 -0
- package/md_cg/judgment_manifest.py +177 -0
- package/md_cg/lexicon/build_cedict_en_zh.py +329 -329
- package/md_cg/lexicon/build_standard_en.py +171 -171
- package/md_cg/lexicon/expand_en_zh.py +211 -211
- package/md_cg/lifecycle.py +272 -272
- package/md_cg/linkref.py +280 -280
- package/md_cg/links.py +140 -107
- package/md_cg/mcp_server.py +403 -55
- package/md_cg/md_whitebox.py +345 -345
- package/md_cg/mdcg.py +783 -233
- package/md_cg/mdcos.py +500 -70
- package/md_cg/metacognition.py +591 -591
- package/md_cg/migrate.py +119 -119
- package/md_cg/migrate_aeis.py +221 -221
- package/md_cg/migrate_roleplay.py +293 -293
- package/md_cg/migrate_wisdom_graph.py +360 -360
- package/md_cg/mreview/__init__.py +25 -25
- package/md_cg/mreview/__main__.py +110 -110
- package/md_cg/mreview/bundle.py +178 -178
- package/md_cg/mreview/candidates.py +262 -262
- package/md_cg/mreview/govern.py +694 -693
- package/md_cg/mreview/locate.py +939 -939
- package/md_cg/mreview/pipeline.py +728 -728
- package/md_cg/mreview/rules/duplication.json +21 -21
- package/md_cg/mreview/rules/field_coverage.json +54 -54
- package/md_cg/mreview/rules/source_license.json +21 -21
- package/md_cg/mreview/rules/template_flow.json +21 -21
- package/md_cg/mreview/ruleset.py +252 -252
- package/md_cg/nodefile.py +575 -575
- package/md_cg/pooling.py +484 -472
- package/md_cg/postings.py +300 -298
- package/md_cg/predict.py +1100 -1100
- package/md_cg/progressive.py +123 -123
- package/md_cg/protect.py +272 -272
- package/md_cg/protocol/md_cg_gate.proto +33 -33
- package/md_cg/protocol.py +372 -372
- package/md_cg/provenance.py +582 -582
- package/md_cg/reach.py +453 -453
- package/md_cg/readcache.py +143 -0
- package/md_cg/reconcile.py +228 -0
- package/md_cg/refindex.py +833 -833
- package/md_cg/refine.py +604 -604
- package/md_cg/review_cli.py +170 -0
- package/md_cg/roleviews.py +89 -89
- package/md_cg/routing.py +393 -365
- package/md_cg/run_tests.py +211 -0
- package/md_cg/scrub.py +13 -3
- package/md_cg/security.py +128 -18
- package/md_cg/self_state.py +1029 -1029
- package/md_cg/selfreport.py +152 -151
- package/md_cg/semantic/__init__.py +10 -10
- package/md_cg/semantic/canonical.py +122 -122
- package/md_cg/semantic/en_normalizer.py +364 -364
- package/md_cg/semantic/en_zh_map.json +28694 -0
- package/md_cg/semantic/export_en_zh_map.py +64 -0
- package/md_cg/semantic/unify.py +45 -0
- package/md_cg/semantic/zh_en_atoms.py +139 -139
- package/md_cg/signer.py +7 -4
- package/md_cg/sources.py +816 -582
- package/md_cg/statushdr.py +179 -179
- package/md_cg/stg.py +54 -37
- package/md_cg/subgraph.py +729 -729
- package/md_cg/sustain.py +35 -5
- package/md_cg/tasks.py +470 -470
- package/md_cg/test_access_hints.py +147 -0
- package/md_cg/test_action_derive.py +203 -203
- package/md_cg/test_audit_rotate.py +270 -270
- package/md_cg/test_autonomy.py +143 -143
- package/md_cg/test_bench_governance.py +102 -102
- package/md_cg/test_blindspot_tickets.py +166 -166
- package/md_cg/test_branch_discard_tombstone.py +136 -0
- package/md_cg/test_branches.py +13 -3
- package/md_cg/test_ccg_perturb.py +184 -184
- package/md_cg/test_ccgc.py +433 -433
- package/md_cg/test_census_prune.py +81 -81
- package/md_cg/test_chain_read_isolate.py +168 -0
- package/md_cg/test_cond_compose_anchors.py +76 -76
- package/md_cg/test_cond_match.py +165 -165
- package/md_cg/test_condition_anchor.py +81 -81
- package/md_cg/test_d_meta.py +412 -412
- package/md_cg/test_datapath_device_name.py +203 -0
- package/md_cg/test_datapath_root.py +199 -199
- package/md_cg/test_emit_negtail_cache.py +156 -0
- package/md_cg/test_en_pipeline.py +22 -2
- package/md_cg/test_gain_gate.py +212 -212
- package/md_cg/test_govern_directread.py +421 -0
- package/md_cg/test_health_scale.py +173 -173
- package/md_cg/test_hive_ingest.py +285 -0
- package/md_cg/test_hot_cold.py +215 -215
- package/md_cg/test_hyperedge.py +245 -245
- package/md_cg/test_i26_empty_first_write.py +116 -0
- package/md_cg/test_i27_e041_identity.py +128 -0
- package/md_cg/test_i28_hotcache_prodpath.py +122 -0
- package/md_cg/test_i32_hotcache_env_key.py +218 -0
- package/md_cg/test_identity_attribution.py +96 -15
- package/md_cg/test_index_durability.py +17 -3
- package/md_cg/test_interop.py +95 -0
- package/md_cg/test_interop_judgment.py +228 -0
- package/md_cg/test_issue39_utf8_stdio.py +273 -0
- package/md_cg/test_lifecycle.py +309 -309
- package/md_cg/test_linkref.py +306 -306
- package/md_cg/test_links_concurrent_write.py +188 -0
- package/md_cg/test_lock.py +43 -43
- package/md_cg/test_md_access_parity.py +255 -255
- package/md_cg/test_md_writepath.py +345 -345
- package/md_cg/test_mdstore_search_parity.py +160 -0
- package/md_cg/test_merge_upsert.py +168 -0
- package/md_cg/test_mr_m2.py +587 -587
- package/md_cg/test_mr_m3.py +710 -710
- package/md_cg/test_mr_m4.py +485 -485
- package/md_cg/test_n123_derive_expiry_chain.py +205 -0
- package/md_cg/test_n130_verify_falsified_protect.py +185 -0
- package/md_cg/test_n131_merge_gate.py +205 -0
- package/md_cg/test_p0.py +250 -250
- package/md_cg/test_p1.py +316 -316
- package/md_cg/test_p10_identity.py +173 -173
- package/md_cg/test_p11_consistency.py +233 -233
- package/md_cg/test_p12_metacognition.py +212 -212
- package/md_cg/test_p13_encryption.py +241 -241
- package/md_cg/test_p14_sustain.py +249 -249
- package/md_cg/test_p15_scrub.py +280 -280
- package/md_cg/test_p16_self_state.py +301 -301
- package/md_cg/test_p17_predict.py +354 -354
- package/md_cg/test_p18_whitebox.py +171 -171
- package/md_cg/test_p19_migrate_roleplay.py +149 -149
- package/md_cg/test_p1x_ref_root.py +160 -0
- package/md_cg/test_p20_evolution.py +315 -315
- package/md_cg/test_p21_tokens.py +293 -270
- package/md_cg/test_p22_theory.py +175 -175
- package/md_cg/test_p23_links.py +311 -311
- package/md_cg/test_p24_evidence.py +227 -227
- package/md_cg/test_p25_weights.py +156 -156
- package/md_cg/test_p26_refindex.py +416 -416
- package/md_cg/test_p27_docindex.py +16 -7
- package/md_cg/test_p28_refcheck.py +305 -305
- package/md_cg/test_p29_session_ingest_export.py +354 -333
- package/md_cg/test_p2_mcp.py +3 -0
- package/md_cg/test_p3.py +11 -2
- package/md_cg/test_p30_maintain.py +330 -330
- package/md_cg/test_p31_insight.py +534 -534
- package/md_cg/test_p32_backfill.py +7 -1
- package/md_cg/test_p33_ccg_wiring.py +293 -293
- package/md_cg/test_p34_crosscheck.py +331 -331
- package/md_cg/test_p35_conditioned_claim.py +252 -252
- package/md_cg/test_p36_kp_align.py +230 -230
- package/md_cg/test_p37_condition_space.py +248 -248
- package/md_cg/test_p38_concurrent_flush.py +102 -0
- package/md_cg/test_p38_contextualize.py +273 -273
- package/md_cg/test_p39_verify_flow.py +153 -0
- package/md_cg/test_p39_vision_evidence.py +369 -369
- package/md_cg/test_p40_refine_worklist.py +241 -241
- package/md_cg/test_p41_evolve_patrol.py +224 -224
- package/md_cg/test_p42_provenance.py +269 -269
- package/md_cg/test_p43_pooling.py +412 -398
- package/md_cg/test_p44_md_whitebox.py +231 -231
- package/md_cg/test_p45_session_identity.py +219 -219
- package/md_cg/test_p46_unit_scope.py +272 -272
- package/md_cg/test_p47_session_view.py +316 -0
- package/md_cg/test_p4_fuzzy.py +223 -223
- package/md_cg/test_p5_semantic.py +226 -226
- package/md_cg/test_p6_consolidate.py +440 -387
- package/md_cg/test_p7_goals_recent.py +202 -202
- package/md_cg/test_p8_subgraph_chain.py +200 -200
- package/md_cg/test_p9_forget_protect.py +231 -231
- package/md_cg/test_predict_beta.py +135 -135
- package/md_cg/test_preflight_failclosed.py +100 -100
- package/md_cg/test_progressive.py +146 -146
- package/md_cg/test_propose_tail_index.py +157 -0
- package/md_cg/test_protocol.py +243 -243
- package/md_cg/test_reach.py +378 -378
- package/md_cg/test_reach_keys.py +201 -201
- package/md_cg/test_read_clip.py +141 -141
- package/md_cg/test_read_scope_b27.py +277 -0
- package/md_cg/test_readcache_default_on.py +168 -0
- package/md_cg/test_readcache_precise_inval.py +270 -0
- package/md_cg/test_readcache_prodpath.py +203 -0
- package/md_cg/test_reconcile_v0.py +294 -0
- package/md_cg/test_retr_gates_prodpath.py +140 -0
- package/md_cg/test_retr_s1.py +344 -340
- package/md_cg/test_retr_s1b.py +276 -209
- package/md_cg/test_retr_s3.py +194 -194
- package/md_cg/test_retr_s4.py +163 -163
- package/md_cg/test_retr_s5.py +200 -200
- package/md_cg/test_retr_s6.py +157 -157
- package/md_cg/test_retr_s7.py +392 -384
- package/md_cg/test_retr_s8_time.py +369 -316
- package/md_cg/test_retr_s9_edges.py +286 -286
- package/md_cg/test_retr_s9_entity_ctx.py +9 -3
- package/md_cg/test_retr_score_once.py +208 -0
- package/md_cg/test_review_conformance.py +367 -367
- package/md_cg/test_review_onepass.py +170 -0
- package/md_cg/test_role_views.py +354 -354
- package/md_cg/test_rrf_graph_seed_cache.py +154 -0
- package/md_cg/test_security_audit.py +155 -0
- package/md_cg/test_security_audit_b26.py +161 -0
- package/md_cg/test_security_audit_v21.py +250 -0
- package/md_cg/test_sem_noise.py +242 -242
- package/md_cg/test_semantic_canonical.py +16 -2
- package/md_cg/test_session_isolation.py +168 -0
- package/md_cg/test_snapshot_autoclose.py +187 -0
- package/md_cg/test_subproc_encoding.py +192 -192
- package/md_cg/test_sustain_mutual.py +153 -153
- package/md_cg/test_tail_watermark_race.py +208 -0
- package/md_cg/test_tasks.py +409 -409
- package/md_cg/test_tenant_env_override_warn.py +139 -0
- package/md_cg/test_tenant_registry_corrupt_warn.py +151 -0
- package/md_cg/test_tool_face.py +189 -189
- package/md_cg/test_transfer.py +180 -180
- package/md_cg/test_trust.py +361 -361
- package/md_cg/test_twophase.py +286 -286
- package/md_cg/test_v14_fixes.py +38 -20
- package/md_cg/test_validity_filter.py +280 -280
- package/md_cg/test_verify_answer.py +138 -138
- package/md_cg/test_verify_dirty_reconcile.py +157 -0
- package/md_cg/test_wisdom_md_store.py +292 -292
- package/md_cg/test_writelimit.py +197 -197
- package/md_cg/test_writepipe.py +214 -214
- package/md_cg/theory.py +6 -3
- package/md_cg/tokens.py +85 -14
- package/md_cg/tool_face.py +260 -260
- package/md_cg/trust.py +986 -950
- package/md_cg/twophase.py +231 -231
- package/md_cg/units.py +668 -667
- package/md_cg/vision_evidence.py +667 -666
- package/md_cg/weights.py +624 -624
- package/md_cg/whitebox.py +527 -527
- package/md_cg/whitebox_kb/__init__.py +37 -37
- package/md_cg/whitebox_kb/aeis_core/__init__.py +42 -42
- package/md_cg/whitebox_kb/aeis_core/semantic.py +280 -280
- package/md_cg/whitebox_kb/aeis_core/textutil.py +13 -13
- package/md_cg/whitebox_kb/engine.py +310 -310
- package/md_cg/whitebox_kb/seed_knowledge//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
- package/md_cg/whitebox_kb/wisdom/browser_units.py +2631 -2631
- package/md_cg/whitebox_kb/wisdom/causal_discover.py +432 -432
- package/md_cg/whitebox_kb/wisdom/chat_engine.py +1506 -1506
- package/md_cg/whitebox_kb/wisdom/compiler_code_units.py +3033 -3033
- package/md_cg/whitebox_kb/wisdom/condition_algebra.py +112 -112
- package/md_cg/whitebox_kb/wisdom/condition_frame.py +315 -315
- package/md_cg/whitebox_kb/wisdom/condition_kb.py +108 -108
- package/md_cg/whitebox_kb/wisdom/conflict_map.json +4445 -4445
- package/md_cg/whitebox_kb/wisdom/core/lexer.py +512 -512
- package/md_cg/whitebox_kb/wisdom/core/name_checker.py +1023 -1023
- package/md_cg/whitebox_kb/wisdom/cspmn.py +258 -258
- package/md_cg/whitebox_kb/wisdom/csre.py +264 -264
- package/md_cg/whitebox_kb/wisdom/danmaku_audit.py +252 -252
- package/md_cg/whitebox_kb/wisdom/distilled_condition_units.json +6417 -6417
- package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902b.json +1950 -1950
- package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902c.json +1296 -1296
- package/md_cg/whitebox_kb/wisdom/docs/whitebox_capability_graph_demo.json +59 -59
- package/md_cg/whitebox_kb/wisdom/graph_db_units.py +3089 -3089
- package/md_cg/whitebox_kb/wisdom/knowledge_points.py +318 -318
- package/md_cg/whitebox_kb/wisdom/md_access.py +470 -470
- package/md_cg/whitebox_kb/wisdom/md_store.py +276 -251
- package/md_cg/whitebox_kb/wisdom/migrate_wisdom.py +476 -476
- package/md_cg/whitebox_kb/wisdom/multilang_ir.py +128 -124
- package/md_cg/whitebox_kb/wisdom/navigate.py +248 -248
- package/md_cg/whitebox_kb/wisdom/neural_retrieve.py +224 -224
- package/md_cg/whitebox_kb/wisdom/os_units.py +2735 -2735
- package/md_cg/whitebox_kb/wisdom/pattern_separation.py +376 -376
- package/md_cg/whitebox_kb/wisdom/prereq_map.json +364 -364
- package/md_cg/whitebox_kb/wisdom/python_code_units.py +2766 -2766
- package/md_cg/whitebox_kb/wisdom/role_solidified.json +7 -7
- package/md_cg/whitebox_kb/wisdom/route_memory.py +244 -244
- package/md_cg/whitebox_kb/wisdom/scene_reconstruction.py +148 -148
- package/md_cg/whitebox_kb/wisdom/snr_report.json +40 -40
- package/md_cg/whitebox_kb/wisdom/test_code_compose_domains.py +7541 -7541
- package/md_cg/whitebox_kb/wisdom/test_compiler_self_bootstrap.py +354 -354
- package/md_cg/whitebox_kb/wisdom/test_ecosystem_assembly.py +158 -158
- package/md_cg/whitebox_kb/wisdom/test_ecosystem_demos.py +193 -193
- package/md_cg/whitebox_kb/wisdom/test_graph_db.py +292 -292
- package/md_cg/whitebox_kb/wisdom/test_python_self_bootstrap.py +160 -160
- package/md_cg/whitebox_kb/wisdom/trigger_words_index.json +4366 -4366
- package/md_cg/whitebox_kb/wisdom/verifier.py +1297 -1297
- package/md_cg/writelimit.py +356 -356
- package/md_cg/writepipe.py +20 -8
- package/package.json +101 -96
- package/skills/plugin.json +54 -54
- package/skills/skills/designer-perspective/SKILL.md +158 -158
- package/skills/skills/designer-perspective/references/01-observation-position.md +66 -66
- package/skills/skills/designer-perspective/references/02-structure-recognition.md +62 -62
- package/skills/skills/designer-perspective/references/03-direction-judgment.md +55 -55
- package/skills/skills/designer-perspective/references/04-qualification-verdict.md +72 -72
- package/skills/skills/designer-perspective/references/05-condition-attribution.md +74 -74
- package/skills/skills/designer-perspective/scripts/designer.py +545 -545
- package/skills/skills/designer-perspective/tests/cases.jsonl +17 -17
- package/skills/skills/designer-perspective/tests/selftest.py +61 -61
- package/skills/skills/lingshu-browser/SKILL.md +60 -60
- package/skills/skills/lingshu-compiler/SKILL.md +56 -56
- package/skills/skills/lingshu-compiler/units/analyze-type-infer/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/check-name-real/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-assign/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-expr-tree/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-full-pipeline/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-func-def/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-if-then/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-logic-expr/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-recursive/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-scope/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-type-check/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-while/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0010c4bf/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0355bffb/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0361708a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-054a0414/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-05a1691a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-05eeed1e/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0622a1f6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-08b54217/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0a62b70c/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0ab24d00/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0e093688/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0e82b966/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0ee9b9b9/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0f3787e6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-1028685f/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-11897630/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-16661b9b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-1f722303/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-25be1262/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2a76ba07/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2dbea54a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2df52f16/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2ec2c9d2/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2f8c8f39/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-38378ac7/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-39457d2e/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-39fb5926/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-47f4fbfa/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4a8cd1f1/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4b230b6b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4cbbda95/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4d5a68ff/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-56dc9bdd/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-57e76ebe/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-61ff016b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-63eae588/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-64c4224b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-66377955/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-674ab4f6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6af76fd6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6d979db2/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6de326c0/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6f1c0eea/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-724d6c9b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-7690177f/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-7b229a7d/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-7f471b3a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-815cad08/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-83c61634/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-8c798c81/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-8dd747ac/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-90324d0a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-94b8d72d/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-94f12231/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-95937c16/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-98a5625b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-98b4c42f/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-98e3894a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-9bdfe4b8/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-9d9b4e83/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-9f7be5ad/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-a6daf076/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-a7995a0c/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-a8399248/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-aabbd099/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-afe169d8/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b0678bda/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b09bd196/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b1396e23/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b9b31ce0/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-c10264a7/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-cb1e8e4b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-ccafd438/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-cda9c262/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-ce648068/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-cf5776a4/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-d974e5d3/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-e3979fd3/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-eb1cf2b5/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-ecb30d5b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-f8c8b24b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-f99fedbe/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-fa8ff5f7/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-fe1b058d/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/lex-chinese-program/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/lex-dao-de-jing/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/lex-nine-chapters/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-arithmetic/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-array-ops/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-closure-call/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-closure-create/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-compare/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-cond-jump/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-cond-space/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-exception/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-func-call/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-loop-run/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-profiling/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-refcount/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-run-loop/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-short-circuit/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-stack-guard/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-stack-ops/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-trust-accum/SKILL.md +45 -45
- package/skills/skills/lingshu-graph/SKILL.md +63 -63
- package/skills/skills/lingshu-net/SKILL.md +48 -48
- package/skills/skills/lingshu-os/SKILL.md +64 -64
- package/skills/skills/lingshu-pylang/SKILL.md +71 -71
- package/src/bridge.ts +33 -0
- package/src/hooks.ts +38 -2
- package/src/index.ts +526 -518
- package/src/lib/datapath.ts +326 -326
- package/src/lib/mdcg_client.ts +413 -413
- package/src/lib/mutual.ts +428 -428
- package/src/lib/prompt_safety.ts +62 -62
- package/src/lib/python_path.ts +71 -71
- package/src/lib/roleplay_web.ts +116 -29
- package/src/lib/token_store.ts +13 -3
- package/src/tools.ts +212 -212
- package/zcode/AGENTS.md +11 -3
- package/zcode/README.md +41 -41
- /package/docs/{mdcg → hive}//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" +0 -0
package/md_cg/mcp_server.py
CHANGED
|
@@ -59,10 +59,11 @@ def _s(_desc, **props):
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
# 生效条件:始终返回 {"type":t,"description":desc},仅当 req 为真值时该字典额外含 "_req": True。
|
|
62
|
-
def _p(t, desc, req=False):
|
|
62
|
+
def _p(t, desc, req=False, **extra):
|
|
63
63
|
d = {"type": t, "description": desc}
|
|
64
64
|
if req:
|
|
65
65
|
d["_req"] = True
|
|
66
|
+
d.update(extra) # P2-22 前置(批次 24):node_id 等可传 pattern/maxLength
|
|
66
67
|
return d
|
|
67
68
|
|
|
68
69
|
|
|
@@ -103,12 +104,22 @@ TOOLS = [
|
|
|
103
104
|
"description": "写入一条记忆节点(md 认知图)。content 建议含 CCG 5 要素注释"
|
|
104
105
|
"(# 功能名/# 生效条件/# 子功能/# 执行/# 验证方式/# 不适用条件)。"
|
|
105
106
|
"gated=true 时先经主动遗忘闸门(三问→四态:ACCEPT/MERGE/DROP/DEFER),"
|
|
106
|
-
"适用于写入情景层记忆时的筛选(未指定 layer 时默认 contextual)。"
|
|
107
|
-
|
|
107
|
+
"适用于写入情景层记忆时的筛选(未指定 layer 时默认 contextual)。"
|
|
108
|
+
"写入恒带会话身份(session)以区分不同会话的记忆;省略则归因到"
|
|
109
|
+
"进程/环境身份。",
|
|
110
|
+
"inputSchema": _s("", node_id=_p("string", "节点 id(省略则自动生成)",
|
|
111
|
+
pattern="^[A-Za-z0-9_.@\u4e00-\u9fff,-]{1,128}$",
|
|
112
|
+
maxLength=128),
|
|
108
113
|
content=_p("string", "节点内容", True),
|
|
109
114
|
layer=_p("string", "层:anchor|structural|knowledge|contextual|self"),
|
|
110
115
|
role=_p("string", "角色:knowledge|user|assistant|tool-output|command|edit"
|
|
111
116
|
"(兼作来源证据:user=外部惊奇,command/tool-output=内部确定性)"),
|
|
117
|
+
session=_p("string", "本会话标识(归因维度,与授权无关):单进程服务"
|
|
118
|
+
"多个会话时用它声明这条记忆属于哪个会话,以便按会话"
|
|
119
|
+
"隔离检索。DSH 形态会校验会话真实存在(不存在降级 "
|
|
120
|
+
"anonymous),非 DSH 形态原样采用;部署侧已设 "
|
|
121
|
+
"MDCG_SESSION/DSH_SESSION_ID 时本参数被忽略(环境权威,"
|
|
122
|
+
"客户端不得改写归属)"),
|
|
112
123
|
tags=_p("array", "标签"), importance=_p("number", "重要性 0-1"),
|
|
113
124
|
importance_hint=_p("number", "闸门的重要性提示(≥0.7 保护优先直接 ACCEPT)"),
|
|
114
125
|
gated=_p("boolean", "启用主动遗忘闸门(默认否;写情景层建议开)"),
|
|
@@ -171,7 +182,10 @@ TOOLS = [
|
|
|
171
182
|
},
|
|
172
183
|
{
|
|
173
184
|
"name": "mdcg_get",
|
|
174
|
-
"description": "按 id 读取一个记忆节点(frontmatter + content)。"
|
|
185
|
+
"description": "按 id 读取一个记忆节点(frontmatter + content)。"
|
|
186
|
+
"id 不存在或密级不可读时返回 {ok:false, error:'not_found', "
|
|
187
|
+
"readable_sensitivities, hint}(不再返回裸 null——"
|
|
188
|
+
"调用方须能区分「没有」与「读不到」)。",
|
|
175
189
|
"inputSchema": _s("", node_id=_p("string", "节点 id", True)),
|
|
176
190
|
},
|
|
177
191
|
{
|
|
@@ -183,10 +197,13 @@ TOOLS = [
|
|
|
183
197
|
{
|
|
184
198
|
"name": "mdcg_verify",
|
|
185
199
|
"description": "验证单元:对节点做外部裁决 confirmed/weakened/falsified"
|
|
186
|
-
"(falsified 会移入 rejected/
|
|
200
|
+
"(falsified 会移入 rejected/ 负记忆;受保护节点"
|
|
201
|
+
" self/anchor 层、protected 标记、importance≥0.7 不可"
|
|
202
|
+
"一键证伪删除,需显式 override=true,旧版本自动快照+留痕)。",
|
|
187
203
|
"inputSchema": _s("", node_id=_p("string", "节点 id", True),
|
|
188
204
|
evidence=_p("string", "证据", True),
|
|
189
|
-
verdict=_p("string", "confirmed|weakened|falsified", True)
|
|
205
|
+
verdict=_p("string", "confirmed|weakened|falsified", True),
|
|
206
|
+
override=_p("boolean", "受保护节点需显式 true 才可证伪删除")),
|
|
190
207
|
},
|
|
191
208
|
{
|
|
192
209
|
"name": "mdcg_flywheel",
|
|
@@ -225,7 +242,9 @@ TOOLS = [
|
|
|
225
242
|
},
|
|
226
243
|
{
|
|
227
244
|
"name": "mdcg_review_decide",
|
|
228
|
-
"description": "审核裁决:accept / reject / edit / merge / noop(merge 需 merge_into
|
|
245
|
+
"description": "审核裁决:accept / reject / edit / merge / noop(merge 需 merge_into;"
|
|
246
|
+
"merge 与 add 同受写保护——目标层须可写,self/anchor/immutable "
|
|
247
|
+
"目标需显式 override=true)。"
|
|
229
248
|
"noop=已评估、判定不改变任何现有记忆:只留痕并关闭提案,"
|
|
230
249
|
"不落业务节点、不进负记忆(与 reject 的区别是语义而非路径)。"
|
|
231
250
|
"redteam.verdict=reject 不落库,转 needs_reapproval,"
|
|
@@ -235,7 +254,8 @@ TOOLS = [
|
|
|
235
254
|
edits=_p("object", "edit 时的覆盖字段"), merge_into=_p("string", "merge 目标节点 id"),
|
|
236
255
|
reason=_p("string", "裁决理由"),
|
|
237
256
|
redteam=_p("object", "红队裁决 {verdict:pass|reject, issues:[], round:n}"),
|
|
238
|
-
issues=_p("array", "问题清单(打回理由)")
|
|
257
|
+
issues=_p("array", "问题清单(打回理由)"),
|
|
258
|
+
override=_p("boolean", "merge 进受保护目标需显式 true")),
|
|
239
259
|
},
|
|
240
260
|
{
|
|
241
261
|
"name": "mdcg_review_records",
|
|
@@ -461,10 +481,13 @@ TOOLS = [
|
|
|
461
481
|
{
|
|
462
482
|
"name": "mdcg_ingest",
|
|
463
483
|
"description": "设备驱动:从会话文件增量摄取事件(自动 fix-pair 挖掘 + watermark 去重)。"
|
|
464
|
-
"source=auto 时自动发现本机 DSH
|
|
484
|
+
"source=auto 时自动发现本机 DSH 会话,按**文件体积**降序选取"
|
|
485
|
+
"(不是按最近活动);选中的会话与候选明细见返回体 selection 字段。",
|
|
465
486
|
"inputSchema": _s("", source=_p("string", "会话文件路径,或 'auto' 自动发现 DSH 会话"),
|
|
466
487
|
max_events=_p("integer", "单次最多摄取事件数"),
|
|
467
|
-
mine_fix_pairs=_p("boolean", "
|
|
488
|
+
mine_fix_pairs=_p("boolean", "是否自动挖掘错误→修复对(默认否——"
|
|
489
|
+
"先落账后挖矿;显式开启时产物走 propose "
|
|
490
|
+
"审核队列,不直写知识层)"),
|
|
468
491
|
dry_run=_p("boolean", "只统计不写入")),
|
|
469
492
|
},
|
|
470
493
|
{
|
|
@@ -591,8 +614,11 @@ KERNEL_TOOLS = [
|
|
|
591
614
|
"op=session:会话三件套(action=note 写要点 / recall 续接 / "
|
|
592
615
|
"compact 压摘要;hook 缺失时的库侧替代——载体负责「何时做」、库保证"
|
|
593
616
|
"「一次调用就够用」;note 与 compact(note=True) 需 can_write,recall 只读);"
|
|
594
|
-
"op=ingest:文件摄取(action=file|dir|jsonl|stat;写链需 can_write,"
|
|
595
|
-
|
|
617
|
+
"op=ingest:文件摄取(action=file|dir|jsonl|stat|hive;写链需 can_write,"
|
|
618
|
+
"支持 dry_run 预演与 incremental 增量去重、watermark 留痕;"
|
|
619
|
+
"mine_fix_pairs 全入口默认关(先落账后挖矿,显式开启走 propose 队列);"
|
|
620
|
+
"hive=蜂巢任务事件源——path=hive/jobs 目录或 env MDCG_HIVE_JOBS,"
|
|
621
|
+
"只落 contextual,error 事件自动 private);"
|
|
596
622
|
"op=export:全库导出(action=graph|nodes|slice|stat;导出整库属管理"
|
|
597
623
|
"操作,一律 require_admin);"
|
|
598
624
|
"op=maintain:记忆维护(action=stat|history|importance|longterm|"
|
|
@@ -735,7 +761,7 @@ KERNEL_TOOLS = [
|
|
|
735
761
|
"derive_catalog|derive_rebuild|catalog;"
|
|
736
762
|
"ref: read|check|stat|prune;"
|
|
737
763
|
"session: note|recall|compact;"
|
|
738
|
-
"ingest: file|dir|jsonl|stat;"
|
|
764
|
+
"ingest: file|dir|jsonl|stat|hive;"
|
|
739
765
|
"export: graph|nodes|slice|stat;"
|
|
740
766
|
"maintain: stat|history|importance|longterm|prefeed|"
|
|
741
767
|
"separate|rollback|backfill|backfill_rollback|"
|
|
@@ -948,7 +974,9 @@ KERNEL_TOOLS = [
|
|
|
948
974
|
"name": "stg",
|
|
949
975
|
"description": "语义时空图接口:精确得到信息的时间/空间关系。"
|
|
950
976
|
"op=relation:两节点时空关系(Allen 时间 6 态 + RCC 空间 7 态);"
|
|
951
|
-
"op=timeline
|
|
977
|
+
"op=timeline:按时间排序(可用 session 切本会话/跨会话视图,"
|
|
978
|
+
"看「所有会话做了什么」传 session=\"*\",返回项带会话归属);"
|
|
979
|
+
"op=anchors:落在时间窗/空间范围的节点;"
|
|
952
980
|
"op=consistency:时空字段自洽性检查。"
|
|
953
981
|
"四个 op 均可用 time_axis 切换时间轴(缺省 observed)。",
|
|
954
982
|
"inputSchema": _s("",
|
|
@@ -957,6 +985,10 @@ KERNEL_TOOLS = [
|
|
|
957
985
|
time_window=_p("array", "anchors 的时间窗 [t1,t2]"),
|
|
958
986
|
bbox=_p("array", "anchors 的包围盒 [x1,y1,x2,y2]"),
|
|
959
987
|
layer=_p("string", "限定层"), limit=_p("integer", "返回条数"),
|
|
988
|
+
session=_p("string", "timeline 的会话视图开关(归因维度,与授权无关):"
|
|
989
|
+
"省略 = 不过滤(读遍所有会话,向后兼容);\"*\" = 显式"
|
|
990
|
+
"跨会话,与「忘了传参」区分开;其它值 = 只取该会话"
|
|
991
|
+
"(frontmatter.session 精确相等)"),
|
|
960
992
|
desc=_p("boolean", "timeline 是否倒序(默认是)"),
|
|
961
993
|
time_axis=_p("string", "时间轴:observed(观察轴 temporal/time_window,"
|
|
962
994
|
"缺省)| effective(效力轴 effective_from/until)")),
|
|
@@ -1064,6 +1096,15 @@ def _trust_state(fm):
|
|
|
1064
1096
|
return None
|
|
1065
1097
|
|
|
1066
1098
|
|
|
1099
|
+
# 生效条件:cg 具有 whoami() 且其返回 dict 含 readable_sensitivities 时返回该值;cg 无该方法或抛异常时返回 None(不编造、不抛)。
|
|
1100
|
+
def _readable_sensitivities(cg):
|
|
1101
|
+
"""当前身份可读密级(whoami 同源;取不到返回 None,不编造)。"""
|
|
1102
|
+
try:
|
|
1103
|
+
return (cg.whoami() or {}).get("readable_sensitivities")
|
|
1104
|
+
except Exception:
|
|
1105
|
+
return None
|
|
1106
|
+
|
|
1107
|
+
|
|
1067
1108
|
def _node_view(node, offset: int = 0):
|
|
1068
1109
|
if not node:
|
|
1069
1110
|
return None
|
|
@@ -2001,6 +2042,10 @@ def _cg_dispatch(cg, a):
|
|
|
2001
2042
|
limit=int(a.get("limit") or a.get("k") or 100))
|
|
2002
2043
|
if act in ("export", "evidence_export"):
|
|
2003
2044
|
from . import evidence as _ev
|
|
2045
|
+
from .security import check_path_root
|
|
2046
|
+
# P1-4(批次 26):证据包写/读路径根约束(报告点名的
|
|
2047
|
+
# 「link export 不经 require_admin → 任意文件写」缺口)
|
|
2048
|
+
check_path_root(a.get("out"), "MDCG_EXPORT_ROOT", "link/export")
|
|
2004
2049
|
subs = a.get("subjects") or a.get("subject")
|
|
2005
2050
|
if isinstance(subs, str):
|
|
2006
2051
|
subs = [subs]
|
|
@@ -2014,6 +2059,9 @@ def _cg_dispatch(cg, a):
|
|
|
2014
2059
|
return res
|
|
2015
2060
|
if act in ("import", "evidence_import"):
|
|
2016
2061
|
from . import evidence as _ev
|
|
2062
|
+
from .security import check_path_root
|
|
2063
|
+
check_path_root(a.get("path") or a.get("pack"),
|
|
2064
|
+
"MDCG_EXPORT_ROOT", "link/import")
|
|
2017
2065
|
src = a.get("path") or a.get("pack")
|
|
2018
2066
|
if isinstance(src, str) and src.lstrip().startswith("{"):
|
|
2019
2067
|
src = json.loads(src)
|
|
@@ -2103,7 +2151,9 @@ def _cg_dispatch(cg, a):
|
|
|
2103
2151
|
return _node_view(cg.get(a["node_id"]),
|
|
2104
2152
|
offset=int(a.get("offset") or 0))
|
|
2105
2153
|
q = a.get("query") or a.get("intent") or ""
|
|
2106
|
-
if a.get("budget_tokens")
|
|
2154
|
+
# 显式 0 也是「显式」(2026-09-24 修复):旧写法 `if a.get("budget_tokens")`
|
|
2155
|
+
# 把 0 当没传,静默换成 1200 —— 调用方以为「零预算」拿到的是满预算结果。
|
|
2156
|
+
if a.get("budget_tokens") is not None:
|
|
2107
2157
|
return cg.recall(q, budget_tokens=int(a["budget_tokens"]),
|
|
2108
2158
|
k=int(a.get("k") or 20), context=a.get("context"),
|
|
2109
2159
|
goal_text=a.get("goal"),
|
|
@@ -2165,7 +2215,8 @@ def _cg_dispatch(cg, a):
|
|
|
2165
2215
|
|
|
2166
2216
|
if op == "verify":
|
|
2167
2217
|
return cg.verify(a.get("node_id", ""), a.get("evidence", ""),
|
|
2168
|
-
a.get("verdict", "")
|
|
2218
|
+
a.get("verdict", ""),
|
|
2219
|
+
override=bool(a.get("override")))
|
|
2169
2220
|
|
|
2170
2221
|
if op == "review":
|
|
2171
2222
|
act = (a.get("action") or "list").strip().lower()
|
|
@@ -2185,7 +2236,8 @@ def _cg_dispatch(cg, a):
|
|
|
2185
2236
|
return cg.review_decide(a.get("pid", ""), a.get("decision", ""),
|
|
2186
2237
|
edits=a.get("edits"), merge_into=a.get("merge_into"),
|
|
2187
2238
|
reason=a.get("reason", ""),
|
|
2188
|
-
redteam=a.get("redteam"), issues=a.get("issues")
|
|
2239
|
+
redteam=a.get("redteam"), issues=a.get("issues"),
|
|
2240
|
+
override=bool(a.get("override")))
|
|
2189
2241
|
|
|
2190
2242
|
if op == "forget":
|
|
2191
2243
|
if (a.get("action") or "forget").strip().lower() == "restore":
|
|
@@ -2228,7 +2280,12 @@ def _cg_dispatch(cg, a):
|
|
|
2228
2280
|
|
|
2229
2281
|
if op == "index_code":
|
|
2230
2282
|
from . import refindex
|
|
2283
|
+
from .security import check_path_root
|
|
2231
2284
|
root = a.get("path") or cg.root
|
|
2285
|
+
# P1-X:path 是模型可控输入——索引会读取目录下全部
|
|
2286
|
+
# 命中文件。根白名单与 ingest 的 P1-4 同语义:显式 path 越界即拒;
|
|
2287
|
+
# 未传(回落服务器侧 cg.root)不校验,默认部署行为不变。
|
|
2288
|
+
check_path_root(a.get("path"), "MDCG_INGEST_ROOT", "index_code")
|
|
2232
2289
|
if not os.path.isdir(root):
|
|
2233
2290
|
return {"ok": False, "error": f"目录不存在:{root}"}
|
|
2234
2291
|
items, errors, stats = refindex.index_dir(
|
|
@@ -2260,7 +2317,11 @@ def _cg_dispatch(cg, a):
|
|
|
2260
2317
|
|
|
2261
2318
|
if op == "index_doc":
|
|
2262
2319
|
from . import refindex
|
|
2320
|
+
from .security import check_path_root
|
|
2263
2321
|
root = a.get("path") or cg.root
|
|
2322
|
+
# P1-X:与 index_code 同族——path 模型可控,根白名单
|
|
2323
|
+
# 越界即拒;未传(回落 cg.root)不校验,默认部署行为不变。
|
|
2324
|
+
check_path_root(a.get("path"), "MDCG_INGEST_ROOT", "index_doc")
|
|
2264
2325
|
if not os.path.isdir(root):
|
|
2265
2326
|
return {"ok": False, "error": f"目录不存在:{root}"}
|
|
2266
2327
|
layer = a.get("layer") or "knowledge"
|
|
@@ -2326,7 +2387,10 @@ def _ccg_call(cg, a):
|
|
|
2326
2387
|
"""CCG 六要素编译器(op=ccg):对话记录 → 六要素候选 → **编外复核** → 落库。
|
|
2327
2388
|
|
|
2328
2389
|
定位:**记忆可靠性闸**——不是又一个写入通道,而是写入前「条件是否成立」的检查。
|
|
2329
|
-
裁定 A(LLM 不得自己验证自己)由 ccgc 的 E041
|
|
2390
|
+
裁定 A(LLM 不得自己验证自己)由 ccgc 的 E041 机械执行,不依赖 prompt 自觉。
|
|
2391
|
+
阻断强度如实分层(issue #27):身份归一比较拦截同源字符串变体;根本保障是
|
|
2392
|
+
verifier_token 凭据(mdcg 令牌 HMAC 验签)——无令牌时签章标
|
|
2393
|
+
verifier_identity="self-reported",下游策略可据此识别可信级别。
|
|
2330
2394
|
|
|
2331
2395
|
action(缺省 compile):
|
|
2332
2396
|
compile 对话记录 → 六要素候选(五环编译);候选+签章槽落
|
|
@@ -2433,7 +2497,8 @@ def _ccg_call(cg, a):
|
|
|
2433
2497
|
at = ccgc.attest(node_id, args.get("verdict") or ccgc.DEFER,
|
|
2434
2498
|
args.get("verifier") or "", compiled.actor or actor,
|
|
2435
2499
|
slot_corrections=args.get("slot_corrections"),
|
|
2436
|
-
evidence=args.get("evidence") or "", cg=cg
|
|
2500
|
+
evidence=args.get("evidence") or "", cg=cg,
|
|
2501
|
+
verifier_token=str(args.get("verifier_token") or ""))
|
|
2437
2502
|
out["attest"] = ccgc.asdict(at)
|
|
2438
2503
|
out["pending"] = ccgc.save_pending(cg, compiled, at)
|
|
2439
2504
|
out["hint"] = ("已签章(%s);下一步 cg(op=ccg, action=link, "
|
|
@@ -2453,7 +2518,8 @@ def _ccg_call(cg, a):
|
|
|
2453
2518
|
str(o.get("verifier") or ""),
|
|
2454
2519
|
str(o.get("compiled_by") or compiled.actor or actor),
|
|
2455
2520
|
slot_corrections=o.get("slot_corrections"),
|
|
2456
|
-
evidence=str(o.get("evidence") or ""), cg=cg
|
|
2521
|
+
evidence=str(o.get("evidence") or ""), cg=cg,
|
|
2522
|
+
verifier_token=str(o.get("verifier_token") or ""))
|
|
2457
2523
|
return {"ok": bool(at.ok), "op": "ccg", "action": "attest",
|
|
2458
2524
|
"attest": ccgc.asdict(at),
|
|
2459
2525
|
"pending": ccgc.save_pending(cg, compiled, at),
|
|
@@ -2517,7 +2583,9 @@ def _session_call(cg, a):
|
|
|
2517
2583
|
return cg.session_recall(
|
|
2518
2584
|
session=a.get("session"), limit=int(a.get("limit") or 5),
|
|
2519
2585
|
recent_limit=int(a.get("recent_limit") or 10),
|
|
2520
|
-
|
|
2586
|
+
# `is not None`:显式 0 不再被吞成默认 1200(2026-09-24 修复)
|
|
2587
|
+
budget_tokens=int(a["budget_tokens"])
|
|
2588
|
+
if a.get("budget_tokens") is not None else 1200,
|
|
2521
2589
|
include_state=bool(a.get("include_state", True)))
|
|
2522
2590
|
if act == "compact":
|
|
2523
2591
|
if a.get("note") and principal is not None \
|
|
@@ -2569,7 +2637,7 @@ def _skip_dirs_report(stats, limit=20):
|
|
|
2569
2637
|
return out
|
|
2570
2638
|
|
|
2571
2639
|
|
|
2572
|
-
#
|
|
2640
|
+
# 生效条件:先经 check_path_root(a.get("path"), "MDCG_INGEST_ROOT", "ingest")(env 未设置或 path 空时放行,越界抛 PermissionError);act=(a.get("action") or "stat").strip().lower();act 属 ("file","dir","jsonl") 且 principal 非 None 且其 can_write 为假时先 require_admin(f"ingest_{act}"),随后以 action=act 及各透传参数调 sources.run 并返回。
|
|
2573
2641
|
def _ingest_call(cg, a):
|
|
2574
2642
|
"""文件摄取分派(P0):file / dir / jsonl / stat。
|
|
2575
2643
|
|
|
@@ -2577,7 +2645,11 @@ def _ingest_call(cg, a):
|
|
|
2577
2645
|
支持 dry_run 预演(对应计划「可预演」要求)。
|
|
2578
2646
|
"""
|
|
2579
2647
|
from . import sources
|
|
2648
|
+
from .security import check_path_root
|
|
2580
2649
|
act = (a.get("action") or "stat").strip().lower()
|
|
2650
|
+
# P1-4(批次 26):ingest 的 path 是模型可控输入——根白名单约束
|
|
2651
|
+
# (MDCG_INGEST_ROOT 设置时越界即拒;未设置保持现状)
|
|
2652
|
+
check_path_root(a.get("path"), "MDCG_INGEST_ROOT", "ingest")
|
|
2581
2653
|
principal = getattr(cg, "principal", None)
|
|
2582
2654
|
if act in ("file", "dir", "jsonl") and principal is not None \
|
|
2583
2655
|
and not getattr(principal, "can_write", False):
|
|
@@ -2590,17 +2662,20 @@ def _ingest_call(cg, a):
|
|
|
2590
2662
|
max_events=a.get("max_events"))
|
|
2591
2663
|
|
|
2592
2664
|
|
|
2593
|
-
#
|
|
2665
|
+
# 生效条件:先经 require_admin("export_{act}")(principal 非 None 时)与 check_path_root(a.get("out"), "MDCG_EXPORT_ROOT", "export")(env 未设置或 out 空时放行,越界抛 PermissionError);act=(a.get("action") or "stat").strip().lower();principal 非 None 时一律先 require_admin(f"export_{act}"),随后以 include_content=True if a.get("include_content") is None else bool(a.get("include_content")) 等参数调 _ex.run 并返回。
|
|
2594
2666
|
def _export_call(cg, a):
|
|
2595
2667
|
"""全库导出(P0):graph / nodes / slice / stat。
|
|
2596
2668
|
|
|
2597
2669
|
导出整库属**管理操作** → 一律 require_admin(designer 专属)。
|
|
2598
2670
|
"""
|
|
2599
2671
|
from . import export as _ex
|
|
2672
|
+
from .security import check_path_root
|
|
2600
2673
|
act = (a.get("action") or "stat").strip().lower()
|
|
2601
2674
|
principal = getattr(cg, "principal", None)
|
|
2602
2675
|
if principal is not None:
|
|
2603
2676
|
principal.require_admin(f"export_{act}")
|
|
2677
|
+
# P1-4(批次 26):export 的 out 是写路径——根白名单约束
|
|
2678
|
+
check_path_root(a.get("out"), "MDCG_EXPORT_ROOT", "export")
|
|
2604
2679
|
inc = a.get("include_content")
|
|
2605
2680
|
return _ex.run(
|
|
2606
2681
|
cg, action=act, out=a.get("out"), ids=a.get("ids"),
|
|
@@ -2826,6 +2901,17 @@ def _ref_call(cg, a):
|
|
|
2826
2901
|
if not ref:
|
|
2827
2902
|
return {"ok": False,
|
|
2828
2903
|
"error": "该节点没有 code_ref/doc_ref(不是索引节点)"}
|
|
2904
|
+
# P1-X(两份独立报告合并):ref 回读是任意文件读原语——
|
|
2905
|
+
# 自报 root、inline ref 自带的 root/path 均模型可控,probe_ref 直接
|
|
2906
|
+
# os.path.join 后 open 全文回读(绝对 path 丢弃 root、'..' 上跳同漏)。
|
|
2907
|
+
# 按最终将打开的完整路径过根白名单:env 未设置=放开(部署开关,与
|
|
2908
|
+
# P1-4 的 ingest/export/link 同语义);设置了=realpath 落根内否则拒
|
|
2909
|
+
# (fail-closed),上跳与绝对路径在 realpath 归一后自然涵盖。
|
|
2910
|
+
from .security import check_path_root
|
|
2911
|
+
check_path_root(
|
|
2912
|
+
os.path.join(a.get("root") or ref.get("root") or "",
|
|
2913
|
+
ref.get("path") or ""),
|
|
2914
|
+
"MDCG_INGEST_ROOT", "ref")
|
|
2829
2915
|
out = refindex.read_ref(ref, root=a.get("root"), ref_kind=ref_kind)
|
|
2830
2916
|
out["node_id"] = nid or None
|
|
2831
2917
|
return out
|
|
@@ -2842,7 +2928,7 @@ def _whitebox_call(cg, a):
|
|
|
2842
2928
|
return whitebox.dispatch(cg, a)
|
|
2843
2929
|
|
|
2844
2930
|
|
|
2845
|
-
# 生效条件:op=(a.get("op") or "").strip().lower();op=="relation" 时返回 stg.relation(cg, a.get("a",""), a.get("b",""));op=="timeline" 时返回 stg.timeline(cg, layer=a.get("layer"), limit=int(a.get("limit") or 50), desc=bool(a.get("desc", True)))
|
|
2931
|
+
# 生效条件:op=(a.get("op") or "").strip().lower();op=="relation" 时返回 stg.relation(cg, a.get("a",""), a.get("b",""), time_axis=axis);op=="timeline" 时返回 stg.timeline(cg, layer=a.get("layer"), limit=int(a.get("limit") or 50), desc=bool(a.get("desc", True)), time_axis=axis, session=a.get("session"))(session 缺省不过滤读遍所有会话,"*" = 显式跨会话,其它值 = 本会话视图);op=="anchors" 时返回 stg.anchors(cg, time_window=a.get("time_window"), bbox=a.get("bbox"), layer=a.get("layer"), limit=int(a.get("limit") or 50));op=="consistency" 时返回 stg.consistency(cg, layer=a.get("layer"), limit=int(a.get("limit") or 50));op 为空或其它的值抛 ValueError。
|
|
2846
2932
|
def _stg_call(cg, a):
|
|
2847
2933
|
"""语义时空图唯一入口。
|
|
2848
2934
|
|
|
@@ -2860,7 +2946,10 @@ def _stg_call(cg, a):
|
|
|
2860
2946
|
if op == "timeline":
|
|
2861
2947
|
return stg.timeline(cg, layer=a.get("layer"),
|
|
2862
2948
|
limit=int(a.get("limit") or 50),
|
|
2863
|
-
desc=bool(a.get("desc", True)), time_axis=axis
|
|
2949
|
+
desc=bool(a.get("desc", True)), time_axis=axis,
|
|
2950
|
+
# 会话视图:缺省读遍所有会话,"*" = 显式跨会话,
|
|
2951
|
+
# 其它值 = 本会话视图(自动召回走这条防串台)
|
|
2952
|
+
session=a.get("session"))
|
|
2864
2953
|
if op == "anchors":
|
|
2865
2954
|
return stg.anchors(cg, time_window=a.get("time_window"), bbox=a.get("bbox"),
|
|
2866
2955
|
layer=a.get("layer"), limit=int(a.get("limit") or 50),
|
|
@@ -2881,42 +2970,97 @@ def _stg_call(cg, a):
|
|
|
2881
2970
|
# 工具实现
|
|
2882
2971
|
# --------------------------------------------------------------------------
|
|
2883
2972
|
|
|
2884
|
-
# 生效条件:a=args or {},unit=(a.get("as_unit") or "").strip();
|
|
2973
|
+
# 生效条件:a=args or {},unit=(a.get("as_unit") or "").strip(),sess=_declared_session(a.get("session"));cg.principal 为 None 或 unit 与 sess 皆为空时直接返回 _dispatch(cg,name,a);否则先 narrowed_principal(cg.principal, unit)(TokenError 时返回 {"ok":False,"error":f"as_unit 非法:{e}"}),sess 非空时再以 copy 出的 Principal 覆盖 session,暂存 cg.principal/cg.session、置为作用域值、try 返回 _dispatch、finally 还原。
|
|
2885
2974
|
def call_tool(cg, name, args):
|
|
2886
|
-
"""MCP tools/call 入口:按 `as_unit`
|
|
2975
|
+
"""MCP tools/call 入口:按 `as_unit` 做**请求级身份收窄**(单进程多身份),
|
|
2976
|
+
按 `session` 做**请求级会话归因**(单进程多会话)。
|
|
2887
2977
|
|
|
2888
|
-
|
|
2978
|
+
三个身份维度的职责分离(勿混):
|
|
2889
2979
|
· env 身份(MDCG_TOKEN)—— **谁装了这个大脑**,是权限上限,进程级恒定;
|
|
2890
|
-
· `as_unit` ——
|
|
2980
|
+
· `as_unit` —— 本次调用以哪个**单元**执行,请求级、可缺省,参与授权;
|
|
2981
|
+
· `session` —— 本次调用属于哪个**会话**,请求级、可缺省,**只影响归因**
|
|
2982
|
+
(不参与任何 ops 裁决;来源优先级见 `_declared_session`)。
|
|
2891
2983
|
|
|
2892
2984
|
收窄由 `tokens.narrowed_principal` 保证「只能变小不能变大」(求交 +
|
|
2893
2985
|
can_admin 恒 False),故调用方即使伪造 `as_unit` 也无法提权——最坏等于
|
|
2894
2986
|
不传(owner 全权)。这是本机制**不需要对 `as_unit` 额外鉴权**的根据。
|
|
2987
|
+
`session` 同理不需要额外鉴权:它不参与任何 ops 裁决,最坏是贴错标签。
|
|
2895
2988
|
|
|
2896
2989
|
`as_unit` 与 `unit` 字段**职责分离**:
|
|
2897
2990
|
· `as_unit` —— 受限枚举(五单元),参与授权;未知值 fail-closed 报错;
|
|
2898
2991
|
· `unit` —— 自由文本,仅归因(进 _audit / _recent),不参与授权。
|
|
2899
2992
|
"""
|
|
2900
2993
|
a = args or {}
|
|
2994
|
+
p = getattr(cg, "principal", None)
|
|
2995
|
+
if p is None:
|
|
2996
|
+
return _dispatch(cg, name, a)
|
|
2901
2997
|
unit = (a.get("as_unit") or "").strip()
|
|
2902
|
-
|
|
2998
|
+
sess = _declared_session(a.get("session"))
|
|
2999
|
+
scope = p
|
|
3000
|
+
if unit:
|
|
3001
|
+
from .tokens import TokenError, narrowed_principal
|
|
3002
|
+
try:
|
|
3003
|
+
scope = narrowed_principal(p, unit)
|
|
3004
|
+
except TokenError as e:
|
|
3005
|
+
return {"ok": False, "error": f"as_unit 非法:{e}"}
|
|
3006
|
+
# 请求级 session 只做**归因**(cg.session,写入归属/_attribution 取它),
|
|
3007
|
+
# **不**改 principal.session——绑定档(private/secret)的读授权锚定连接级
|
|
3008
|
+
# 身份(issue #35 会话隔离定稿:调用方自报的会话不得成为看他人 private
|
|
3009
|
+
# 的授权;与上方「session 不参与任何 ops 裁决」的原设计意图一致)。
|
|
3010
|
+
if scope is p and not sess:
|
|
2903
3011
|
return _dispatch(cg, name, a)
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
saved = cg.principal
|
|
2910
|
-
cg.principal = narrowed # 单线程 stdin 循环:无并发竞争
|
|
3012
|
+
saved_p, saved_s = cg.principal, getattr(cg, "session", None)
|
|
3013
|
+
had_s = hasattr(cg, "session")
|
|
3014
|
+
cg.principal = scope # 单线程 stdin 循环:无并发竞争
|
|
3015
|
+
if had_s:
|
|
3016
|
+
cg.session = sess or scope.session
|
|
2911
3017
|
try:
|
|
2912
3018
|
return _dispatch(cg, name, a)
|
|
2913
3019
|
finally:
|
|
2914
|
-
cg.principal =
|
|
3020
|
+
cg.principal = saved_p
|
|
3021
|
+
if had_s:
|
|
3022
|
+
cg.session = saved_s
|
|
3023
|
+
|
|
3024
|
+
|
|
3025
|
+
# P1-1(批次 24,外部审查报告):mdcg_* 工具的 op 要求映射——此前 require_op
|
|
3026
|
+
# 只在 _cg_dispatch(cg 工具)内生效,mdcg_* 分支直接落库层(只验
|
|
3027
|
+
# can_write/层/密级,不验 ops_allow)→「--ops-allow read」的只读令牌仍可经
|
|
3028
|
+
# mdcg_remember 写入,权限收窄形同虚设。映射用令牌签发域内的既有 op 词
|
|
3029
|
+
# (read/write/verify——tokens.ROLE_SPECS 全角色都含 read,写类角色含
|
|
3030
|
+
# write),ops_allow=None(不限)令牌零影响。
|
|
3031
|
+
_MDCG_OP_REQUIRE = {
|
|
3032
|
+
# 写面
|
|
3033
|
+
"mdcg_remember": "write", "mdcg_reflect": "write",
|
|
3034
|
+
"mdcg_flywheel": "write", "mdcg_mine_fix_pairs": "write",
|
|
3035
|
+
"mdcg_rejected": "write", "mdcg_unresolved": "write",
|
|
3036
|
+
"mdcg_propose": "write", "mdcg_review_decide": "write",
|
|
3037
|
+
"mdcg_forget": "write", "mdcg_restore": "write",
|
|
3038
|
+
"mdcg_protect": "write", "mdcg_ingest": "write",
|
|
3039
|
+
"mdcg_consistency": "write",
|
|
3040
|
+
# 读面
|
|
3041
|
+
"mdcg_recall": "read", "mdcg_search": "read", "mdcg_get": "read",
|
|
3042
|
+
"mdcg_review_list": "read", "mdcg_review_records": "read",
|
|
3043
|
+
"mdcg_forgetting_history": "read", "mdcg_identity": "read",
|
|
3044
|
+
"mdcg_metacognition": "read", "mdcg_self_state": "read",
|
|
3045
|
+
"mdcg_predict": "read", "mdcg_causal": "read",
|
|
3046
|
+
"mdcg_evolution": "read", "mdcg_health": "read",
|
|
3047
|
+
"mdcg_whoami": "read", "mdcg_watermarks": "read",
|
|
3048
|
+
"mdcg_whitebox": "read",
|
|
3049
|
+
# 裁决面(仅高权角色域含 verify)
|
|
3050
|
+
"mdcg_verify": "verify",
|
|
3051
|
+
}
|
|
2915
3052
|
|
|
2916
3053
|
|
|
2917
|
-
# 生效条件:name 为已注册工具名之一(cg / stg / mdcg_whitebox / mdcg_service_info / mdcg_remember
|
|
3054
|
+
# 生效条件:name 为已注册工具名之一(cg / stg / mdcg_whitebox / mdcg_service_info / mdcg_remember 等);name 属 _MDCG_OP_REQUIRE 且 cg.principal 具 require_op 属性时先 require_op(越权抛 AccessDenied),principal 为 None 或无该方法时跳过;cg 走 _cg_call、stg 走 _stg_call、whitebox 走 _whitebox_call;未识别的 name 返回含 error 的响应字典而不抛异常,进程不因此中断;
|
|
2918
3055
|
def _dispatch(cg, name, args):
|
|
2919
3056
|
a = args or {}
|
|
3057
|
+
# P1-1:mdcg_* 面的角色作用域闸(与 cg 工具的 require_op 同一语义——
|
|
3058
|
+
# ops_allow=None 令牌不受影响;受限令牌越权即 AccessDenied)
|
|
3059
|
+
_need_op = _MDCG_OP_REQUIRE.get(name)
|
|
3060
|
+
if _need_op:
|
|
3061
|
+
_p = getattr(cg, "principal", None)
|
|
3062
|
+
if _p is not None and hasattr(_p, "require_op"):
|
|
3063
|
+
_p.require_op(_need_op)
|
|
2920
3064
|
if name == "cg":
|
|
2921
3065
|
return _cg_call(cg, a)
|
|
2922
3066
|
if name == "stg":
|
|
@@ -2990,7 +3134,9 @@ def _dispatch(cg, name, args):
|
|
|
2990
3134
|
# 直接引用 mdcos.DEFAULT_MAX_ITEM_TOKENS 会 NameError —— 故此处按需导入)。
|
|
2991
3135
|
from .mdcos import DEFAULT_MAX_ITEM_TOKENS as _DEFAULT_MAX_ITEM
|
|
2992
3136
|
return cg.recall(a.get("query", ""),
|
|
2993
|
-
|
|
3137
|
+
# `is not None`:显式 0 不再被吞成默认 1200(2026-09-24 修复)
|
|
3138
|
+
budget_tokens=int(a["budget_tokens"])
|
|
3139
|
+
if a.get("budget_tokens") is not None else 1200,
|
|
2994
3140
|
max_item_tokens=int(a["max_item_tokens"])
|
|
2995
3141
|
if a.get("max_item_tokens") is not None
|
|
2996
3142
|
else _DEFAULT_MAX_ITEM,
|
|
@@ -3019,15 +3165,24 @@ def _dispatch(cg, name, args):
|
|
|
3019
3165
|
for n, s, q in res]}
|
|
3020
3166
|
|
|
3021
3167
|
if name == "mdcg_get":
|
|
3022
|
-
|
|
3023
|
-
|
|
3168
|
+
_nid = a.get("node_id", "")
|
|
3169
|
+
node = cg.get(_nid)
|
|
3170
|
+
if not node:
|
|
3171
|
+
# 裸 null 让调用方无从区分「id 不存在」与「密级不可读」(2026-09-24 修复)
|
|
3172
|
+
return {"ok": False, "error": "not_found", "node_id": _nid,
|
|
3173
|
+
"readable_sensitivities": _readable_sensitivities(cg),
|
|
3174
|
+
"hint": "id 不存在(或已被清退/证伪移入 rejected),"
|
|
3175
|
+
"或该节点密级高于当前身份可读——whoami 可查 clearance"}
|
|
3176
|
+
return _node_view(node, offset=int(a.get("offset") or 0))
|
|
3024
3177
|
|
|
3025
3178
|
if name == "mdcg_reflect":
|
|
3026
3179
|
res, _ = cg.search(a.get("query", ""), k=int(a.get("k") or 10), record=False)
|
|
3027
3180
|
return cg.reflect(a.get("query", ""), res, a.get("feedback"))
|
|
3028
3181
|
|
|
3029
3182
|
if name == "mdcg_verify":
|
|
3030
|
-
return cg.verify(a.get("node_id", ""), a.get("evidence", ""),
|
|
3183
|
+
return cg.verify(a.get("node_id", ""), a.get("evidence", ""),
|
|
3184
|
+
a.get("verdict", ""),
|
|
3185
|
+
override=bool(a.get("override")))
|
|
3031
3186
|
|
|
3032
3187
|
if name == "mdcg_flywheel":
|
|
3033
3188
|
return cg.flywheel_step(a.get("error_report") or {})
|
|
@@ -3065,7 +3220,8 @@ def _dispatch(cg, name, args):
|
|
|
3065
3220
|
return cg.review_decide(a.get("pid", ""), a.get("decision", ""),
|
|
3066
3221
|
edits=a.get("edits"), merge_into=a.get("merge_into"),
|
|
3067
3222
|
reason=a.get("reason", ""),
|
|
3068
|
-
redteam=a.get("redteam"), issues=a.get("issues")
|
|
3223
|
+
redteam=a.get("redteam"), issues=a.get("issues"),
|
|
3224
|
+
override=bool(a.get("override")))
|
|
3069
3225
|
|
|
3070
3226
|
if name == "mdcg_review_records":
|
|
3071
3227
|
nid = a.get("node_id")
|
|
@@ -3116,18 +3272,43 @@ def _dispatch(cg, name, args):
|
|
|
3116
3272
|
if name == "mdcg_ingest":
|
|
3117
3273
|
from .sources import DSHSessionSource, JsonlSource, Ingestor
|
|
3118
3274
|
src_arg = (a.get("source") or "auto").strip()
|
|
3275
|
+
# P1-4(批次 26):报告点名「mdcg_ingest 完全没有权限闸」——权限闸
|
|
3276
|
+
# 已由批次 24 _MDCG_OP_REQUIRE(write)补上,此处补路径根约束;
|
|
3277
|
+
# auto(自动发现 ~/.dsh/sessions)不经路径参数
|
|
3278
|
+
from .security import check_path_root
|
|
3279
|
+
if src_arg != "auto":
|
|
3280
|
+
check_path_root(src_arg, "MDCG_INGEST_ROOT", "mdcg_ingest")
|
|
3119
3281
|
ing = Ingestor(cg)
|
|
3282
|
+
picked, cands = None, []
|
|
3120
3283
|
if src_arg == "auto":
|
|
3121
|
-
|
|
3122
|
-
|
|
3284
|
+
# `discover_detailed` 是排序的唯一真源;候选明细留在手里,
|
|
3285
|
+
# 才能在返回体里回答「为什么选中它」(issue #23 附带建议)。
|
|
3286
|
+
cands = DSHSessionSource.discover_detailed()
|
|
3287
|
+
if not cands:
|
|
3123
3288
|
return {"error": "no_dsh_session_found"}
|
|
3124
|
-
|
|
3289
|
+
picked = cands[0]
|
|
3290
|
+
src = DSHSessionSource(picked[0])
|
|
3125
3291
|
else:
|
|
3126
3292
|
src = _pick_source(src_arg)
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3293
|
+
res = ing.ingest(src,
|
|
3294
|
+
mine_fix_pairs=bool(a.get("mine_fix_pairs", False)),
|
|
3295
|
+
max_events=a.get("max_events"),
|
|
3296
|
+
dry_run=bool(a.get("dry_run")))
|
|
3297
|
+
if picked is not None:
|
|
3298
|
+
res["selection"] = {
|
|
3299
|
+
"policy": "max_size",
|
|
3300
|
+
"selected": picked[0],
|
|
3301
|
+
"selected_size": picked[1],
|
|
3302
|
+
"selected_mtime": picked[2],
|
|
3303
|
+
"candidate_count": len(cands),
|
|
3304
|
+
"candidates": [{"path": p, "size": s, "mtime": m}
|
|
3305
|
+
for p, s, m in cands[:5]],
|
|
3306
|
+
"hint": ("auto 按会话**文件体积**降序选取(**不是**按最近活动),"
|
|
3307
|
+
"故可能选中很久以前的会话;如需指定会话请显式传 "
|
|
3308
|
+
"source=<会话文件路径>,或先看 selected_mtime / "
|
|
3309
|
+
"candidates[].mtime 判断新鲜度。"),
|
|
3310
|
+
}
|
|
3311
|
+
return res
|
|
3131
3312
|
|
|
3132
3313
|
if name == "mdcg_watermarks":
|
|
3133
3314
|
from .sources import Ingestor
|
|
@@ -3224,6 +3405,37 @@ def _normalize_session(raw):
|
|
|
3224
3405
|
return "anonymous"
|
|
3225
3406
|
|
|
3226
3407
|
|
|
3408
|
+
# 生效条件:raw=str(raw or "").strip();raw 为空或恰为 "*" 时返回 None(不构成归因声明);部署侧 MDCG_SESSION 或 DSH_SESSION_ID 去空白后非空时返回 None(环境权威,请求声明被否决);否则返回 _normalize_session(raw)。
|
|
3409
|
+
def _declared_session(raw):
|
|
3410
|
+
"""**请求级会话归属声明**(归因维度,与授权正交)。
|
|
3411
|
+
|
|
3412
|
+
「记忆写入必须带会话身份」是既定设计,但身份来源要分场景:
|
|
3413
|
+
|
|
3414
|
+
· 部署侧能把会话固定在**连接**上(每会话一条 MCP 连接,或进程 env 里给了
|
|
3415
|
+
`MDCG_SESSION`)→ 环境即权威,请求里的声明一律忽略,客户端不得改写归属:
|
|
3416
|
+
这正是 `MdCGSecure._attribution` 注释里「MCP 面不透传该入参——客户端不得
|
|
3417
|
+
伪造归属」要守的纪律;
|
|
3418
|
+
· 单进程多会话的载体(如 DSH web 一个 MCP 进程服务多个前端会话)没法把会话
|
|
3419
|
+
写进进程 env,此时才允许调用方在请求里声明,**且必须过 `_normalize_session`
|
|
3420
|
+
的防编造校验**(DSH 形态须真存在,否则降级 anonymous),不是照单全收。
|
|
3421
|
+
|
|
3422
|
+
优先级(高 → 低):env(MDCG_SESSION / DSH_SESSION_ID)> 请求声明 > 进程身份。
|
|
3423
|
+
|
|
3424
|
+
与 `as_unit` 的分工:`as_unit` 收窄**授权**(求交,只能变小,见 `call_tool`);
|
|
3425
|
+
本项只改**归因**、不动任何 ops 裁决——即使声明被伪造,最坏后果是「记忆贴错
|
|
3426
|
+
会话标签」,拿不到任何额外权限;而归因里的 `writer` 恒为令牌 actor,请求面
|
|
3427
|
+
改不了「真正谁写的」。`"*"` 是**读取**侧的跨会话视图语法(见 `stg.timeline`),
|
|
3428
|
+
不是会话名,故在此一律返回 None。
|
|
3429
|
+
"""
|
|
3430
|
+
s = str(raw or "").strip()
|
|
3431
|
+
if not s or s == "*":
|
|
3432
|
+
return None
|
|
3433
|
+
if (os.environ.get("MDCG_SESSION")
|
|
3434
|
+
or os.environ.get("DSH_SESSION_ID") or "").strip():
|
|
3435
|
+
return None # 环境已固定会话:客户端不得改写归属
|
|
3436
|
+
return _normalize_session(s)
|
|
3437
|
+
|
|
3438
|
+
|
|
3227
3439
|
# 生效条件:环境变量 MDCG_SESSION(优先)或 DSH_SESSION_ID 去空白后非空时把 p.session 设为 _normalize_session(raw),MDCG_HARNESS 去空白后非空时把 p.harness 设为该值,MDCG_UNIT 去空白后非空时把 p.unit 设为该值,三者均为空串或未设置时 p 的对应字段保持原值;
|
|
3228
3440
|
def _apply_attribution(p):
|
|
3229
3441
|
"""归因维度注入(嵌套身份:(harness, session)),**不参与授权**。
|
|
@@ -3245,7 +3457,7 @@ def _apply_attribution(p):
|
|
|
3245
3457
|
p.unit = unit
|
|
3246
3458
|
|
|
3247
3459
|
|
|
3248
|
-
# 生效条件:环境变量 MDCG_TOKEN 去空白后非空时经 verify_token(token, tenant=os.environ.get("MDCG_TENANT")) 构造——抛 TokenError 则返回 (None, f"令牌校验失败:{e}"),成功则返回 (_attach_theory(p), None);否则 MDCG_LEGACY_ENV_AUTH 值为 "1"/"true"/"True" 时按 MDCG_CAN_ADMIN/MDCG_CAN_WRITE
|
|
3460
|
+
# 生效条件:环境变量 MDCG_TOKEN 去空白后非空时经 verify_token(token, tenant=os.environ.get("MDCG_TENANT")) 构造——抛 TokenError 则返回 (None, f"令牌校验失败:{e}"),成功则返回 (_attach_theory(p), None);否则 MDCG_LEGACY_ENV_AUTH 值为 "1"/"true"/"True" 时按 MDCG_CAN_ADMIN/MDCG_CAN_WRITE 落角色(P1-5 批次 26:admin 需 MDCG_CAN_ADMIN 与 MDCG_LEGACY_ENV_ADMIN 同时为真,只设前者时降级 recorder 并写 stderr 提示),两者都不满足时构造 can_write=False、can_admin=False、auth_mode="anonymous" 的 guest 身份,后两条路径同样返回 (_attach_theory(p), None);
|
|
3249
3461
|
def _build_principal():
|
|
3250
3462
|
"""构造 Principal(令牌优先,fail-closed)。返回 (principal, error)。
|
|
3251
3463
|
|
|
@@ -3267,11 +3479,33 @@ def _build_principal():
|
|
|
3267
3479
|
p = verify_token(token, tenant=os.environ.get("MDCG_TENANT"))
|
|
3268
3480
|
except TokenError as e:
|
|
3269
3481
|
return None, f"令牌校验失败:{e}"
|
|
3482
|
+
# 密级口径冲突必须开口(2026-09-24 修复):令牌优先时 MDCG_CLEARANCE
|
|
3483
|
+
# **完全不参与**(令牌里冻结的 clearance 说了算),而插件侧
|
|
3484
|
+
# config.mdcg.clearance 默认 'private'——配置写 private、实际 internal
|
|
3485
|
+
# 会让 private/secret 节点静默读不到(本机实测:readable=[public,internal])。
|
|
3486
|
+
_want = (os.environ.get("MDCG_CLEARANCE") or "").strip()
|
|
3487
|
+
if _want and _want != (p.clearance or ""):
|
|
3488
|
+
sys.stderr.write(
|
|
3489
|
+
f"[mdcg-mcp] ⚠ 密级配置被令牌覆盖:MDCG_CLEARANCE={_want} 但令牌"
|
|
3490
|
+
f" clearance={p.clearance}(令牌优先,实际可读密级以令牌为准)。"
|
|
3491
|
+
f"要让配置生效:用 --clearance {_want} 重新签发令牌,"
|
|
3492
|
+
f"或删除 MDCG_TOKEN 走 legacy/env 身份。\n")
|
|
3270
3493
|
_apply_attribution(p)
|
|
3271
3494
|
return _attach_theory(p), None
|
|
3272
3495
|
|
|
3273
3496
|
if os.environ.get("MDCG_LEGACY_ENV_AUTH", "0") in ("1", "true", "True"):
|
|
3274
|
-
|
|
3497
|
+
# P1-5(批次 26,外部审查报告):legacy env 直连身份不再能给 admin——
|
|
3498
|
+
# 「环境变量可达即 designer/can_admin」= 配置即提权后门。保留兼容但
|
|
3499
|
+
# admin 需**显式二次开关** MDCG_LEGACY_ENV_ADMIN=1;只设 MDCG_CAN_ADMIN
|
|
3500
|
+
# 时降级 recorder 并 stderr 提示(不静默)。
|
|
3501
|
+
_want_admin = os.environ.get("MDCG_CAN_ADMIN", "0") in ("1", "true", "True")
|
|
3502
|
+
can_admin = _want_admin and os.environ.get(
|
|
3503
|
+
"MDCG_LEGACY_ENV_ADMIN", "0") in ("1", "true", "True")
|
|
3504
|
+
if _want_admin and not can_admin:
|
|
3505
|
+
sys.stderr.write(
|
|
3506
|
+
"[mdcg-mcp] ⚠ MDCG_CAN_ADMIN=1 在 legacy env 身份下已不生效:"
|
|
3507
|
+
"管理员需要二次开关 MDCG_LEGACY_ENV_ADMIN=1(P1-5 收紧,防 env "
|
|
3508
|
+
"注入自授 admin)。当前降级为 recorder。\n")
|
|
3275
3509
|
can_write = os.environ.get("MDCG_CAN_WRITE", "1") not in ("0", "false", "False")
|
|
3276
3510
|
role = "designer" if can_admin else ("recorder" if can_write else "output")
|
|
3277
3511
|
spec = role_spec(role)
|
|
@@ -3310,8 +3544,96 @@ def _attach_theory(p):
|
|
|
3310
3544
|
|
|
3311
3545
|
|
|
3312
3546
|
# 生效条件:环境变量 MDCG_ROOT 非空且其 os.path.abspath 规范化后的 basename 小写不以 "_md_cg_" 开头、且 _build_principal() 返回的 err 为空时,构造 MdCGSecure(root, principal=principal, autoflush=1) 并对 sys.stdin 逐行 method 分派(initialize 回 protocolVersion=PROTOCOL_VERSION 与 SERVER_NAME/SERVER_VERSION,tools/list 回 tools_for_surface(),tools/call 经 call_tool 后回 content,shutdown 跳出循环),遍历结束后调用 sustain.stop_all() 与 cg.close() 并返回 0;MDCG_ROOT 为空或 basename 命中 "_md_cg_" 前缀返回 2,令牌校验失败返回 3;
|
|
3547
|
+
# 生效条件:env 缺省取 os.environ;返回 (root, err)——MDCG_TENANT 已登记(登记表路径可经 MDCG_TENANT_REGISTRY 覆盖,缺省 ~/.mdcg/_tenants.json)时 root=登记根,与显式 MDCG_ROOT 冲突返回 (None, 冲突说明);未登记租户回落 MDCG_ROOT;两者皆空返回 (None, None);登记表损坏/不可读(TenantRegistry.load_error 留痕或读取抛异常,N124 2026-09-25)时向 stderr 写「登记根绑定失效回落 MDCG_ROOT」告警后按未登记同形回落(零闸变,只开口)。
|
|
3548
|
+
def _resolve_root(env=None):
|
|
3549
|
+
"""租户 × 认知图根解析(issue #35 接线,独立函数供守卫测试)。
|
|
3550
|
+
|
|
3551
|
+
口径:MDCG_TENANT 已登记 → 登记根;与显式 MDCG_ROOT 不一致 → 冲突
|
|
3552
|
+
(fail-closed,由调用方拒启);未登记租户 → 维持 MDCG_ROOT(零变更)。
|
|
3553
|
+
登记表损坏/不可读 → 同未登记回落,但必须开口(N124):静默回落会让
|
|
3554
|
+
租户根物理隔离绑定无声消失、写入落进公共根,且下方冲突 fail-closed
|
|
3555
|
+
检测连带失效。
|
|
3556
|
+
"""
|
|
3557
|
+
env = env if env is not None else os.environ
|
|
3558
|
+
root = env.get("MDCG_ROOT")
|
|
3559
|
+
tenant = env.get("MDCG_TENANT")
|
|
3560
|
+
if tenant:
|
|
3561
|
+
t_root = None
|
|
3562
|
+
reg_err = ""
|
|
3563
|
+
try:
|
|
3564
|
+
from .security import TenantRegistry
|
|
3565
|
+
reg = TenantRegistry(env.get("MDCG_TENANT_REGISTRY") or None)
|
|
3566
|
+
t_root = reg.root_of(tenant)
|
|
3567
|
+
reg_err = getattr(reg, "load_error", "") or ""
|
|
3568
|
+
except Exception as e: # noqa: BLE001
|
|
3569
|
+
reg_err = f"{type(e).__name__}: {e}"
|
|
3570
|
+
t_root = None
|
|
3571
|
+
if reg_err:
|
|
3572
|
+
# N124(2026-09-25 止血):登记表损坏/不可读时隔离绑定无声消失,
|
|
3573
|
+
# 对照 MDCG_CLEARANCE 覆盖告警同款口径——零闸变、只开口。
|
|
3574
|
+
sys.stderr.write(
|
|
3575
|
+
f"[mdcg-mcp] ⚠ 租户登记表损坏/不可读({reg_err}):"
|
|
3576
|
+
f"MDCG_TENANT={tenant} 的登记根绑定失效,本次回落 "
|
|
3577
|
+
f"MDCG_ROOT={root or '(未设)'};请修复登记表"
|
|
3578
|
+
f"(MDCG_TENANT_REGISTRY,缺省 ~/.mdcg/_tenants.json)。\n")
|
|
3579
|
+
if t_root:
|
|
3580
|
+
if root and os.path.abspath(root) != os.path.abspath(t_root):
|
|
3581
|
+
return None, (f"MDCG_TENANT={tenant} 已登记根 {t_root},"
|
|
3582
|
+
f"与显式 MDCG_ROOT={root} 不一致(fail-closed)")
|
|
3583
|
+
root = t_root
|
|
3584
|
+
return root, None
|
|
3585
|
+
|
|
3586
|
+
|
|
3587
|
+
# 生效条件:sys.stdin/stdout/stderr 三个流逐个 reconfigure(encoding="utf-8", errors="replace"),
|
|
3588
|
+
# 流不支持 reconfigure(AttributeError,如被替换为非 TextIO 对象)或取值非法(ValueError)时静默跳过该流,无返回值。
|
|
3589
|
+
def _force_utf8_stdio():
|
|
3590
|
+
"""进程内强制 stdio 三流 = UTF-8(issue #39 纵深防线)。
|
|
3591
|
+
|
|
3592
|
+
MCP 协议是 UTF-8 JSON,但 Windows 控制台默认代码页(如 CP936/GBK)会让
|
|
3593
|
+
stdio 管道跟随 locale——宿主按 UTF-8 发来的中文参数被按 GBK 解码:strict
|
|
3594
|
+
下读侧直接 UnicodeDecodeError,surrogateescape 下解出代理对(\\udcXX),
|
|
3595
|
+
``_j()``(ensure_ascii=False)按 UTF-8 编码时即抛 ``UnicodeEncodeError:
|
|
3596
|
+
surrogates not allowed``,整条请求失败(写英文正常,故用户难自查)。
|
|
3597
|
+
桥层已在 ``src/lib/mdcg_client.ts`` 的 ``mdcgChildEnv()`` 注入
|
|
3598
|
+
``PYTHONUTF8=1``,但只覆盖 DSH 桥路径——Claude Code / code CLI 直接
|
|
3599
|
+
mcp.json 接入不经桥,仍踩(issue #39)。进程内 reconfigure 是对桥层
|
|
3600
|
+
防线的纵深补位;``errors="replace"`` 保证坏字节最多丢字符、不炸整条请求。
|
|
3601
|
+
必须在 main() 首行调用:早于一切 stderr 中文写与 stdin 读取。
|
|
3602
|
+
"""
|
|
3603
|
+
for stream in (sys.stdin, sys.stdout, sys.stderr):
|
|
3604
|
+
try:
|
|
3605
|
+
stream.reconfigure(encoding="utf-8", errors="replace")
|
|
3606
|
+
except (AttributeError, ValueError):
|
|
3607
|
+
pass
|
|
3608
|
+
|
|
3609
|
+
|
|
3610
|
+
# 生效条件:_force_utf8_stdio() 先执行(stdio 三流强制 UTF-8,issue #39);随后对 mdcg_root()/aux_root() 各探一次,抛 ValueError(Windows 保留设备名末段被 GetFullPathNameW 吞成设备路径,datapath._abs_host_path 守卫)时向 stderr 写一行含原始消息的告警并返回 2;此后 _resolve_root() 返回 err 非空时向 stderr 写冲突说明并返回 2;root 为空写缺少 MDCG_ROOT 并返回 2;root 的 basename 小写以 _md_cg_ 开头返回 2,令牌校验失败返回 3;其余构造 MdCGSecure 并进入 stdin 分派循环。
|
|
3313
3611
|
def main():
|
|
3314
|
-
|
|
3612
|
+
_force_utf8_stdio()
|
|
3613
|
+
# 启动早期承接受理(Windows 保留设备名守卫):MDCG_ROOT/MDCG_AUX_ROOT/
|
|
3614
|
+
# MDCG_DATA_ROOT 等覆盖值末段若是保留设备名(aux/con/nul/com1-9/lpt1-9…),
|
|
3615
|
+
# ntpath.abspath 经 GetFullPathNameW 会把整个路径吞成设备命名空间形态
|
|
3616
|
+
# (例 D:\sandbox\aux → \\.\aux),datapath._abs_host_path 即抛 ValueError。
|
|
3617
|
+
# 此处先探一次 root/aux 解析,命中即拒绝启动(对照下方 `_md_cg_` 前缀守卫
|
|
3618
|
+
# 先例「启动即拒绝,不带病运行」)——否则首个 aux 常量面(crypto/links/
|
|
3619
|
+
# signer/theory/tokens/evidence 的模块级 aux_root())会在下方 import 处
|
|
3620
|
+
# 裸崩 traceback,密钥/令牌/信任面被指到不存在的设备路径。
|
|
3621
|
+
try:
|
|
3622
|
+
from .datapath import mdcg_root as _probe_root
|
|
3623
|
+
from .datapath import aux_root as _probe_aux
|
|
3624
|
+
_probe_root()
|
|
3625
|
+
_probe_aux()
|
|
3626
|
+
except ValueError as _ve:
|
|
3627
|
+
sys.stderr.write(f"[mdcg-mcp] {_ve}\n"
|
|
3628
|
+
"[mdcg-mcp] 拒绝启动(fail-closed):请把上述覆盖键"
|
|
3629
|
+
"改指向末段不含保留设备名的普通目录。\n")
|
|
3630
|
+
return 2
|
|
3631
|
+
root, _terr = _resolve_root()
|
|
3632
|
+
if _terr:
|
|
3633
|
+
sys.stderr.write(f"[mdcg-mcp] 租户根冲突:{_terr}。"
|
|
3634
|
+
"请二选一:清空 MDCG_ROOT 走租户登记根,或从登记表"
|
|
3635
|
+
"(~/.mdcg/_tenants.json)移除该租户。\n")
|
|
3636
|
+
return 2
|
|
3315
3637
|
if not root:
|
|
3316
3638
|
sys.stderr.write("[mdcg-mcp] 缺少 MDCG_ROOT 环境变量\n")
|
|
3317
3639
|
return 2
|
|
@@ -3347,6 +3669,15 @@ def main():
|
|
|
3347
3669
|
except Exception as _mig_exc: # 迁移故障不得影响服务可用性
|
|
3348
3670
|
sys.stderr.write("[mdcg-mcp] 数据面迁移检查失败(不阻塞启动): %r\n"
|
|
3349
3671
|
% (_mig_exc,))
|
|
3672
|
+
# 两个根一并留痕(2026-09-24):记忆真源与「身份/凭据根」**有意分离**
|
|
3673
|
+
# (身份不随认知图迁移),但分居两处必须可见——历史事故多为「以为在一处」。
|
|
3674
|
+
try:
|
|
3675
|
+
from .datapath import aux_root as _aux_root
|
|
3676
|
+
sys.stderr.write(
|
|
3677
|
+
"[mdcg-mcp] 路径:记忆真源 root=%s · 身份/凭据根 aux=%s"
|
|
3678
|
+
"(aux 可用 MDCG_AUX_ROOT 覆盖)\n" % (root, _aux_root()))
|
|
3679
|
+
except Exception: # 仅日志:任何失败都不影响启动
|
|
3680
|
+
pass
|
|
3350
3681
|
principal, err = _build_principal()
|
|
3351
3682
|
if err:
|
|
3352
3683
|
sys.stderr.write(
|
|
@@ -3392,6 +3723,17 @@ def main():
|
|
|
3392
3723
|
except Exception as _exc: # 对账故障不得影响服务可用性
|
|
3393
3724
|
sys.stderr.write("[mdcg-mcp] 两段式对账失败(不阻塞启动): %r\n"
|
|
3394
3725
|
% (_exc,))
|
|
3726
|
+
# ③' 启动对账 reconcile v0(v0.3 T9 自稳定定理落地,落地清单 P0-3):两段式
|
|
3727
|
+
# 清账只覆盖「有意图无结果的写入」,这里补全量 diff——索引(派生态)vs 盘面
|
|
3728
|
+
# 真源:多/缺索引条目与内容哈希漂移三类,以盘面为真源**增量**修复索引面;
|
|
3729
|
+
# 真源自身损坏只告警留痕不自动改写(T9 边界:结构合法≠内容正确)。告警与
|
|
3730
|
+
# 留痕由模块发声(diff 非空才输出,干净库零噪声);MDCG_RECONCILE=0 关闭
|
|
3731
|
+
# (缺省开,开关真源 reconcile.enabled)。失败不阻塞启动,与③同风格。
|
|
3732
|
+
try:
|
|
3733
|
+
cg.reconcile_state()
|
|
3734
|
+
except Exception as _exc: # 对账故障不得影响服务可用性
|
|
3735
|
+
sys.stderr.write("[mdcg-mcp] 启动对账 v0 失败(不阻塞启动): %r\n"
|
|
3736
|
+
% (_exc,))
|
|
3395
3737
|
# 进程自报(诊断设施,fail-safe):把「md_cg 实际加载源 + render 契约代际」
|
|
3396
3738
|
# 落成 `<tempdir>/md_cg_servers/<pid>.json`,供 `scripts/mdcg_stale_servers.py`
|
|
3397
3739
|
# 机械判定**活进程代际**。根因(第4条取证):原先只能比「进程启动时间 vs
|
|
@@ -3445,8 +3787,14 @@ def main():
|
|
|
3445
3787
|
_reply(rid, {"content": [{"type": "text", "text": _j(out)}],
|
|
3446
3788
|
"isError": False})
|
|
3447
3789
|
except Exception as exc: # noqa: BLE001 —— 工具错误以 MCP 结果返回
|
|
3790
|
+
# issue #34:失败路径必须带「怎么办」——AccessDenied 的 hint
|
|
3791
|
+
# (guest 配凭据 / 令牌补授权 / 过期重签)随结构化错误透出。
|
|
3792
|
+
err = {"error": f"{type(exc).__name__}: {exc}"}
|
|
3793
|
+
_hint = getattr(exc, "hint", None)
|
|
3794
|
+
if _hint:
|
|
3795
|
+
err["hint"] = _hint
|
|
3448
3796
|
_reply(rid, {"content": [{"type": "text",
|
|
3449
|
-
"text": _j(
|
|
3797
|
+
"text": _j(err)}],
|
|
3450
3798
|
"isError": True})
|
|
3451
3799
|
elif method == "shutdown":
|
|
3452
3800
|
_reply(rid, {})
|