@furongjun1999/dsh-memory 0.6.0 → 0.7.0
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 +618 -572
- package/codebuddy/CODEBUDDY.md +10 -10
- package/data/policy.json +27 -0
- package/docs/README.md +1 -0
- package/docs/discipline/harnesses.yaml +31 -0
- package/docs/discipline/templates/full.md.tmpl +1 -1
- package/docs/discipline/templates/rules.mdc.tmpl +1 -1
- package/docs/eval/N225_/347/264/242/345/274/225/346/227/245/345/277/227/351/235/236/345/257/271/350/261/241/350/243/205/350/275/275/351/235/242/347/261/273/345/236/213/351/227/270_v1.0.md +418 -0
- package/docs/eval/issue43_/351/273/230/350/256/244/347/255/226/347/225/245/344/270/216/351/224/256/347/261/273/345/236/213/351/227/270_v1.1.md +441 -0
- package/docs/eval/issue43_/351/273/230/350/256/244/347/255/226/347/225/245/345/212/240/350/275/275/344/270/216/345/207/255/346/215/256/346/230/216/346/226/207/351/230/237/345/210/227_v1.0.md +398 -0
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/270/200/346/211/271_/346/216/245/347/272/277/344/270/216/347/255/211/344/273/267/345/217/230/346/215/242_v1.0.md +498 -0
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/270/211/346/211/271_/351/227/250/347/246/201/350/275/254/346/255/243/344/270/216/350/260/203/345/272/246/346/255/242/350/241/200/344/270/216/351/227/250/346/216/247/346/224/266/345/217/243_v1.0.md +669 -0
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/272/214/346/211/271_/344/276/235/350/265/226/351/200/217/344/274/240/344/270/216/345/257/271/346/213/215/345/217/243/345/276/204/344/270/216/350/264/237/347/274/223/345/255/230_v1.0.md +683 -0
- package/docs/eval//345/207/272/350/264/247/351/235/242/345/206/222/347/203/237_/350/277/233/350/264/247/351/227/250/347/246/201_v1.0.md +460 -0
- package/docs/eval//345/217/221/345/270/20307_/345/244/226/351/203/250/346/212/245/345/221/212/345/233/233/346/211/271/344/277/256/345/244/215/344/270/216/346/217/222/344/273/266/351/235/242/345/212/240/345/233/272_v1.0.md +205 -0
- package/docs/eval//345/217/221/345/270/20308_/350/207/252/350/277/255/344/273/243/344/270/216/347/235/241/347/234/240_/345/233/276/346/243/200/347/264/242/350/267/257/344/270/216/346/235/203/351/207/215_v1.0.md +97 -0
- package/docs/eval//345/275/222/344/270/200/345/261/202/347/274/272/347/234/201/347/277/273/345/205/263_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +458 -0
- package/docs/eval//346/200/247/350/203/275/344/270/223/351/241/271_/345/206/267/346/237/245/350/257/242/344/270/216/345/206/205/345/255/230_v1.0.md +218 -0
- package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md +10 -0
- package/docs/eval//347/274/226/347/240/201/351/235/242/345/211/215/347/275/256_/345/205/245/345/217/243/350/207/252/344/277/235/350/257/201UTF8/344/270/216/346/226/207/346/234/254open/345/256/210/345/215/253_v1.0.md +646 -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_v20.md +283 -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_v21.md +224 -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_v22.md +223 -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_v23.md +293 -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_v24.md +303 -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_v25.md +230 -0
- 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 +136 -11
- 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 +52 -2
- 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 +1 -1
- package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +100 -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 +40 -40
- package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +57 -9
- 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 +7 -2
- package/docs/mdcg//347/235/241/347/234/240/345/221/250/346/234/237_/350/277/220/347/273/264/345/211/215/346/217/220/344/270/216/347/273/264/346/212/244/346/214/207/345/215/227_v1.0.md +183 -0
- 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 +39 -3
- package/docs/plans//345/205/250/344/270/255/346/226/207/347/274/226/347/240/201/344/270/216/350/234/202/345/267/242/344/273/273/345/212/241/346/240/207/350/257/206/345/245/221/347/272/246_v2.0.md +220 -0
- package/docs/plans//347/234/237/346/272/220/347/264/242/345/274/225_/351/200/232/347/224/250/346/234/272/345/210/266_v0.3.md +227 -0
- package/docs/plans//347/235/241/347/234/240/344/270/216/350/207/252/350/277/255/344/273/243_/345/212/237/350/203/275/344/274/230/345/214/226/350/256/276/350/256/241_v0.4.md +547 -0
- package/docs/plans//350/234/202/345/267/242/346/250/241/345/236/213/345/257/206/351/222/245/351/205/215/347/275/256/351/235/242_v1.0.md +385 -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 +460 -460
- package/lib/bridge.js +24 -2
- package/lib/hooks.d.ts +31 -2
- package/lib/hooks.js +219 -16
- package/lib/init.js +16 -1
- package/lib/lib/prompt_safety.d.ts +52 -1
- package/lib/lib/prompt_safety.js +76 -1
- package/md_cg/audit.py +652 -379
- package/md_cg/bench6_arms.py +1 -1
- package/md_cg/bench_e2e_locomo_qa.py +11 -4
- package/md_cg/bench_p0.py +1 -1
- package/md_cg/branches.py +2 -2
- package/md_cg/ccgc.py +1071 -1006
- package/md_cg/chain.py +48 -1
- package/md_cg/consistency.py +97 -9
- package/md_cg/consolidate.py +34 -9
- package/md_cg/crypto.py +59 -26
- package/md_cg/docindex.py +16 -1
- package/md_cg/evolution.py +17 -1
- package/md_cg/export.py +1 -1
- package/md_cg/forgetting.py +309 -13
- package/md_cg/freshness.py +511 -0
- package/md_cg/fsutil.py +454 -8
- package/md_cg/generation.py +409 -0
- package/md_cg/hotcache.py +4 -1
- package/md_cg/identity.py +3 -3
- package/md_cg/insight.py +24 -3
- package/md_cg/linkref.py +1 -1
- package/md_cg/logref.py +327 -0
- package/md_cg/mcp_server.py +4261 -3818
- package/md_cg/mdcg.py +4695 -3547
- package/md_cg/mdcos.py +4672 -4159
- package/md_cg/mreview/pipeline.py +15 -1
- package/md_cg/nodefile.py +713 -576
- package/md_cg/protect.py +158 -11
- package/md_cg/protocol.py +41 -2
- package/md_cg/provenance.py +22 -4
- package/md_cg/reach.py +4 -4
- package/md_cg/readcache.py +76 -15
- package/md_cg/reconcile.py +1 -1
- package/md_cg/refindex.py +246 -37
- package/md_cg/refine.py +1 -1
- package/md_cg/routing.py +32 -5
- package/md_cg/run_tests.py +17 -0
- package/md_cg/scrub.py +30 -3
- package/md_cg/security.py +47 -1
- package/md_cg/self_state.py +5 -5
- package/md_cg/semantic/canonical.py +22 -0
- package/md_cg/semantic/unify.py +73 -22
- package/md_cg/semantic/unify_fixture.json +25 -0
- package/md_cg/sleep.py +1297 -0
- package/md_cg/sources.py +23 -6
- package/md_cg/srcindex.py +352 -0
- package/md_cg/stg.py +47 -3
- package/md_cg/subgraph.py +2 -2
- package/md_cg/sustain.py +1436 -1168
- package/md_cg/tasks.py +469 -470
- package/md_cg/test_auto_defaults.py +424 -0
- package/md_cg/test_b1_auto_id_multiproc.py +277 -0
- package/md_cg/test_b1b2_write_face.py +417 -0
- package/md_cg/test_b2_sensitivity_landing.py +223 -0
- package/md_cg/test_b3_merge_keeps_content.py +576 -0
- package/md_cg/test_b4_shard_dir_selfheal.py +843 -0
- package/md_cg/test_b4_shard_dir_selfheal_guard.py +238 -0
- package/md_cg/test_boundary_hit.py +410 -0
- package/md_cg/test_c3_transient_read_negative.py +793 -0
- package/md_cg/test_c8_search_rrf_gates.py +502 -0
- package/md_cg/test_ccg_form_parity.py +188 -0
- package/md_cg/test_ccgc.py +28 -3
- package/md_cg/test_en_pipeline.py +22 -13
- package/md_cg/test_generation_guard.py +352 -0
- package/md_cg/test_govern_directread.py +17 -4
- package/md_cg/test_h2_session_view_norm.py +233 -0
- package/md_cg/test_h4_sustain_snapshot.py +1387 -0
- package/md_cg/test_hive_ingest.py +285 -285
- package/md_cg/test_issue39_utf8_stdio.py +307 -16
- package/md_cg/test_issue43_default_policy.py +865 -0
- package/md_cg/test_legacy_p3_node_id_type.py +375 -0
- package/md_cg/test_linkref.py +10 -3
- package/md_cg/test_lock.py +2 -2
- package/md_cg/test_logref.py +1109 -0
- package/md_cg/test_m3_h9_bucket_health_protect_mark.py +301 -0
- package/md_cg/test_m3_h9_semantic_guard.py +525 -0
- package/md_cg/test_mr_m2.py +15 -3
- package/md_cg/test_n130_verify_falsified_protect.py +1 -1
- package/md_cg/test_n139_dek_provision_failclosed.py +185 -0
- package/md_cg/test_n176_link_trust.py +221 -0
- package/md_cg/test_n178_units_jobid_gate.py +212 -0
- package/md_cg/test_n184_keys_concurrent_provision.py +307 -0
- package/md_cg/test_n195_writepath_reload.py +283 -0
- package/md_cg/test_n196_stale_gate_skip.py +169 -0
- package/md_cg/test_n197_n208_write_face_gates.py +471 -0
- package/md_cg/test_n198_tokens_corrupt_failclosed.py +225 -0
- package/md_cg/test_n199_tokens_concurrent_write.py +378 -0
- package/md_cg/test_n201_proposal_visibility.py +382 -0
- package/md_cg/test_n202_session_notes_visibility.py +461 -0
- package/md_cg/test_n204_n205_n226_n227_n228_n229_exit_gates.py +542 -0
- package/md_cg/test_n206_stdio_jsonrpc_type.py +403 -0
- package/md_cg/test_n209_verify_write_face_gates.py +461 -0
- package/md_cg/test_n212_n213_n224_generation_gates.py +519 -0
- package/md_cg/test_n214_n215_n221_n222_write_face_gates.py +563 -0
- package/md_cg/test_n225_nonobject_load.py +1110 -0
- package/md_cg/test_n230_dirty_replay.py +375 -0
- package/md_cg/test_n62_tenant_bind_failclosed.py +200 -0
- package/md_cg/test_neg_condition_hits.py +333 -0
- package/md_cg/test_neg_tail_honesty.py +663 -0
- package/md_cg/test_none_id_write_guard.py +4 -3
- package/md_cg/test_opt_batch1_md_cg.py +451 -0
- package/md_cg/test_p1.py +5 -5
- package/md_cg/test_p11_consistency.py +161 -12
- package/md_cg/test_p26_refindex.py +2 -2
- package/md_cg/test_p27_docindex.py +777 -774
- package/md_cg/test_p28_refcheck.py +740 -13
- package/md_cg/test_p29_session_ingest_export.py +2 -2
- package/md_cg/test_p2_mcp.py +12 -1
- package/md_cg/test_p2_six_elements.py +463 -0
- package/md_cg/test_p30_maintain.py +33 -2
- package/md_cg/test_p31_insight.py +1 -0
- package/md_cg/test_p3_legacy_closure.py +433 -0
- package/md_cg/test_p4_freshness.py +680 -0
- package/md_cg/test_p8_subgraph_chain.py +14 -1
- package/md_cg/test_p9c_dedup_hints.py +276 -0
- package/md_cg/test_policy_required_ccg.py +426 -0
- package/md_cg/test_protocol.py +22 -0
- package/md_cg/test_rank_parity_score_mode.py +522 -0
- package/md_cg/test_read_face_input_gates.py +363 -0
- package/md_cg/test_read_face_semantics.py +489 -0
- package/md_cg/test_recall_face_guards.py +812 -0
- package/md_cg/test_rejected_credential_forms.py +188 -0
- package/md_cg/test_rejected_redact.py +146 -0
- package/md_cg/test_retr_s1b.py +2 -2
- package/md_cg/test_retr_s5.py +20 -7
- package/md_cg/test_review_conformance.py +21 -3
- package/md_cg/test_security_audit_v21.py +2 -2
- package/md_cg/test_semantic_canonical.py +5 -3
- package/md_cg/test_server_version.py +67 -0
- package/md_cg/test_sleep.py +611 -0
- package/md_cg/test_sleep_p1.py +784 -0
- package/md_cg/test_srcindex.py +171 -0
- package/md_cg/test_tenant_env_override_warn.py +63 -50
- package/md_cg/test_time_core_lint.py +968 -0
- package/md_cg/test_token_lowercase_form.py +315 -0
- package/md_cg/test_unify_default_off.py +701 -0
- package/md_cg/test_unify_scope.py +182 -0
- package/md_cg/test_v21r1_package_version.py +310 -0
- package/md_cg/test_writepipe.py +10 -4
- package/md_cg/tokens.py +225 -95
- package/md_cg/tool_face.py +4 -4
- package/md_cg/trust.py +49 -5
- package/md_cg/units.py +204 -6
- package/md_cg/weights.py +4 -4
- package/md_cg/whitebox_kb/aeis_core/time_core.py +8 -0
- package/md_cg/whitebox_kb/wisdom/knowledge_points.py +1 -1
- package/md_cg/writelimit.py +42 -8
- package/md_cg/writepipe.py +651 -554
- package/package.json +4 -2
- package/skills/plugin.json +1 -1
- package/src/bridge.ts +25 -2
- package/src/hooks.ts +229 -16
- package/src/init.ts +15 -1
- package/src/lib/prompt_safety.ts +88 -1
- package/utf8_boot.py +237 -0
- package/zcode/AGENTS.md +10 -10
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# 出货面冒烟腿(PKG-SMOKE-GATE)修复工程报告 v1.0
|
|
2
|
+
|
|
3
|
+
> **修订**:**v1.0-r1**(2026-10-01,按读者反馈逐条处置,处置明细见 **§九**)。
|
|
4
|
+
> **日期**:2026-10-01 | **缺陷号**:PKG-SMOKE-GATE
|
|
5
|
+
> **本文件路径的来处**:由工作流 `args.report` 指定为 `docs/eval/出货面冒烟_进货门禁_v1.0.md`(本报告实读运行脚本确认,见 §4.9-③)。**「进货门禁」是文件名用词**,正文一律称「**出货面冒烟腿**」;该词在本报告中的定义见 §1.0。
|
|
6
|
+
> **契约与判据出处**:动态工作流 `dwfrun-b27a6016-4fb8-4a76-a03a-aad166ef5762` 的 `args.contract`——**原文全文见附录 A**(本报告实读该运行脚本内联 `args` JSON 取得)。
|
|
7
|
+
> **被测面**:`D:\program\dsh-memory-main` **工作树(未提交)**——2 个已修改跟踪件(`package.json`、`scripts/check_publish_artifact.py`)+ 1 个已修改文档(`docs/mdcg/发布门禁链_v0.1.md`)+ 2 个未跟踪新件(`scripts/check_publish_smoke.py`、`scripts/test_publish_smoke_guard.py`)。
|
|
8
|
+
> ⚠ **并发观测(非本报告所为)**:本报告写作期间工作区被**本报告之外**的进程改动过两次(详见 §4.3 注与 §6.4)——`docs/plans/…_v0.1.md` → `…_v0.2.md`,且**本报告文件本身被置为暂存状态(`A`)**;本报告从未执行 `git add`。
|
|
9
|
+
>
|
|
10
|
+
> **证据分级**(本报告不越界陈述):
|
|
11
|
+
> - **§一、§三**=本次读码实读,行号以本次读码为准;**每处同时给 `git HEAD`(修前)与工作树(修后)两个行号**,§一.2、§三.1 各附实跑命令原文。
|
|
12
|
+
> - **§二**=本工作流**采集腿**给出的修前现场(**来源与可信度见 §2.0**,不是 ask#1 记录——该记录本次不可达);本报告直接复核了其中可机械复现的两点并如实标注。
|
|
13
|
+
> - **§四**=凡标「本报告实跑」者均在本次会话实跑并照录命令与读数(并标注是前序 ask 还是本 ask);其余逐条标注为**工作流采集**(非本报告执行)。
|
|
14
|
+
> - **§五**=独立复核(不同执行体)的判定与其自列 uncovered,**转述**并标注本报告能复现到哪一步(含其探针不可定位一事)。
|
|
15
|
+
> - **§六**=边界、未覆盖、本轮明确**不修而留池**的面。**§八**=读者问询逐条回应。**§九**=本次修订的处置明细。
|
|
16
|
+
> - 本报告撰写任务的硬边界:**只写本文件**;不改源码;不 `git add/commit/push`;**未跑**「写活库」类归档(工作纪律第 16 条)——显式声明,非静默跳过;**全文不含任何明文凭据**。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 一、缺陷定义与真实站点
|
|
21
|
+
|
|
22
|
+
### 1.0 术语:本腿与「进货门禁」
|
|
23
|
+
|
|
24
|
+
- **出货面冒烟腿**(本文正文用词):`scripts/check_publish_smoke.py` 这道门禁腿。
|
|
25
|
+
- **进货门禁**(**文件名用词**,仅出现在本文件路径里):本腿守的口径=**出厂件必须真到货**——`files` 白名单声明的必要件必须**出现在 pack 出的 tarball 里**(S1)、**出现在装好的目录里**(S2/S3)、且到货件能**真启动**并给出文档口径的缺省工具面(S4/S5)。「到货」与「进货」同指本腿的落地检查,不指任何采购/入库流程。
|
|
26
|
+
|
|
27
|
+
### 1.1 缺陷
|
|
28
|
+
|
|
29
|
+
发布门禁链(`npm run gate`)**缺一道「出货面」判据**:既有门禁只检查**包内件的内容**(凭据/私有数据/隐私/非追踪件),**不检查某个必要件是否出现在发货清单里**。于是「**仓库里在、包里不在**」这一族缺陷全链无感——修前实测两次同族事故:`#38`(`scripts/` 与 `hive/` 整目录未被 `files` 收录)与 `issue #48`(仓根 `utf8_boot.py` 未被 `files` 收录 ⇒ 0.6.1 **装机即挂**)。#48 的补丁(提交 `52677077`)只把件加回白名单,**没有补上机器检查**——同类再犯仍无人拦(此判断的解除条件见 §八.2,**未完全解除**)。
|
|
30
|
+
|
|
31
|
+
### 1.2 真实站点(两个行号都给)
|
|
32
|
+
|
|
33
|
+
| 站点 | 修前(`git HEAD`) | 修后(工作树) | 说明 |
|
|
34
|
+
|---|---|---|---|
|
|
35
|
+
| 门禁腿链 | `package.json:88`,实读 **8 条腿**(末尾为 `gate_rust_parity.py`) | `package.json:89`,实读 **9 条腿** | 新腿插在 `check_publish_artifact` 之后、`cogmap_sync check` 之前 |
|
|
36
|
+
| 冒烟腿本体 | 不存在(`git cat-file -e HEAD:scripts/check_publish_smoke.py` → **rc=128**) | `scripts/check_publish_smoke.py:1`(新建,470 行) | §一.2 实跑复核 |
|
|
37
|
+
| 冒烟腿守卫 | 不存在(同形 cat-file → **rc=128**) | `scripts/test_publish_smoke_guard.py:1`(新建,433 行) | 同上 |
|
|
38
|
+
| 缺失判据的宿主 | `scripts/check_publish_artifact.py:556` `def local_mode(...)`——判据面仅 R1–R6 | `scripts/check_publish_artifact.py:568` 同函数(**+12 行位移**,因插入 `resolve_npm`) | R1 凭据/R2 私有数据/R3 隐私文本/R4 非追踪件/R5 清单路径/R6 清单来源(`:14`–`:15` 自述)——**六档全无「应有件在否」** |
|
|
39
|
+
| npm 解析方言 | `scripts/check_publish_artifact.py:401` 内联字面量 `npm = "npm.cmd" if os.name == "nt" else "npm"` | `scripts/check_publish_artifact.py:399`–`:409` `resolve_npm()` 单点;`:414` 调用点 | 消除「第二套方言」 |
|
|
40
|
+
| 崩溃点(#48 装机面) | — | `md_cg/mcp_server.py:57` `from utf8_boot import ensure_utf8` | 包内缺件时 ModuleNotFoundError(§二.2 实测) |
|
|
41
|
+
|
|
42
|
+
**实跑取证(本报告,命令与读数照录)**:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
$ python -X utf8 -c "…git show HEAD:package.json 解析 scripts.gate…"
|
|
46
|
+
HEAD package.json gate legs = 8
|
|
47
|
+
1 python scripts/check_unreachable.py
|
|
48
|
+
2 python scripts/check_publish_artifact.py
|
|
49
|
+
3 python scripts/cogmap_sync.py check
|
|
50
|
+
4 python scripts/link_check.py
|
|
51
|
+
5 python scripts/workspace_index.py --check
|
|
52
|
+
6 python scripts/verify_discipline.py --allow-missing
|
|
53
|
+
7 python scripts/gate_rust_crate_test.py
|
|
54
|
+
8 python scripts/gate_rust_parity.py
|
|
55
|
+
files has utf8_boot.py: True
|
|
56
|
+
git cat-file -e HEAD:scripts/check_publish_smoke.py rc = 128
|
|
57
|
+
git cat-file -e HEAD:scripts/test_publish_smoke_guard.py rc = 128
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
⇒ 修前「**有 #48 的补丁、无 #48 的机器检查**」成立:`files` 已含 `utf8_boot.py`(`package.json:23`),但门禁链里没有任何一条腿会检查它是否真出货。
|
|
61
|
+
|
|
62
|
+
### 1.3 定因:为什么八道全漏
|
|
63
|
+
|
|
64
|
+
`scripts/check_publish_artifact.py` 的 `local_mode()`(`HEAD:556` / 工作树 `:568`)判据面是 **R1–R6 六档**——凭据面、私有数据面、隐私文本、非追踪件面、清单路径安全、清单来源可信(`:589`–`:615` 六处 `report.rule`)。这些全是对**已列进清单的件**做内容/来源检查;一个必要件**整体缺席**时,它**没有任何可扫的对象**,照样 `VERDICT=PASS`(`:938`)。**「缺席」不是「命中」,扫描面天然看不见空集**——这就是同类缺陷两漏的结构性根因(不是某条腿写错了)。
|
|
65
|
+
|
|
66
|
+
### 1.4 缺件分两形(本轮新识别)
|
|
67
|
+
|
|
68
|
+
| 形 | 载荷 | 表现 | 隐蔽性 |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| **即挂** | `files` 缺 `utf8_boot.py` | 装机后真启动 rc=1,`ModuleNotFoundError`,握手 `serverInfo=None` | 中(一启就死) |
|
|
71
|
+
| **静默** | `files` 缺 `skills` | 清单条目 **−703**(`/` 前缀 703 件随包消失;§4.9-① 本报告实跑),安装 rc=0、启动 rc=0、握手照常 `['cg','stg']` | **高(零异常、零告警)** |
|
|
72
|
+
|
|
73
|
+
⇒ 后者说明「清单点名」判据必须**独立于**「能不能启动」——只靠真启动会漏掉非启动硬依赖的出货物(本轮新腿的 S1 判据即为此形而设)。
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 二、修前现场(复现腿逐条)
|
|
78
|
+
|
|
79
|
+
### 2.0 来源与可信度(先交代,再列读数)
|
|
80
|
+
|
|
81
|
+
- 本工作流 ask#1「缺陷复现员」的记录**本次不可达**——会话内 `ListWorkflowRuns` 返回 `workflow_introspection_unavailable`(该前置由独立复核声明,本报告沿用)。
|
|
82
|
+
- 因此 **§2.1 表的载荷与读数来源是「本工作流采集腿」**(即本次修订任务上下文所提供的 `修前复现` 数组),**不是 ask#1 的原始记录**。它们是**转述**:本报告能核对其中**可机械复现的部分**(见「本报告复核」列),其余**按转述采信并标注**。
|
|
83
|
+
- 表中每条的 **site** 列可由读者独立复核(`git show HEAD:…`、读码);**数值读数**(1493→1492、rc=3、1.4s、R4 非追踪=28 允许=28…)**本报告未逐条重跑**,凡与本期实跑口径不一致者已就地标注。
|
|
84
|
+
|
|
85
|
+
### 2.1 修前复现腿
|
|
86
|
+
|
|
87
|
+
| # | 腿 | payload(确切命令/输入) | 观察(修前) | 站点 | 来源 / 本报告复核 |
|
|
88
|
+
|---|---|---|---|---|---|
|
|
89
|
+
| 1 | **构造期装载 · 出货面冒烟门禁腿缺失** | 读 `package.json:89` 的 `scripts.gate`;执行 `python -X utf8 scripts/check_publish_smoke.py`(argv 列表 + `shell=False` + cwd=仓根);查 `scripts/` 下名字含 `smoke` 的文件 | gate 串实解 = **8 条腿**(无任何冒烟腿);`scripts/` 下 smoke 文件数 = **0**,`scripts/test_publish_smoke_guard.py` 亦不存在;执行缺失脚本实得 **rc=2**,stderr=`python.exe: can't open file '…\scripts\check_publish_smoke.py': [Errno 2] No such file or directory`(⚠ 该 rc=2 是 **Python 解释器**打不开文件的退出码,**与本腿契约的「2=环境错误」无关**——见 §3.4)。附带核实:`scripts/workspace_index.py:187-188`/`:261-262` 只登记顶层目录(`DIR_ROLES`)与根级文件(`ROOT_FILES`),新增 `scripts/*.py` 无需登记 | `package.json:88`(实为八道)· `scripts/check_publish_smoke.py`(不存在) | 采集腿;**本报告复核成立**(§一.2:HEAD 8 腿 + cat-file rc=128;§4.9-⑤ 复核 workspace_index 登记面) |
|
|
90
|
+
| 2 | **重放面 · 出货面缺件 issue#48 载荷(装机即挂)** | 临时副本 `package.json` 的 `files` 删 `"utf8_boot.py"`(修前 11 项 → 修后 10 项),随后 `npm pack --pack-destination <沙箱>/pack`(cwd=副本)→ 空目录写 `{"name":"pkg-smoke-repro","private":true}` → `npm install <tgz> --no-audit --no-fund --legacy-peer-deps` → 在 `node_modules/@furongjun1999/dsh-memory` 下跑 `python -m md_cg.mcp_server`,stdin 三行(initialize/notifications-initialized/tools-list) | 发货清单条目数 **1493→1492**,`"utf8_boot.py"` 不在清单(False),根级条目只剩 `['LICENSE','README.md','package.json']`;`npm install` rc=0(7.4s)但装好的目录 `utf8_boot.py` 在 = **False**;启动 **rc=1**、0.1s,异常 `ModuleNotFoundError: No module named 'utf8_boot'`,Traceback 定格行 = `md_cg/mcp_server.py:57` 的 `from utf8_boot import ensure_utf8`。对照(未变异)同链路 rc=0、1.4s、`serverInfo={name:mdcg-mcp,version:0.6.1}`、tools=`['cg','stg']` | `package.json:23`(`files` 里的 `"utf8_boot.py"`)· 崩溃点 `md_cg/mcp_server.py:57` | 采集腿;**本报告复核(等价实跑)**:守卫 B2 红侧同形同读数(§4.3,本次实跑) |
|
|
91
|
+
| 3 | **重放面 · 同类第二载荷(静默缺件)** | 同一变异装置,改删 `files` 里的 `"skills"`(条件单元投影随插件分发) | 发货清单条目数 **1493→790**,差 **703** 件随包**静默**消失,`skills/` 前缀命中 **0** 件;但 `npm install` rc=0、启动 rc=0(1.4s)、握手照常 `tools=['cg','stg']`——**skills 非启动硬依赖,缺件不产生任何异常或告警**。⚠ 采集原文写「704 件」——**该数字与本报告实跑不符**(本报告实跑差量 = **703**,见 §4.9-①;且 1493−790 = **703** 亦自洽)⇒「704」应读作采集文本中的孤立误数,**本报告不采信** | `package.json:25`(`files` 里的 `"skills"`) | 采集腿;**本报告复核**:差量 703 由本报告实跑独立复现(§4.9-①) |
|
|
92
|
+
| 4 | **重放面 · 现有八道腿对上述缺件全漏** | 在腿2/腿3 的变异副本(含 `.git`,剔除 `node_modules` 与保留设备名 `nul`)上逐条跑八道腿;并在未变异对照副本上跑串联 `npm run gate`。命令:`python -X utf8 scripts/<leg>`,cwd=副本根 | 变异后八道腿**全部 rc=0**:`check_unreachable` rc=0 / `check_publish_artifact` rc=0 且 `VERDICT=PASS`(R1 文件面=0 内容面=0、R2、R3、R4 非追踪=28 允许=28、R5、R6 全 PASS)/ `cogmap_sync check` rc=0 / `link_check` rc=0(OK=235 BROKEN=0)/ `workspace_index --check` rc=0(顶层 20·追踪 2111)/ `verify_discipline --allow-missing` rc=0(10/10)/ `gate_rust_crate_test` rc=0(cargo 不在位 → SKIP,计入通过数 0)/ `gate_rust_parity` rc=0。对照副本 `npm run gate` rc=0、9.1s(八腿串联全绿)。**根因**:`check_publish_artifact.py` 的 `local_mode` 只做 R1–R6,没有「应有件是否出现在发货清单里」这一类判据 | `scripts/check_publish_artifact.py:556`(`local_mode`,缺「应有件在否」判据——与 §一.3 一致) | 采集腿;**本报告复核(口径一致)**:§一.3 读码确认六档不含「在否」 |
|
|
93
|
+
| 5 | **重放面 · 假红坑(子进程 env 不剔凭据 ⇒ rc=3)** | 与腿2 安装链路同(装好的包 + 三行 JSON-RPC),但子进程 env **保留**调用者实有的 `MDCG_TOKEN`/`MDCG_VERIFY_KEY`/`DEEPSEEK_API_KEY`(哑值,本文不列原文),仅注入 `MDCG_ROOT=<沙箱>/memory_root` 与 `MDCG_AUX_ROOT=<沙箱>/aux_root` | **rc=3**、0.1s,stderr = 两行路径播报 + 「令牌校验失败:令牌不存在(可能已吊销或来自其他令牌文件)」+「拒绝启动(fail-closed)」;`serverInfo=None`、`tools=None`。同一进程若先剔除全部 `MDCG_*`/`DEEPSEEK_*` 则 rc=0(见腿6)。⇒ 新腿不显式剔这些前缀会**假红** | `md_cg/mcp_server.py:3714`(`"令牌校验失败:{e}"` 成形)· `md_cg/tokens.py:497`(`TokenError("令牌不存在…")` 抛出,本报告读码确认) | 采集腿;**本报告复核(读码)**:两处成形/抛出点行号属实 |
|
|
94
|
+
| 6 | **重放面 · 基线握手(可拦性 / 绿侧对照)** | 剔凭据 + `MDCG_ROOT=<沙箱>/memory_root` + `MDCG_AUX_ROOT=<沙箱>/aux_root`(均在 `tempfile` 沙箱内);三行逐行 JSON-RPC:`initialize{protocolVersion:2024-11-05, clientInfo}` / `notifications/initialized` / `tools/list` | `npm pack` rc=0、3.0s、共 **1493** 条目、含 `utf8_boot.py`=True、含 `md_cg/mcp_server.py`=True、根级条目 `['LICENSE','README.md','package.json','utf8_boot.py']`;`npm install` rc=0、7.9~8.2s;启动 rc=0、1.4~1.5s,`serverInfo={"name":"mdcg-mcp","version":"0.6.1"}`、`tools=['cg','stg']`——**等于**文档口径缺省面(`md_cg/mcp_server.py:1044` `SURFACE` 缺省 `'kernel'`、`:1056` `tools = ALL_TOOLS if SURFACE == "full" else KERNEL_TOOLS`)。stderr 实得「写入策略:来源=package_default path=<…>\dsh-memory\data\policy.json(forbidden=11 required=6)」。⇒ 链路在改动前树上即已跑通、缺省面可机械锚定,新腿的**可拦性成立** | `md_cg/mcp_server.py:1056` | 采集腿;**本报告复核(等价实跑)**:§4.3 绿侧同读数(本次实跑) |
|
|
95
|
+
| 7 | **文档面口径 · 八道 ↔ 九道缺口** | 全仓扫 `八道 / 八条腿 / 8 条腿 / 8 legs / 八腿 / 九道 / check_publish_smoke`(遍历仓内 `.md/.py/.ts/.json/.yml`,跳过 `.git/node_modules/__pycache__`) | 采集时 `docs/mdcg/发布门禁链_v0.1.md` 写 `:7`「门禁链已由 5 条扩至 8 条腿」、`:17`「(八道门禁,见下)」、`:40`「八道门禁与 CI 同形但不完全同覆盖」——该文档自称「逐条与 `package.json` 的 `scripts.gate` 实读对齐」,实读确为 8 ⇒ **缺第九道**。同类表述另见 `docs/eval/发布07_…_v1.0.md:135`、`docs/eval/优化第三批_…_v1.0.md:34`、`docs/eval/归一层缺省翻关_修复记录_v1.0.md:88/263/419`。`README.md` **无**门禁腿数描述 | `docs/mdcg/发布门禁链_v0.1.md:7` | 采集腿;**本报告复核**(§4.8 实跑扫描:该文档现已同步为九道;README 无腿数表述) |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 三、修法契约与落点
|
|
100
|
+
|
|
101
|
+
### 3.1 新腿契约(`scripts/check_publish_smoke.py`)
|
|
102
|
+
|
|
103
|
+
**链路(照抄契约「已由编排侧验证过的配方」,四段真做)**:
|
|
104
|
+
|
|
105
|
+
1. `npm pack --pack-destination <沙箱>/pack`(**真产物**,非 `--dry-run`)——`scripts/check_publish_smoke.py:343`;
|
|
106
|
+
2. `tarfile` 独立扫描 tgz 得到**发货清单**(`:180` `_tarball_members`)——不采信 npm 自报;
|
|
107
|
+
3. 空沙箱(写 `{"name":"mdcg-publish-smoke","private":true}`)`npm install <tgz> --no-audit --no-fund --legacy-peer-deps`——`:373`;
|
|
108
|
+
4. cwd=**装好的目录**跑 `python -X utf8 -m md_cg.mcp_server`,stdin 逐行喂 `initialize(2024-11-05)` / `notifications/initialized` / `tools/list`——`:221` `_handshake`、`:231` argv。
|
|
109
|
+
|
|
110
|
+
**判据面 S0–S6(名字即机器读面,末行 `SMOKE_JSON` 供守卫解析)**:
|
|
111
|
+
|
|
112
|
+
| 判据 | 内容 | 红否 |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| S0 | npm 可执行面可解析(复用 `check_publish_artifact.resolve_npm()`;探不到即 **fail-closed 退出码 1**,不静默 SKIP) | 判负 |
|
|
115
|
+
| S1 | 出货清单**点名**含仓根 `utf8_boot.py`(`:363`),缺则打印「修法:files 加 utf8_boot.py」(`:367`) | 判负 |
|
|
116
|
+
| S2 | 装好的目录含 `utf8_boot.py`(`:386`) | 判负 |
|
|
117
|
+
| S3 | 装好的目录含 `md_cg/mcp_server.py`(`:390`) | 判负 |
|
|
118
|
+
| S4 | 真握手成功:`serverInfo.name/version` 与包内 `package.json` 对齐(`:424`) | 判负 |
|
|
119
|
+
| S5 | `tools == list(DEFAULT_TOOLS)`=`('cg','stg')`(`:63`、`:438`) | 判负 |
|
|
120
|
+
| S6 | 启动 stderr 的策略来源来自**包内** `data/policy.json`(`:454`) | **NOTE,恒不判负** |
|
|
121
|
+
|
|
122
|
+
**密闭契约(`_sealed_env`,`:121`–`:140`)**:剔除**继承来的全部** `MDCG_*` 与 `DEEPSEEK_*`(`:132`–`:133`),再注入沙箱内四根 `MDCG_ROOT`/`MDCG_AUX_ROOT`/`MDCG_STATE_ROOT`/`MDCG_DATA_ROOT`——**四根全在沙箱**,因为只给前两根时 `state/data` 根会回落 `~/.dsh/.dsh-memory` 并可能读到使用者 `paths.json` 指向的真实记忆库(注释 `:127`–`:130` 明写)。**本腿绝不读写真实记忆库**。
|
|
123
|
+
|
|
124
|
+
**沙箱契约(`_make_sandbox`,`:145`)**:缺省 `tempfile.mkdtemp()`(跑完 `rmtree`);env `MDCG_GATE_SANDBOX_DIR` 给定时用该目录并**保留不删**(两分支各打印一行来源与处置,`:151`/`:154`、`:273`/`:276`)。
|
|
125
|
+
|
|
126
|
+
### 3.2 落点(逐处)
|
|
127
|
+
|
|
128
|
+
| 落点 | 内容 |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `package.json:89` | `scripts.gate` 增第九腿 `python scripts/check_publish_smoke.py`,插在 `check_publish_artifact` **之后**、`cogmap_sync check` 之前(**位序有理**:贴发布件面,且在会重写 `lib/` 的 `prepare` 之前,见 `docs/mdcg/发布门禁链_v0.1.md:58-62`) |
|
|
131
|
+
| `scripts/check_publish_artifact.py:399-409` | 新增 `resolve_npm()` **解析单点**(Windows→`npm.cmd`,不经 `cmd /c`) |
|
|
132
|
+
| `scripts/check_publish_artifact.py:414` | `_npm_pack_json` 改走该单点(HEAD `:401`→`:402` 的内联字面量被删,**不留第二套方言**) |
|
|
133
|
+
| `scripts/check_publish_smoke.py:1` | 新腿本体(纯 stdlib:`argparse/importlib.util/json/os/shutil/subprocess/sys/tarfile/tempfile/time`;argv 列表 + `shell=False` + 显式 UTF-8) |
|
|
134
|
+
| `scripts/test_publish_smoke_guard.py:1` | 新腿的守卫([A] 静态锚点 11 条 · [B] 定点变异自证) |
|
|
135
|
+
| `docs/mdcg/发布门禁链_v0.1.md` | `:7` 保留 2026-09-30 历史段、`:12-14` 补 2026-10-01 段、`:21`/`:44` 八道→九道、`:50` 补第 3 腿行、`:58-62` 位序理由、`:66-74` 为何必要(#38 与 #48 同类漏两次)、`:76-82` 判据面 S0–S6、`:84-87` 诚实边界、`:93-95` 无 CI 覆盖的腿号改 1/3/8/9 |
|
|
136
|
+
|
|
137
|
+
**契约点名、本报告核实存在的参考件**(契约 `sites` 提示「照抄同目录风格/参考实现」):`scripts/check_registry_tarball.py`(6577 字节)、`test/mock_mcp.py`(2031 字节)——两者均在位(本报告实跑 `ls`)。
|
|
138
|
+
|
|
139
|
+
### 3.3 偏离契约两处(显式披露,非静默)
|
|
140
|
+
|
|
141
|
+
**① 沙箱凭据根叶子取 `aux_root`,不取契约写的 `aux`**(`scripts/check_publish_smoke.py:66-71` 注释、`:71` `AUX_LEAF = "aux_root"`)。
|
|
142
|
+
|
|
143
|
+
机制(本报告读码 + 实跑,**这才是从「那个表达式」到「服务 rc=2 拒启」的完整链条**):
|
|
144
|
+
|
|
145
|
+
- 契约原文要求把凭据根指到 `<沙箱>/aux`(附录 A 可核)。
|
|
146
|
+
- 在 Windows 上,**`os.path.abspath` 内部走 `nt._getfullpathname`(即 `GetFullPathNameW`)**,该 API 会把**保留设备名**末段解析进**设备命名空间**——所以 `os.path.abspath(r"D:\x\aux")` 实测得到 `'\\\\.\\aux'`(本报告实跑,见 §4.9-②),而不是 `D:\x\aux`。**不是 `basename`,也不是 `_abs_host_path` 内部另做了一次解析**:解析就发生在 `abspath` 那一层,`_abs_host_path` 只是**读结果**。
|
|
147
|
+
- `md_cg/datapath.py:60` `_abs_host_path` 的实现正是「`r = os.path.abspath(os.path.expanduser(p))`(`:61`)→ `if os.name == "nt" and r.startswith("\\\\.\\"):`(`:62`)→ `raise ValueError(...)`(`:64`–`:68`)」,其注释 `:53`–`:57` 逐字写着「归一结果以设备命名空间前缀(`\\.\`)开头时抛 ValueError……例 `D:\sandbox\aux` → `\\.\aux`」。
|
|
148
|
+
- `datapath.aux_root()`(`:253`–`:267`)对环境变量 `MDCG_AUX_ROOT` 走 `_abs_host_path(env, ENV_AUX_ROOT)`(`:267`)⇒ 一旦末段是 `aux`,起点即抛 `ValueError`,服务以 rc=2 拒绝启动。
|
|
149
|
+
- **本报告实跑确认的是等式的左边一半**(`abspath` → `\\.\aux`);「服务 rc=2 拒启」这后半段是**采集腿读数 + 读码推得**,**本报告未端到端实跑**(与 §5 的处置一致)。
|
|
150
|
+
|
|
151
|
+
**② 文档里对新脚本用 code span 而非相对链接**:`link_check` 把 **UNTRACKED** 链接目标判失败——首次 gate 实跑即卡在 `[UNTRACKED] docs/mdcg/发布门禁链_v0.1.md:77 -> ../../scripts/check_publish_smoke.py`,而本次硬边界**禁 `git add`**。本报告同样全程用 code span。
|
|
152
|
+
|
|
153
|
+
### 3.4 退出码:**两个程序的两个含义,必须并列读**
|
|
154
|
+
|
|
155
|
+
| 程序 | 退出码 2 的含义 | 出处 |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| **新腿** `scripts/check_publish_smoke.py` | **环境错误**(npm pack 失败、tarball 找不到、解释器起不来、读不到 `package.json` 的 `name`、npm 解析单点加载失败) | `:41` 契约行;`:312`/`:326`/`:348`/`:353`/`:357` 各返回 2 |
|
|
158
|
+
| **守卫** `scripts/test_publish_smoke_guard.py` | **ANCHOR-MISS**(变异锚点漂移,fail-closed)——**与环境无关** | `:37` 契约行;`:420`–`:422` `if _MISS: return 2` |
|
|
159
|
+
|
|
160
|
+
⇒ **两者不是同一个「2」**。新腿的 `2` 是「本腿没跑成」;守卫的 `2` 是「守卫的变异锚点在真源里找不到,拒绝放行」。**读 §4.1/§4.4 里的 `rc=2` 时一律按守卫语义理解**,不要代回新腿的 §3.1 定义。另有第三个「2」出现过一次:§二.1 里「执行缺失脚本实得 rc=2」是 **Python 解释器**打不开文件的退出码,与前两者都无关。
|
|
161
|
+
|
|
162
|
+
**新腿退出码契约**:`0` 通过 | `1` 判据红(含 npm 探不到)| `2` 环境错误(`:465` `code = 1 if report.fails else 0`;环境错误路径一律 `_finish(..., 2, ...)`)。
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 四、验证数字
|
|
167
|
+
|
|
168
|
+
### 4.1 守卫本体(`scripts/test_publish_smoke_guard.py`)——**本报告实跑**
|
|
169
|
+
|
|
170
|
+
| 模式 | 命令(照录) | 读数 | 退出码 |
|
|
171
|
+
|---|---|---|---|
|
|
172
|
+
| 缺省(进全量套件的形态) | `python -X utf8 scripts/test_publish_smoke_guard.py` | **11 条断言,0 红**(`11 通过,0 失败,0 锚点漂移`) | **0** |
|
|
173
|
+
| 变异自证 | `python -X utf8 scripts/test_publish_smoke_guard.py --mutate` | **27 通过,0 失败,0 锚点漂移** | **0** |
|
|
174
|
+
|
|
175
|
+
(缺省模式跑于本报告前序 ask;本 ask 复跑 `--mutate`,其中 `[A]` 组 11 条静态断言全 PASS,读数一致。)
|
|
176
|
+
|
|
177
|
+
27 = 静态 11 + 变异自证 16(B1 逐处 11 + B2 行为面 5)。**`[A]` 11 条锚点**:C1 gate 链含本腿 / C2 紧随 `check_publish_artifact` / C3 脚本在且可读 / C4 清单点名 + 修法行 / C5 缺省工具面字面量 + 相等断言 / C6 剔除 `MDCG_*` 与 `DEEPSEEK_*` / C7 沙箱两分支 / C8 复用 `cpa.resolve_npm()` / C9 握手三条 JSON-RPC / C10 沙箱内注入 `MDCG_ROOT`+`MDCG_AUX_ROOT` / C11 `_npm_pack_json` 未被绕过。
|
|
178
|
+
|
|
179
|
+
> 守卫的验收判据**不是「门禁绿」**:它要求每处定点变异后**恰好**命中预期红项集合(集合相等,多一项少一项都判红),锚点漂移报 `ANCHOR-MISS` 并退出码 **2**(fail-closed,**守卫语义,见 §3.4**)。`docs` 里亦以 C2 把新腿位序钉死(挪到链尾即红)。
|
|
180
|
+
|
|
181
|
+
### 4.2 每处变异红项数(**本报告实跑 `--mutate`**,逐行照录)
|
|
182
|
+
|
|
183
|
+
| 变异 | 命中红项(**恰好**) | 红项数 |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| 删 gate 腿 | C1, C2 | **2** |
|
|
186
|
+
| 把 gate 腿挪到链尾 | C2 | **1** |
|
|
187
|
+
| 删冒烟脚本文件 | C3, C4, C5, C6, C7, C8, C9, C10 | **8** |
|
|
188
|
+
| 去掉缺件修法行 | C4 | **1** |
|
|
189
|
+
| 改缺省工具面字面量 | C5 | **1** |
|
|
190
|
+
| 漏剔 `DEEPSEEK_*` | C6 | **1** |
|
|
191
|
+
| 沙箱保留分支改名 | C7 | **1** |
|
|
192
|
+
| 不再复用 npm 单点 | C8 | **1** |
|
|
193
|
+
| 握手不再发 `tools/list` | C9 | **1** |
|
|
194
|
+
| 凭据根不指沙箱 | C10 | **1** |
|
|
195
|
+
| `_npm_pack_json` 绕过单点 | C11 | **1** |
|
|
196
|
+
|
|
197
|
+
「删 gate 腿 → 2 红」「删脚本文件 → 8 红」两处多红是**语义必然**(腿没了位序亦无从成立;源不可读时锚点必须红),已写死在 expected 里,多一项少一项都算漂移。
|
|
198
|
+
|
|
199
|
+
### 4.3 行为面变异(B2,**本报告本 ask 实跑**:临时副本 → 真 pack → 真装 → 真握手)
|
|
200
|
+
|
|
201
|
+
- **副本材料化**:`复制追踪件 2113 件 + lib/`(走 `git ls-files`,显式补拷本腿源文件与 `lib/`;**不以 git HEAD/提交为基线源**——本腿未 `git add` 时守卫亦可用,`:261` `_materialize_repo`)。
|
|
202
|
+
- **绿侧(未变异副本)**:`rc=0` / `fails=[]` / 清单条目=**1495** / 装好目录含 `utf8_boot=True` / `serverInfo={"name":"mdcg-mcp","version":"0.6.1"}` / `tools=["cg","stg"]`。
|
|
203
|
+
- **红侧(变异:`files` 删 `"utf8_boot.py"`)**:`rc=1` / **恰好 4 红**(S1 出货清单含仓根 `utf8_boot.py`、S2 装好的目录含 `utf8_boot.py`、S4 真握手成功、S5 tools 面 == 缺省面) / 清单条目=**1494** / `has_utf8_boot=false` / 握手 `rc=1`,并打印「修法:files 加 utf8_boot.py」。
|
|
204
|
+
- **真工作区未变异**:`--mutate` 的 pack/install 均在 `%TEMP%\smoke_guard_behav_…\repo` 副本内进行;本报告读 `package.json:23` 仍含 `"utf8_boot.py"`。
|
|
205
|
+
|
|
206
|
+
**注(清单条目数为何在三次观测里是 1493 / 1494 / 1495,以及它为何会继续变)**:这三个数**不是矛盾,是同一序列上的三个时刻**,差额全部来自**本报告之外**的暂存动作(`npm pack` 按 `files` 白名单打包**工作区文件**,与 git 跟踪状态无关;`docs/` 在白名单内,故暂存进 `docs/` 的文件会同时进包):
|
|
207
|
+
|
|
208
|
+
| 时刻 | `git ls-files` 计数 | pack 条目 | 该时刻工作区的额外暂存项(**非本报告所为**) | 出处 |
|
|
209
|
+
|---|---|---|---|---|
|
|
210
|
+
| 工作流采集腿 | 2111 | **1493** | 无 | §二.2/§二.6(采集腿读数) |
|
|
211
|
+
| 本报告前序 ask 实跑 | 2112 | **1494** | `docs/plans/…_v0.1.md`(`A`) | §4.3 上一版读数 |
|
|
212
|
+
| 本报告本 ask 实跑 | **2113** | **1495** | `docs/plans/…_v0.2.md`(`A`,由 v0.1 更名而来)**+ 本报告文件本身被置为 `A`** | §4.3/§4.9-①(本报告实跑) |
|
|
213
|
+
|
|
214
|
+
**读者可自行验证这条序列**:`git ls-files | wc -l` 与 `git status --short`(本报告实跑:2113;`A docs/eval/出货面冒烟_进货门禁_v1.0.md`、`A docs/plans/…_v0.2.md`)。**各读数只在其自身时刻的口径内成立**;本报告不再断言「哪一套是标准口径」。
|
|
215
|
+
|
|
216
|
+
### 4.4 新腿自身读数(**工作流采集**,非本报告执行)
|
|
217
|
+
|
|
218
|
+
> **本节全部读数属于新腿 `scripts/check_publish_smoke.py`**。下面最后一条(`--mutate` / `ANCHOR-MISS`)**属于守卫 `scripts/test_publish_smoke_guard.py`**——新腿没有 `--mutate` 开关,其可配面只有 `--root`(`:291`–`:294`)与环境变量 `MDCG_GATE_SANDBOX_DIR`(`:329`);该条与上表并列只为对照「两个 2 的不同语义」(§3.4),**不属于新腿判据面**。
|
|
219
|
+
|
|
220
|
+
- `python -X utf8 scripts/check_publish_smoke.py` → `rc=0`:沙箱=`tempfile.mkdtemp` 且已清理、清单条目=1493、S1–S5 全 PASS、`serverInfo={name:mdcg-mcp,version:0.6.1}`、`tools=['cg','stg']`、S6 NOTE 策略来源=package_default path=`<装好目录>/data/policy.json`(包内件=是)。
|
|
221
|
+
- `MDCG_GATE_SANDBOX_DIR=E:/test/smoke` 重跑 → `rc=0` 且打印「沙箱保留:E:\test\smoke」,其余读数同上。
|
|
222
|
+
- **密闭面取证**:握手前后快照 `C:/Users/test/.mdcg` 与 `C:/Users/test/.dsh/.dsh-memory` → **added 0 / changed 0**(真库未被触碰)。
|
|
223
|
+
- **退化路径**(npm 探不到):`PATH` 剥到 `C:\Windows\System32` 使 `which('npm.cmd')=None` → `rc=1` + `[FAIL] S0` + `SMOKE_JSON verdict=FAIL/env_error=false`,**无 `[SKIP]` 行、无 Traceback**(fail-closed,不静默放过)。
|
|
224
|
+
- 【**守卫**,非本腿】ANCHOR-MISS 判别力:临时根里把修法行改名后跑 `python -X utf8 scripts/test_publish_smoke_guard.py --mutate` → 打印 `ANCHOR-MISS 去掉缺件修法行 ← … 找不到变异锚点` 并 **rc=2**(守卫语义,§3.4)。
|
|
225
|
+
|
|
226
|
+
### 4.5 测试套件
|
|
227
|
+
|
|
228
|
+
| 层 | 命令 | 读数 | 退出码 | 谁跑的 |
|
|
229
|
+
|---|---|---|---|---|
|
|
230
|
+
| `scripts` 组(含新守卫) | `python -X utf8 scripts/run_tests.py scripts` | **17/17 通过,0 跳过**,含 `PASS scripts.test_publish_smoke_guard` | **0** | **本报告实跑**(前序 ask 与本 ask 各一次,读数一致) |
|
|
231
|
+
| `md_cg` 组 | `python -X utf8 scripts/run_tests.py md_cg` | **213/213 通过(3 跳过)** | 0 | 工作流采集 |
|
|
232
|
+
| **python 全量** | `python -X utf8 scripts/run_tests.py` | `PASS scripts.test_utf8_boot_guard` | `===== SUMMARY 290/290 通过,5 跳过(依赖缺失/平台不符) =====` | **0** | 工作流采集(**本报告未跑**) |
|
|
233
|
+
|
|
234
|
+
### 4.6 容器两栈(**工作流采集,本报告未跑**——本机 win32 无 Docker)
|
|
235
|
+
|
|
236
|
+
| 栈 | 读数 | 退出码 |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| 一(`linux_verify.sh full`) | `结果: 22 pass / 0 fail` | `[PASS] smoke_test (linux)` | `=== 汇总: 38 pass / 0 fail ===` | **0** |
|
|
239
|
+
| 二(`verify_linux_node.sh`) | `# cancelled 0` | `# skipped 3` | `# todo 0` | `# duration_ms 11689.195425` | **0** |
|
|
240
|
+
|
|
241
|
+
### 4.7 串联门禁 `npm run gate`
|
|
242
|
+
|
|
243
|
+
- **工作流采集**:`npm run gate` → `rc=0` **九腿全绿**(新腿 `SMOKE_JSON verdict=PASS`;`cogmap check` 通过;`link_check` OK=235/BROKEN=0/UNTRACKED=0;`workspace_index [OK]` 顶层 20·追踪 2112;`verify_discipline` 10/10;`cargo test` 28 passed/0 failed;`rank_parity` 逐位一致)。对照(修前形态、八腿)副本 `npm run gate` rc=0、9.1s。
|
|
244
|
+
- ⚠ **该读数的成立条件缺一项:采集方未标注这次 gate 跑在哪个树**(真工作树?还是副本?)。本报告**不据它推断工作树未被改动**——因为 `npm pack` 会触发 `prepare`(本仓 `prepare` 脚本检查 `node_modules/typescript/bin/tsc` 是否存在,存在即 `rmSync('lib')` 后重跑 `tsc`),**若该 gate 跑在真工作树上,则 `lib/` 会被重写**。§五里复核者的「`lib/` mtime 仍 05:02 未被重建」是**复核者自己那份探针的读数**,其探针范围见 §五,**不构成本报告对那次 gate 的核验**。
|
|
245
|
+
- **本报告未跑串联 gate**,原因如实说明:`npm pack` 会触发上述 `prepare`→`tsc`,**会重写工作树的 `lib/`**——与本任务「不改源码」硬边界相冲。故本报告只在**临时副本内**跑等价链路(§4.3、§4.9-①),并已实测副本内 `prepare` 走「**跳过构建:typescript 未安装**」分支(副本不含 `node_modules`,§4.9-① 的 pack stdout 首行可核)。
|
|
246
|
+
|
|
247
|
+
### 4.8 文档面扫描(**本报告前序 ask 实跑**)
|
|
248
|
+
|
|
249
|
+
扫描命令:遍历仓内 `.md/.py/.ts/.json/.yml/.yaml`(跳过 `.git/node_modules/__pycache__/.zcode`)匹配 `八道|八条腿|8 条腿|8 legs|八腿|九道|check_publish_smoke`,命中 **39** 行。结论:
|
|
250
|
+
|
|
251
|
+
- `docs/mdcg/发布门禁链_v0.1.md` 已同步:`:21`/`:44` 均为「九道」,`:50` 第 3 腿行为 `check_publish_smoke.py`,`:12-14` 有 2026-10-01 更新段,`:7` 的「8 条腿」是**带日期的历史段**(保留合理)。
|
|
252
|
+
- **现存「八道/八条腿」表述只在带日期的 `docs/eval/*` 历史记录里**(`发布07_…:135/137/160`、`优化第三批_…:34/89`、`归一层缺省翻关_…:88/263/388/419`)——历史报告不回改,符合本仓口径。
|
|
253
|
+
- `README.md` **未命中**任何腿数表述(故无需同步腿数)。
|
|
254
|
+
- 与 `.github/workflows/` 实读一致:**8 个 workflow**(`cogmap-check` / `conformance-check` / `discipline-check` / `hive-check` / `install-verify` / `publish-artifact-check` / `python-tests` / `workspace-index-check`),**无 smoke 腿**(故新腿「无 CI」标注属实)。
|
|
255
|
+
|
|
256
|
+
### 4.9 本次修订 ask 新增的实跑(四条,均本报告执行)
|
|
257
|
+
|
|
258
|
+
**① `skills` 缺件差量复核**(在 `%TEMP%` 副本内,复用 `check_publish_artifact._npm_pack_json` + `extract_pack_manifest`,不触真工作区):
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
tracked copied = 2113
|
|
262
|
+
BASELINE n=1495 skills/=703 (样例:skills/plugin.json、skills/README.md、skills/skills/designer-perspective/…)
|
|
263
|
+
MUTATED n=792 skills/=0 (files 删 "skills" 后)
|
|
264
|
+
DELTA = 703
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
⇒ **差量 = 703**,与采集腿「1493→790」的差(**703**)一致;采集文本里的「704 件」**无支撑,已就地标注不采信**(§二.3 / §1.4)。
|
|
268
|
+
|
|
269
|
+
**② `abspath` 设备名等式**(本机 win32,Python 3.12):
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
abspath(r'D:\x\aux') = '\\\\.\\aux' ← 与 §3.3-① 引用的等式一致
|
|
273
|
+
normpath(r'D:\x\aux') = 'D:\\x\\aux' ← 规范化本身不触发
|
|
274
|
+
basename = 'aux' | dirname = 'D:\\x'
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**③ 契约原文提取**(回答反馈「契约全文一行未列」):从 `.zcode/workflow-runs/dwfrun-b27a6016-4fb8-4a76-a03a-aad166ef5762.mjs` 内联 `args` JSON 取出 `contract`(3078 字符)、`sites`(350 字符)、`guard`、`report`、`container`——**全文见附录 A**。其中 `args.report = "docs/eval/出货面冒烟_进货门禁_v1.0.md"`,即本文件路径的出处。
|
|
278
|
+
|
|
279
|
+
**④ 独立复核所引探针的可达性检查**:在**工作区**、`%TEMP%`、`D:/program` 三处递归搜索 `probe_prefix*.py / probe_silent*.py / probe_equiv*.py / probe_del_assert*.py / probe_green*.py` → **0 命中**(`%TEMP%` 下另有 181 个历史 `probe_*.py`,但**不含**这六个名字)。⇒ §五 引用的六个探针**在本报告可达范围内不存在**,其读数**不可定位、不可复现**;§五 已相应降级标注。
|
|
280
|
+
|
|
281
|
+
**⑤ 附带复核**:`scripts/workspace_index.py` 的登记面(`:187`–`:188` `unreg_dirs`/`miss_dirs` 只对 `DIR_ROLES` 与 `tops`;`:261`–`:262` 只对 `roots` 与 `ROOT_FILES`)⇒ 新增 `scripts/*.py` **确实无需登记**(采集腿腿1 的附带核实成立)。
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 五、独立复核判定与 uncovered
|
|
286
|
+
|
|
287
|
+
**判定:ACCEPT**(复核者为不同执行体;本节为**转述**)。
|
|
288
|
+
|
|
289
|
+
**复核者的前置声明**(转述):本会话 `ListWorkflowRuns` 返回 `workflow_introspection_unavailable`,ask#1「复现员」的记录不可达;故①由复核者从 `.zcode/workflow-runs/dwfrun-b27a6016-…mjs` 读出 `args.contract` 后**自建等价修前现场**,**不采信执行者自述**。
|
|
290
|
+
|
|
291
|
+
**依据(复核者自跑的四组检查)**——⚠ **本节读数的可复核性已降级**:其六个探针脚本(`probe_prefix.py`/`probe_silent.py`/`probe_equiv.py`/`probe_equiv2.py`/`probe_del_assert.py`/`probe_green.py`)**本报告在工作区、`%TEMP%`、`D:/program` 三处搜索均未找到(0 命中,§4.9-④)**,即:**无路径、无留存说明、命令与输出均为转述而非照录**。故以下内容本报告**按复核者自述采信,未复核、未复跑**;本报告能独立复核的部分已在 §四分别实跑:
|
|
292
|
+
|
|
293
|
+
1. **修前盲区与退化路径**(复核者称 `probe_prefix.py` / `probe_silent.py`):`git show HEAD:package.json` → gate 仅 8 腿无 smoke;`git cat-file -e HEAD:scripts/check_publish_smoke.py` → **rc=128**(←**本报告已独立复核成立**,§一.2)。临时副本(`files` 去掉 `utf8_boot.py`、文件仍在仓根)上:在役 `check_publish_artifact.py --root <copy>` → `rc=0 VERDICT=PASS`,而**独立 `tarfile` 扫描**同副本真产 tarball 得 1493 条目且 `utf8_boot.py ∉ 集合` ⇒「仓里在、包里不在」成立而旧门禁全绿;同一副本上新腿 → `rc=1`、`fails` 恰为 S1/S2/S4/S5、自报 `manifest_entries=1493` 与独立 tar 扫描 1493 **对账一致**、打印修法行(←**本报告以守卫 B2 红侧等价复核成立**,§4.3)。退化路径:`PATH` 剥到 `C:\Windows\System32` → `rc=1` + `[FAIL] S0` + `SMOKE_JSON verdict=FAIL/env_error=false`,无 `[SKIP]`、无 Traceback(←**转述,本报告未复跑**)。
|
|
294
|
+
2. **与改前逐位一致**(复核者称 `probe_equiv.py` / `probe_equiv2.py`):HEAD 为内联字面量(`git show HEAD:…:401`←**本报告已读码复核**),现行为 `resolve_npm()`(`check_publish_artifact.py:399-409`);拦 `subprocess.run` 取实际 argv:**head 与 cur 逐位相同**(含 `--ignore-scripts` 变体),`shell=False` 保持。同一真 git 面副本上两份实现 `--root` 扫描 → `rc(head)=rc(cur)=0`、stdout 归一逐行相同、`VERDICT=PASS`,且两者自报文件数 **1494** 与独立 `npm pack --dry-run --json` 的 1494 条目 oracle **三方对齐**(←**转述**;其 1494 与 §4.3 的「前序 ask 时刻」口径一致)。
|
|
295
|
+
3. **守卫本体与变异自证**(复核者称独立跑):缺省 → 11 条断言/0 红/rc=0;`--mutate` → **27 通过/0 失败/0 锚点漂移/rc=0**;[B1] 11 处定点变异逐处恰好命中(含 C1+C2、C3+七锚点两处写死的多红);[B2] 绿侧 rc=0/`fails=[]`/`tools=['cg','stg']`/`serverInfo={mdcg-mcp,0.6.1}`/清单 1494,红侧 rc=1 恰 4 项/清单 1493/`has_utf8_boot=false`(←**本报告本 ask 已独立实跑同类读数**,§4.1/§4.2/§4.3,数值差额已于 §4.3 注说明)。**删断言探针**(复核者称 `probe_del_assert.py`,仅内存改 `_static_checks`/`_static_mutations` 不落盘):删 C11 → 自证 `FAIL=1`(实得 `[]` ≠ `{C11}`);删 C4 → `FAIL=2`;删 C4..C10 整组 → `FAIL=8`;基线 0 红 ⇒ **守卫对「断言被删」有判别力**(←**转述,本报告未复跑**;该探针亦不可定位)。
|
|
296
|
+
4. **不得静默可观测面**(复核者称 `probe_silent.py` / `probe_green.py`):S0 fail-closed 见①;锚点漂移把 gate 写成 `'&& python -X utf8 scripts/…'` 后 C1/C2 仍绿(`_FAIL=0`)但打印 `ANCHOR-MISS`、`_MISS=2`、**rc=2**;沙箱两分支均观测(缺省 tempfile → 打印「沙箱已清理」且 `isdir=False`;给定 env → `sandbox_kept=True` 且保留);S6 NOTE 可见。文档面 `docs/mdcg/发布门禁链_v0.1.md:48-56` 列 1–9 腿与 `package.json` gate **同序**、smoke 第 3 位标「无 CI」,与 `.github/workflows/` 实际 8 个 workflow(无 smoke)一致;现存「八道/八条腿」只在带日期的 `docs/eval` 历史记录里(←**文档面与 workflow 计数本报告已独立复核成立**,§4.8)。
|
|
297
|
+
|
|
298
|
+
**结论与残留**:复核者四项 ask 指定检查(**其原文未随转述给出——见 §八.5**)全部由其在同一 ask 内实跑并通过,核心修复成立,故 **ACCEPT**;**残余面如实列入 uncovered**(§六,与本报告自列口径一致)。
|
|
299
|
+
|
|
300
|
+
> **复核者的「工作区只读」自证**(转述):实验全在系统临时目录(跑完清理),`git status` 与开工逐字一致、`lib/` mtime 仍 05:02 未被重建。⚠ **本报告无法核验这句**(§4.7);且本报告写作期间工作区**确实**发生了本报告之外的暂存变化(§4.3 注)。
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 六、边界与未覆盖(含本轮明确不修而留池的面)
|
|
305
|
+
|
|
306
|
+
### 6.1 新腿契约自陈的不覆盖面(`scripts/check_publish_smoke.py:18-21`)
|
|
307
|
+
|
|
308
|
+
1. **不覆盖 DSH 桥侧**——`dsh/` 插件与 MCP 客户端的接线未验;
|
|
309
|
+
2. **不覆盖真实 DSH 安装路径**——装的是空沙箱里的 `node_modules`,不是宿主真实安装面;
|
|
310
|
+
3. **不覆盖 peer 依赖解析**——安装加 `--legacy-peer-deps` **跳过 peer**;
|
|
311
|
+
4. **不覆盖 `MDCG_MCP_SURFACE=full` 的多工具面**——本腿只钉缺省面 `['cg','stg']`(因为子进程 env 已剔除 `MDCG_*`,full 面在本腿口径下不可达);
|
|
312
|
+
5. **不覆盖 TypeScript 侧 `lib/` 的运行时行为**——`prepare` 构建产物本身无运行时断言。
|
|
313
|
+
6. **不覆盖 `#38` 那一形(整目录)**:S1/S2/S3 只点名 **3 个具体路径**(`utf8_boot.py`、`md_cg/mcp_server.py`),**没有**「`files` 里声明的每个白名单项都必须出现在 tarball 里」这类**全量对账**判据 ⇒ 今天再删掉 `files` 里的 `scripts`/`hive` 之外的任何一项(例如 `dsh`、`codebuddy`、`zcode`、`docs`),若无启动副作用则**本腿不红**(详见 §八.1)。
|
|
314
|
+
|
|
315
|
+
### 6.2 验证范围残面
|
|
316
|
+
|
|
317
|
+
7. **容器脚本未并入本腿**:容器双腿是**固定清单**,未含本次新增文件;且新守卫 `--mutate` 需 npm,`rust:bookworm` **无 npm**,故未并入容器清单。⇒ §4.6 两栈读数(38 pass/0 fail 等)**不含**新腿与新守卫,**本报告不把它读成「容器里验过本腿」**。
|
|
318
|
+
8. **`npm install` 是否全程零网络访问未验证**(`--legacy-peer-deps` 实测 rc=0,未触发契约给的降级路径「解包 tarball 后启动」)——离线可复现性无证据;**本腿的单次耗时(四段合计)也未取得专项读数**(§八.4)。
|
|
319
|
+
9. **本轮未跑全量与容器**:按任务自跑范围明确排除「全量 python 套件(`compiler`/`swarm`/`hive` 组)与容器双腿」;§4.5/§4.6 的数字**来源为工作流采集/脚本随后跑,非本报告执行**。
|
|
320
|
+
10. **本报告未跑串联 `npm run gate`**(原因见 §4.7:`npm pack` 会 `prepare`→`tsc` 重写 `lib/`,与「不改源码」硬边界相冲)。⇒ §4.7 的九腿全绿**无本报告的执行证据,且其运行树未标注**。
|
|
321
|
+
11. **`cmd /c` 假绿复现面**:本次会话**未复现**「`cmd /c npm …` 假绿」(python→`CreateProcess` 路径下 rc=0 是因腿**真绿**;MSYS bash 路径下 cmd 解析不到 → rc=127)。⇒「假绿」这一历史读数(`resolve_npm` docstring `:405` 自述 2026-09-30 实测)**本轮未由任何一方复现**,只作背景。
|
|
322
|
+
12. **§五的四组复核读数不可定位**(六个探针 0 命中,§4.9-④)⇒ 其结论**只能作为复核者自述引用**,日后复查无留存入口。
|
|
323
|
+
|
|
324
|
+
### 6.3 本轮**明确不修而留池**的面
|
|
325
|
+
|
|
326
|
+
13. **认知图归档未做**(工作纪律第 16 条)——**硬边界:不动在役数据根**;任务收尾归档留主会话。
|
|
327
|
+
14. **历史 `docs/eval/*` 的「八道/八条腿」表述不回改**——带日期的历史记录,按本仓口径保留(§4.8 已列全部命中位置)。
|
|
328
|
+
15. **`README.md` 未改**——全仓扫描证其无腿数表述(§4.8),无可同步项。
|
|
329
|
+
16. **本腿的 CI 面未补**——`.github/workflows/` 无 smoke workflow,故新腿只在「有人本地跑 `npm run gate`」时生效;见 §八.2。
|
|
330
|
+
|
|
331
|
+
### 6.4 环境侧(本报告之外,非本轮缺陷)
|
|
332
|
+
|
|
333
|
+
17. **并发暂存动作(本报告之外)**:写作期间 `docs/plans/…_v0.1.md` 更名为 `…_v0.2.md`(同为 `A`),**本报告文件本身也被置为 `A`**。⇒ 这两处变动**发生在本报告两次只读观测之间**,且**本报告从未执行 `git add`/`git commit`/`git push`**(本报告全程只读 + 只写本文件)。**至于由哪个会话/进程造成,本报告无证据,不作指认**(依据只有 `git status` 显示的暂存状态本身)。
|
|
334
|
+
18. `gate_rust_crate_test` 在本机 `cargo` 在位时通过数 28、不在位时 SKIP 计入通过数 0(§二.4 vs §4.7)——该腿的「SKIP 即通过」口径是既有设计,**本轮未动**。
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 七、本报告实跑命令清单(可复现)
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
# —— 前序 ask 实跑 ——
|
|
342
|
+
python -X utf8 -c "… git show HEAD:package.json 解析 scripts.gate;git cat-file -e …" → 8 腿;cat-file rc=128 ×2
|
|
343
|
+
python -X utf8 scripts/test_publish_smoke_guard.py → 11 通过 / 0 失败 / 0 锚点漂移 / rc=0
|
|
344
|
+
python -X utf8 scripts/run_tests.py scripts → 17/17 通过,0 跳过 / rc=0
|
|
345
|
+
python -X utf8 -c "… 打印 package.json / check_publish_smoke.py / test_publish_smoke_guard.py /
|
|
346
|
+
check_publish_artifact.py / mcp_server.py / tokens.py / workspace_index.py 指定行 …"
|
|
347
|
+
python -X utf8 -c "… 遍历仓内 md/py/ts/json/yml 匹配 八道|八条腿|九道|check_publish_smoke …" → 39 命中
|
|
348
|
+
ls .github/workflows → 8 个,无 smoke
|
|
349
|
+
|
|
350
|
+
# —— 本 ask(修订)实跑 ——
|
|
351
|
+
python -X utf8 scripts/test_publish_smoke_guard.py --mutate → 27 通过 / 0 失败 / 0 锚点漂移 / rc=0(含 [A] 11 条)
|
|
352
|
+
python -X utf8 scripts/run_tests.py scripts → 17/17 通过,0 跳过 / rc=0
|
|
353
|
+
python -X utf8 -c "… repr(os.path.abspath(r'D:\x\aux')) …" → '\\\\.\\aux'(§4.9-②)
|
|
354
|
+
python -X utf8 -c "… 读 md_cg/datapath.py:44-69 …" → _abs_host_path 的 abspath + startswith("\\\\.\\") 判据
|
|
355
|
+
python -X utf8 - <<'PY' … 临时副本内 npm pack --dry-run --json 两次(含/不含 files 的 "skills")… PY
|
|
356
|
+
→ 1495/703 → 792/0,DELTA=703(§4.9-①)
|
|
357
|
+
python -X utf8 -c "… 从 .zcode/workflow-runs/dwfrun-b27a6016-….mjs 提取 args JSON …" → contract 3078 字符(附录 A)
|
|
358
|
+
python -X utf8 -c "… 三处递归搜 probe_prefix/probe_silent/probe_equiv/probe_del_assert/probe_green …" → 0 命中
|
|
359
|
+
git ls-files | wc -l ; git status --short → 2113;含本报告与 plans v0.2 的 A 状态
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**未跑**:`npm run gate`(串联,原因见 §4.7)、`python -X utf8 scripts/run_tests.py`(全量)、两栈容器脚本(§4.5–§4.7 来源为工作流采集);**未做**:认知图归档写活库(硬边界)。**§五的六个探针:不在本报告可达范围内,未跑、未复现**(§4.9-④)。
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## 八、读者问询逐条回应
|
|
367
|
+
|
|
368
|
+
1. **「新腿今天能拦下 `#38` 那一形(整目录未出资)吗?」** —— **不能,只能拦「点名面」**。理由(本报告读码):S1 判 `"utf8_boot.py" in shipped`(`:363`)、S2/S3 判装好目录里两个具体文件(`:381`–`:383`),**没有任何一条判据做「`files` 白名单项 ⟷ tarball 条目」的全量对账**。⇒ 若有人从 `files` 里删掉 `dsh`、`codebuddy`、`zcode`、`docs` 这类**非启动硬依赖**项,本腿**不红**(与 §1.4 的「静默形」同族)。**这是本报告主动披露的判据缺口**(§6.1-6),是否补成「白名单全量对账」属下一轮设计决策,本报告不改代码。
|
|
369
|
+
2. **「`#48` 的补丁没补上机器检查、同类再犯仍无人拦——这句解除了吗?谁保证每次都跑?」** —— **部分解除,未完全解除**。已解除的是「**没有任何机器检查**」这一条:现在有 S1–S5 五条判据 + `npm run gate` 第九腿。**未解除的是触发条件**:`.github/workflows/` 8 个 workflow **无 smoke 腿**(§4.8 实跑),容器清单也不含它(§6.1-7),故新腿**只在有人本地跑 `npm run gate`(含 `prepublishOnly`)时才生效**。⇒ **发版流程里的保证者 = `package.json` 的 `prepublishOnly`(`npm run build && npm test && npm run gate`)**,即「凡走 `npm publish` 必过」;不走 npm 发布而是直接分发 tarball / 手工装机,则无兜底。补 CI 属下一轮取舍(`rust:bookworm` 无 npm 也需一并解决)。
|
|
370
|
+
3. **「S5 的缺省面两侧谁是真源?将来工具面变动时谁先漂移?」** —— **`md_cg/mcp_server.py:1056`(`KERNEL_TOOLS`)是唯一真源**;新腿的 `DEFAULT_TOOLS`(`:63`)是**独立字面量**,目的是「不读被测方的常量也能判」——它**故意**不从 `mcp_server` 导入(否则被测面自己改口径,判据跟着飘,等于没判)。两侧的一致性由**守卫 C5** 的字面量相等断言钉住(`:159`–`:161`,只断言**腿内自洽**,不跨读 `mcp_server`)。⇒ **漂移顺序:腿先假红**(真源加了工具 → S5 实得 `['cg','stg',…]` ≠ `['cg','stg']` → 腿红,人去改 `DEFAULT_TOOLS`);这正是「判据面独立于被测面」的预期代价,**不是缺陷**。若希望「真源改了就自动同步」,需要反过来导入真源——那会牺牲判别独立性,属设计取舍。
|
|
371
|
+
4. **「新腿并链后单次耗时与网络依赖?」** —— **本报告没有该腿的耗时专项读数**(不臆造):现有数字只有 `npm install` 7.9–8.2s(采集腿)、握手 1.4–1.5s(采集腿)、修前对照八腿串联 `npm run gate` 9.1s(采集腿)。链路四段里 `npm pack`/`npm install` 是主要开销,**单次量级应在十秒级**——但这是**推断**,未实测。网络依赖:契约本身要求「不引入网络」,且本腿用 `--legacy-peer-deps` 跳过 peer;**「全程零网络」未验证**(§6.1-8)。
|
|
372
|
+
5. **「§五 的『四项 ask 指定检查』原文是哪四条?」** —— 复核所据的 ask 原文**未随转述给出**,本报告**无法还原**其四条逐字原文。可精确给出的是**契约的【验收判据】段**(附录 A 末段,共 6 条),以及复核者自列的 1–4 归类(§五)。⇒ 覆盖核对:契约 6 条判据中「新腿单独跑 rc=0」「`MDCG_GATE_SANDBOX_DIR` 分支」「定点变异自证(副本)」「守卫三处锚点 + `--mutate`」「`npm run gate` 全腿」「python 全量 + 容器双腿」在 §四均有点对点读数(来源已逐条标注),**唯有「容器双腿」与「python 全量」不是本报告跑的**。
|
|
373
|
+
6. **「六个探针脚本留没留在工作区?」** —— **本报告在三处(工作区、`%TEMP%`、`D:/program`)递归搜索,0 命中**(§4.9-④)。⇒ 它们**既不在工作区**(故与头部被测面的「2 修改 + 1 文档 + 2 新件」不矛盾),**也不在任何本报告可达的临时目录**;§五 的四组复核读数**因此不可复查**。本报告已把 §五 相应条目标注为「转述,未复核」。
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 九、本次修订(v1.0-r1)的处置明细
|
|
378
|
+
|
|
379
|
+
> 对应读者反馈的三类共 13 条。**能补证据的补、能说清的改措辞、确属误报的说明为何不改**(处置结果已落进上文各节)。
|
|
380
|
+
|
|
381
|
+
| # | 反馈(类别) | 处置 | 落点 |
|
|
382
|
+
|---|---|---|---|
|
|
383
|
+
| 1 | `abspath` 到设备路径「读不通」(unclear) | **句子事实成立、机制补全**:实跑 `abspath(r"D:\x\aux") == '\\\\.\\aux'`;补明「解析发生在 `abspath`(`GetFullPathNameW`)那一层,`_abs_host_path` 只读结果」,并引 `md_cg/datapath.py:53-68`、`:253-267`;同时**如实标注**「服务 rc=2」后半段本报告未端到端实跑 | §3.3-①、§4.9-② |
|
|
384
|
+
| 2 | 「退出码 2」两义混淆(unclear) | **新增并列对照表**:新腿 2=环境错误、守卫 2=ANCHOR-MISS、另加第三处(Python 解释器 rc=2);在两处引用点都挂了指向 | §3.4(新增)、§4.1、§4.4 |
|
|
385
|
+
| 3 | §4.4 末条 `--mutate` 归属错误(unclear) | **移出归属**:标注该条属**守卫**、非本腿;补明新腿可配面只有 `--root` 与 `MDCG_GATE_SANDBOX_DIR` | §4.4 表前引语 |
|
|
386
|
+
| 4 | §二 数据来源未交代(unclear) | **新增 §2.0**:明确 §2 来自**采集腿转述**(非 ask#1 记录,该记录不可达);表内「来源」列改为「采集腿 / 本报告复核」,可复核项逐条标出 | §2.0、§2.1 表 |
|
|
387
|
+
| 5 | 契约原文一行未列(unclear) | **新增附录 A**:`args.contract` 全文(3078 字符)+ `sites`/`guard`/`report`/`container`;并给提取命令 | 附录 A、§4.9-③ |
|
|
388
|
+
| 6 | 文件名与标题不同指、「进货门禁」无定义(unclear) | **新增 §1.0 术语**:文件名来自 `args.report`(附录 A 可核),「进货门禁」= 出厂件必须真到货;正文统一用「出货面冒烟腿」,头部加路径来处 | §1.0、头部 |
|
|
389
|
+
| 7 | 第 83 行的 `1489` 无出处(unsupported) | **删除**(该数字系前版笔误,无任何运行对应;现该处为「等价实跑」表述) | §2.1 表注、§4.3 |
|
|
390
|
+
| 8 | 「1493→790 / 704 件」自相矛盾(unsupported) | **实跑重测并替换**:本报告实跑 `1495→792`、差 **703**、`skills/` 前缀 **703**;明确「704」无支撑、**不采信**;两口径差量(703)互证 | §1.4、§2.1 腿3、§4.9-① |
|
|
391
|
+
| 9 | 「差 1」归因不可验证(unsupported) | **改时间线表**(2111/1493、2112/1494、2113/1495 三时刻 + 各自额外暂存项)并给读者可自行执行的验证命令 | §4.3 注 |
|
|
392
|
+
| 10 | 「另一会话 staged」指认无支撑(unsupported) | **降级措辞**:只陈述「处于暂存状态(`A`)、发生在本报告两次只读观测之间、非本报告所为」,**明确不作主体指认**(无证据) | §4.3 注、§6.4-17、头部 |
|
|
393
|
+
| 11 | 六个探针裸文件名、读数全转述、§7 不含(unsupported) | **补可达性检查(0 命中)**,§五 通篇加「转述,未复核」标注,§7 明列「不在可达范围、未跑」 | §4.9-④、§五、§七 |
|
|
394
|
+
| 12 | §4.7 gate 未写跑在哪个树(unsupported) | **补成立条件缺口声明**:不据该读数推断工作树未被改动;说明 `prepare`→`tsc` 会重写 `lib/`;并说明本报告改用副本内等价链路 | §4.7、§6.2-10 |
|
|
395
|
+
| 13 | 六条 nextQuestions | **新增 §八** 逐条回应(含两条「不能/未加载」的坦白:`#38` 整目录形**拦不住**、单次耗时**无读数**) | §八 |
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## 附录 A:契约原文(`args.contract`,本报告实读 `dwfrun-b27a6016-…mjs` 内联 `args` JSON)
|
|
400
|
+
|
|
401
|
+
```text
|
|
402
|
+
【目标】新增一道「出货面冒烟」发布门禁腿:把包 pack 出来、在**空沙箱**里真装、从装好的目录里真启动 MCP、真发 initialize + tools/list,并断言工具面等于文档口径的缺省面 ['cg','stg']。目的是让「仓库里在、包里不在」这一类继续漏(同类已发生两次:#38 的 scripts/ 与 hive/ 未出货、issue #48 的仓根 utf8_boot.py 未被 files 收录)。背景:issue #48 已由编排侧修好(提交 52677077,files 加 utf8_boot.py),但修完之后**仍无任何机器检查能拦住同类**。
|
|
403
|
+
|
|
404
|
+
【已由编排侧验证过的配方(照抄,不要重新探索)】
|
|
405
|
+
MCP stdio 帧格式 = **逐行 JSON-RPC**(不是 Content-Length 帧),协议 2024-11-05;仓内 test/mock_mcp.py 也是按行读。
|
|
406
|
+
链路与读数(Windows 本机,已亲验):npm pack --pack-destination <沙箱>/pack(约 3s,修后 1493 条目)→ 空目录里写 {"name":"...","private":true} 的 package.json → npm install <tgz> --no-audit --no-fund --legacy-peer-deps(约 10s,rc=0)→ 在 node_modules/@furongjun1999/dsh-memory 里跑 `python -m md_cg.mcp_server`,stdin 塞三行(initialize 含 protocolVersion 2024-11-05 与 clientInfo、notifications/initialized、tools/list)→ 实得 rc=0、1.3s、serverInfo 为 {name: mdcg-mcp, version: <package.json 的 version>}、tools 为 ['cg','stg']。
|
|
407
|
+
**必须清干净的坑**:调用者进程若带 MDCG_TOKEN / MDCG_VERIFY_KEY(本机开发 shell 就有),子进程会读到却不在沙箱凭据库里 → fail-closed 拒启、rc=3 报「令牌不存在」——那是正确行为,但会让门禁假红。故子进程环境必须剔除全部 MDCG_* 与 DEEPSEEK_* 后再注入 MDCG_ROOT=<沙箱>/memory 与 MDCG_AUX_ROOT=<沙箱>/aux(两者都指沙箱 ⇒ 全密闭,绝不碰使用者真实记忆库与 ~/.mdcg)。
|
|
408
|
+
|
|
409
|
+
【必须怎么修】
|
|
410
|
+
1. 新增 scripts/check_publish_smoke.py(跟同目录 check_publish_artifact.py / check_registry_tarball.py 同风格:纯 stdlib、argv 列表 + shell=False + 显式 UTF-8、中文判据行、退出码 0=通过)。它做上面那条链路并断言:①发货清单含仓根 utf8_boot.py(点名式断言,缺则直接红并打出「修法:files 加 utf8_boot.py」);②装好的目录里 utf8_boot.py 与 md_cg/mcp_server.py 都在;③真握手拿到 serverInfo 与 tools,且 tools **等于** ['cg','stg'](缺省面;若加了 MDCG_MCP_SURFACE 多到 33 面的口径请只测缺省面并在注释里说明);④启动 stderr 里出现策略来自**包内** data/policy.json 的证据则一并记录(可选)。
|
|
411
|
+
2. 沙箱路径:缺省 tempfile.mkdtemp(),跑完全部清理;若 env MDCG_GATE_SANDBOX_DIR 给定则使用它并**保留不删**(便于人工复核,例如指到 E:\test)——两条分支都要有读数行。
|
|
412
|
+
3. npm 解析必须复用 check_publish_artifact.py 里已有的那个单点(若它是私有函数就抽成共用,别写第二套方言):Windows 上 npm 会命中 npm.cmd,且实测 `cmd /c npm ...` 在本仓 Bash 里会打印 cmd 横幅且假绿(rc=0)——**不要用 cmd /c 包一层**。若探不到 npm,fail-closed(退出码 1)并打出为什么,不要静默 SKIP。
|
|
413
|
+
4. 接线:package.json 的 gate 脚本里加这条腿,紧跟在 check_publish_artifact 之后(位置要按语义选,别放最后)。
|
|
414
|
+
5. 文档同步:docs/mdcg/发布门禁链_v0.1.md 现在写的是八道/八条腿(它自称与 package.json 对齐),改成九道并补本条腿的说明与为何必要(同类漏两次);README 里若有门禁腿数的描述一并同步;search 一下有无其它写「八腿/八条腿/8 legs」的文档。
|
|
415
|
+
|
|
416
|
+
【不许动什么】
|
|
417
|
+
- 不改检索面与归一层(unify 相关一概不碰);不改 unify 的缺省。
|
|
418
|
+
- 不写活库、不动在役 hive serve、不动 DSH 路径与 hive/inbox.jsonl。
|
|
419
|
+
- 不加新依赖(纯 stdlib);不引入网络(--legacy-peer-deps 就是为了不拉 peer,若实测仍要触网则改为解包 tarball 后启动,并在报告里说明这个降级与理由)。
|
|
420
|
+
- 外部报告与转写本体不入库。
|
|
421
|
+
|
|
422
|
+
【验收判据(逐条给读数)】
|
|
423
|
+
- 新腿单独跑:python -X utf8 scripts/check_publish_smoke.py 得 rc=0 与完整读数(清单条目数、utf8_boot 是否在、握手 serverInfo、tools 列表、沙箱路径与是否清理)。
|
|
424
|
+
- 指定 MDCG_GATE_SANDBOX_DIR=E:\test\smoke 再跑一遍,证明覆盖分支可用且保留沙箱。
|
|
425
|
+
- **定点变异自证(关键,必须在临时副本上做,不许改真工作区)**:在副本里把 package.json 的 files 里 "utf8_boot.py" 删掉 → 本腿必须变红并点名缺件;恢复后变绿。红/绿两侧读数都要给。
|
|
426
|
+
- 新增守卫 scripts/test_publish_smoke_guard.py:断言 ①gate 脚本串里确实含这条腿 ②smoke 脚本存在且其关键断言有可定位锚点(发清单含 utf8_boot / tools 等于 cg 与 stg / 剔除 MDCG_* 三处)③用上面的定点变异证明本腿有判别力(在临时副本上);带 --mutate 或等价自证,红项数点名。
|
|
427
|
+
- npm run gate 全腿 rc=0(沙箱里 npm 可能不可 spawn,按环境报实情)。
|
|
428
|
+
- python 全量测试套件全绿;容器双腿(rust:bookworm 的 linux_verify.sh full 与 node:22-bookworm 的 verify_linux_node.sh)按脚本既有清单跑。
|
|
429
|
+
- 报告里写清:本腿**没**覆盖什么(例:不覆盖 DSH 桥侧、不覆盖真实 DSH 安装路径、不覆盖 peer 依赖解析)。
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**其余 `args` 字段**(同源实读):
|
|
433
|
+
|
|
434
|
+
```text
|
|
435
|
+
repo = D:/program/dsh-memory-main
|
|
436
|
+
defect = PKG-SMOKE-GATE
|
|
437
|
+
sites = package.json 的 scripts.gate(约 :88,现八道腿)|scripts/check_publish_artifact.py(npm 解析单点,供复用)|
|
|
438
|
+
scripts/check_registry_tarball.py(同目录风格参考)|docs/mdcg/发布门禁链_v0.1.md(八道→九道)|
|
|
439
|
+
README.md(若门禁腿数有描述)|scripts/workspace_index.py(新 scripts/ 文件不需改 ROOT_FILES,自行确认)|
|
|
440
|
+
test/mock_mcp.py(按行 JSON-RPC 的参考实现)|新增 scripts/check_publish_smoke.py 与 scripts/test_publish_smoke_guard.py
|
|
441
|
+
guard = scripts/test_publish_smoke_guard.py
|
|
442
|
+
report = docs/eval/出货面冒烟_进货门禁_v1.0.md ← 本文件路径的出处
|
|
443
|
+
container = true
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**契约 ⟷ 本报告的覆盖对照**(契约【验收判据】6 条):
|
|
447
|
+
|
|
448
|
+
| 契约判据 | 本报告落点 | 谁跑的 |
|
|
449
|
+
|---|---|---|
|
|
450
|
+
| 新腿单独跑 rc=0 + 完整读数 | §4.4 第 1 条 | 工作流采集 |
|
|
451
|
+
| `MDCG_GATE_SANDBOX_DIR=E:\test\smoke` 分支 | §4.4 第 2 条 | 工作流采集 |
|
|
452
|
+
| 定点变异自证(副本,红/绿两侧) | §4.3(B2 绿/红)+ §4.9-①(skills 变体) | **本报告实跑** |
|
|
453
|
+
| 守卫三处锚点 + `--mutate`、红项数点名 | §4.1、§4.2、§4.3 | **本报告实跑** |
|
|
454
|
+
| `npm run gate` 全腿 rc=0 | §4.7 | 工作流采集(**运行树未标注**,§6.2-10) |
|
|
455
|
+
| python 全量全绿 + 容器双腿 | §4.5、§4.6 | 工作流采集(**本报告未跑**) |
|
|
456
|
+
| 报告写清「没覆盖什么」 | §6.1 | 本报告 |
|
|
457
|
+
|
|
458
|
+
## 附录 B:不适用条件
|
|
459
|
+
|
|
460
|
+
本报告的读数**不适用于**下列查询:(a) 容器内运行本腿与新守卫的结论(该组合未跑,见 §6.2-7);(b) `MDCG_MCP_SURFACE=full` 工具面(本腿只钉缺省面,见 §6.1-4);(c) 真实 DSH 安装路径与 `dsh/` 桥侧行为(§6.1-1/2);(d) `files` 白名单里**未点名**项的出资与否(本腿无全量对账判据,见 §6.1-6 与 §八.1);(e) 工作区 `lib/` 经 `prepare` 重建后的内容漂移(本报告未触发重建,见 §4.7);(f) §五 六个探针的读数(不可定位,§4.9-④);(g) 其它文档的「九道门禁」同名表述(本条目属 `eval/出货面冒烟_进货门禁_v1.0.md`)。
|