@furongjun1999/dsh-memory 0.5.1 → 0.6.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 +588 -552
- package/codebuddy/CODEBUDDY.md +10 -10
- package/data/policy.json +27 -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/DSH/346/227/245/345/277/227/347/264/242/345/274/225v2_/345/217/202/350/200/203dsh-TUI_v1.0.md +248 -0
- package/docs/eval/DSH/346/227/245/345/277/227/347/264/242/345/274/225/346/225/210/346/236/234/351/252/214/350/257/201_v1.0.md +209 -0
- package/docs/eval/DSH/347/253/257/347/274/272/351/231/267/344/270/223/351/241/271_v1.0.md +254 -0
- 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/P1b2_/350/257/273/351/235/242/344/273/243/351/231/205/344/277/256/345/244/215_v1.0.md +124 -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/217/221/345/270/20306_/344/270/200/351/224/256/351/205/215/347/275/256/344/270/216DSH0172_v1.0.md +171 -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//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_v18.md +183 -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_v19.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_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/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 +20 -0
- 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 +12 -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 +21 -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//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//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/dsh/cordis-patch-profile-web.example.yml +35 -0
- package/lib/bridge.js +24 -2
- package/lib/cli.d.ts +3 -0
- package/lib/cli.js +66 -0
- package/lib/hooks.d.ts +31 -2
- package/lib/hooks.js +219 -16
- package/lib/init.d.ts +88 -0
- package/lib/init.js +302 -0
- 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_p0.py +1 -1
- package/md_cg/branches.py +2 -2
- package/md_cg/ccgc.py +1071 -1006
- package/md_cg/chain.py +1 -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/evidence.py +585 -582
- package/md_cg/evolution.py +17 -1
- package/md_cg/export.py +1 -1
- package/md_cg/forgetting.py +309 -13
- package/md_cg/fsutil.py +454 -8
- 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 +4152 -3818
- package/md_cg/mdcg.py +4208 -3462
- package/md_cg/mdcos.py +4491 -4137
- package/md_cg/mreview/pipeline.py +15 -1
- package/md_cg/nodefile.py +639 -575
- 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/review_cli.py +49 -4
- 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/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 +1299 -1168
- package/md_cg/tasks.py +469 -470
- 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_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_govern_directread.py +17 -4
- package/md_cg/test_h2_session_view_norm.py +233 -0
- package/md_cg/test_h4_sustain_snapshot.py +1377 -0
- package/md_cg/test_hive_ingest.py +285 -285
- package/md_cg/test_index_crossprocess_reload.py +301 -0
- 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 +513 -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_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 +166 -0
- 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_p30_maintain.py +33 -2
- package/md_cg/test_p31_insight.py +1 -0
- 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 +516 -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_cli_attribution.py +177 -0
- package/md_cg/test_review_cli_visibility.py +235 -0
- package/md_cg/test_review_conformance.py +21 -3
- package/md_cg/test_security_audit_v21.py +2 -2
- package/md_cg/test_server_version.py +67 -0
- package/md_cg/test_srcindex.py +171 -0
- package/md_cg/test_tenant_env_override_warn.py +63 -50
- package/md_cg/test_token_lowercase_form.py +315 -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/wisdom/knowledge_points.py +1 -1
- package/md_cg/writelimit.py +42 -8
- package/md_cg/writepipe.py +651 -554
- package/package.json +8 -2
- package/skills/plugin.json +1 -1
- package/src/bridge.ts +25 -2
- package/src/cli.ts +65 -0
- package/src/hooks.ts +229 -16
- package/src/init.ts +361 -0
- package/src/lib/prompt_safety.ts +88 -1
- package/zcode/AGENTS.md +10 -10
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# 蜂巢模型密钥配置面改造 v1.0
|
|
2
|
+
|
|
3
|
+
> **范围**:hive 的密钥/令牌配置面——Rust 剥离面与锚密钥链、Python 执行器端点解析、serve 运维展示面、文档与示例件。
|
|
4
|
+
> **缺陷号**:**N200**(缺陷台账正式编号,`docs/eval/缺陷挖掘_自主迭代_v23.md:124` 首次编号、`docs/eval/缺陷挖掘_自主迭代_v24.md:242` 复测仍成立;本批代码注释内标注为 **N190**——编号口径不一致,见 §六-5)。
|
|
5
|
+
> **批次**:批次69(编排批号);病根源头是批次65(提交 `3069d14b`)的 N185 env 剥离。
|
|
6
|
+
> **一句话结论**:把「一个变量干两件事」拆成三个角色——模型密钥(普通配置、默认继承给执行器)、身份锚(独立、默认不进执行器、orchestrate 例外)、子代理覆盖(可选开关)。契约 C1–C6 全部落地;全量 python 247/247、cargo 50/50、门禁 VERDICT=PASS(均为本轮实跑,见 §四;门禁为本报告落盘前实测,落盘后的 R4 时序性见 §八-8)。**两条遗留**(MCP 面锚链副本未同步、README 计数陈旧)见 §七。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 一、背景与病根(N200:一变量双角色)
|
|
11
|
+
|
|
12
|
+
### 1.1 病根陈述
|
|
13
|
+
|
|
14
|
+
`HIVE_API_KEY` 在改造前同时承担两个互不相干的角色:
|
|
15
|
+
|
|
16
|
+
| 角色 | 位置 | 生效形态 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| **锚密钥链尾**(结果完整性锚 P11 的密钥来源) | `hive/src/keyres.rs` 旧版链第三环 `env("HIVE_API_KEY")` | 谁配了模型密钥,谁就能签锚 |
|
|
19
|
+
| **LLM 网关密钥**(执行器调 chat/completions 的凭据) | `hive/exec.py` 的 `_post_chat` | 执行器干活所必需 |
|
|
20
|
+
|
|
21
|
+
缺陷台账的原始判据(`docs/eval/缺陷挖掘_自主迭代_v23.md:124-127`,F. N200,high,留档·大设计决策):一变量双角色 = **判据面与身份面混同**——「谁有权签锚」退化为「谁能调模型」;同时批次65 的 env 剥离把该键从每个执行器子进程无条件摘掉,导致 serve 派发的全部 LLM 任务确定性失败。
|
|
22
|
+
|
|
23
|
+
### 1.2 批次65 的显性回归(N185)
|
|
24
|
+
|
|
25
|
+
批次65 把 `HIVE_API_KEY` 列入 `ORCH_SECRET_ENV_KEYS` 三键、每次 `spawn_executor` **无条件** `env_remove`,且只在 `spec.orchestrate` 为真时重注身份两键——`HIVE_API_KEY` **永不重注**:
|
|
26
|
+
|
|
27
|
+
- 剥离面(旧):`hive/src/exec.rs:85-86` 三键常量;`:134-135` 无条件 `env_remove`;`:137` 起仅 orchestrate 重注。
|
|
28
|
+
- 后果(现码同位置仍可见该约束):`hive/exec.py:1405-1412` 的 `_post_chat` 经 `model_endpoint()` 取键,键为空即 `RuntimeError`(`hive/exec.py:146-151`)→ 执行器在首次 API 调用前即退。
|
|
29
|
+
- 台账证据(材料,非本轮实跑):v23 复核会话 A/B 实跑——哑 dumper 作执行器经 serve 跑,落盘 env 实测**无 `HIVE_API_KEY`**;同 spec 以仓内 `exec.py` 经 serve 跑 → `state=error`、`error="RuntimeError: HIVE_API_KEY 未设置…"`;同一 spec 带哑密钥直跑 `exec.py` → 走到网络调用(两臂唯一变量即 env 剥离)。
|
|
30
|
+
|
|
31
|
+
**结论**:标准部署下 serve 派发的全部 LLM 任务(`exec.py` 直路与 `orch.py` 编排路复用同一 `_post_chat`)在首次 API 调用前确定性落 error——**主能力全断,无需攻击者**。
|
|
32
|
+
|
|
33
|
+
### 1.3 本机实测现状(本轮只读观察)
|
|
34
|
+
|
|
35
|
+
| 观察项 | 读到的事实 | 证据 |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| 本机锚的实际来源 | `hive/config.local.json` 里 `HIVE_ORCH_TOKEN_FILE` 为**直值非空**、`HIVE_ORCH_TOKEN` 未设、`HIVE_API_KEY` 为 `{"env": "DEEPSEEK_API_KEY"}` ⇒ **锚链首环就命中身份令牌文件** | 逐键形态只读列举(未打印任何值) |
|
|
38
|
+
| 在役 serve 是否带上批次65 剥离面 | 最近三个作业均为 LLM 任务(`model=deepseek-flash`)`state=done`、`result.json` 带 `result_anchor`,创建时间 2026-09-27 14:55–14:58;而在役 `hive/target/release/hive.exe` 的构建时间为 **2026-09-26 12:44** ⇒ **运行中的二进制尚未带上剥离面** | `hive/jobs/*/status.json`、`hive/jobs/*/result.json` 只读摘要 + 二进制 mtime |
|
|
39
|
+
| 运行态 | 心跳新鲜(age ≈ 0.22s)、`workers=4`、`exec_mode=deterministic+llm` ⇒ serve 在跑,本批未动 | `hive/jobs/_serve.json` 只读 |
|
|
40
|
+
|
|
41
|
+
**故本机的真实影响是「功能回归风险」而不是已发生的密钥泄露**:
|
|
42
|
+
|
|
43
|
+
1. **锚泄露/混同面休眠**——锚密钥实际来自令牌文件,「链尾 = 模型密钥」这条混同路径在本机部署上根本没被用到;
|
|
44
|
+
2. **功能回归尚未落地**——在役二进制仍是批次65 之前的构建(LLM 任务照常 `done`),但**下一次 `--rebuild`/重启就会把「LLM 任务全断」带上线**(v23 台账同向记载:「该回归尚未落地、下次 --rebuild/重启后落地」)。
|
|
45
|
+
|
|
46
|
+
⇒ 本批的价值在于:**在该回归上线之前把契约修正掉**,而不是修一个已经发生的事故。
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 二、设计(三角色分离)
|
|
51
|
+
|
|
52
|
+
### 2.1 角色表
|
|
53
|
+
|
|
54
|
+
| 角色 | 键 | 是否默认进执行器 env? | 判据/依据 |
|
|
55
|
+
|---|---|---|---|
|
|
56
|
+
| **模型(网关)密钥**(唯一默认项) | `HIVE_API_KEY` / `HIVE_API_BASE` | **是**(默认继承) | 普通配置:执行器调模型所必需。`hive/exec.py:92-158` 的解析段;`hive/README.md:535` |
|
|
57
|
+
| **身份锚 / 身份令牌**(独立) | `HIVE_ORCH_TOKEN` / `HIVE_ORCH_TOKEN_FILE` | **否**,唯一例外 `spec.orchestrate` 真值任务条件重注 | `hive/src/exec.rs:98` 两键常量 + `:151-164`;同两键 = 锚密钥链两环 `hive/src/keyres.rs:33-52` |
|
|
58
|
+
| **子代理覆盖**(可选开关) | `HIVE_SUBAGENT_API_KEY` / `HIVE_SUBAGENT_API_BASE` | 是(普通配置) | `hive/exec.py:113-125`;`hive/orch.py:516-517` 只写布尔开关 |
|
|
59
|
+
|
|
60
|
+
### 2.2 三条设计决策
|
|
61
|
+
|
|
62
|
+
1. **模型密钥 = 唯一默认项,默认继承给执行器**。收回批次65 对 `HIVE_API_KEY` 的剥离:它从 `ORCH_SECRET_ENV_KEYS` 出表(`hive/src/exec.rs:98`),两种任务形态一致到达执行器(`hive/src/exec.rs:130-132`、`:148-150`)。
|
|
63
|
+
2. **身份锚独立且不进执行器、orchestrate 例外**。剥离判据从「键名里带不带 API/TOKEN」改为**身份**(`hive/src/exec.rs:83-97` 常量 doc 的口径陈述):执行器持身份令牌即可对任意任务自签合法锚(keyres 不可伪造性对最暴露进程失效)、或以 serve 身份认领 principal;编排任务(执行器 = `orch.py`)需要令牌派生收窄身份(`orch.py` `load_principal` fail-closed),故按 `spec.orchestrate` 条件重注,且**重注面 = 剥离面 = 同一常量**(`hive/src/exec.rs:154-164`,杜绝两处清单分叉)。
|
|
64
|
+
3. **子代理覆盖为可选开关**。spec 只承载布尔 `use_subagent_llm`,**密钥值与地址只从 serve env 读**(`hive/exec.py:92-99`、`:107-110`)——spec 会落盘、进 log/result、被编排链与读取方看见,一旦允许携带值,写 spec 者就能让执行器把任意凭据发往任意地址。半套覆盖(开关真、子代理密钥缺)= 主密钥 + 子代理网关的跨网关错配,故**整组回落主配置**(`hive/exec.py:118-125`)。
|
|
65
|
+
|
|
66
|
+
### 2.3 与 v24 裁决建议的关系(必须说清的口径选择)
|
|
67
|
+
|
|
68
|
+
`docs/eval/缺陷挖掘_自主迭代_v24.md:245-269`(5.1 N200 裁决建议)给出三案,推荐 **方案 A(新增专用变量 `HIVE_LLM_API_KEY` + 条件注入)**、次选 **方案 B(按需重注原键)**、不建议 **方案 C(短时作用域凭据)**。
|
|
69
|
+
|
|
70
|
+
**本批既不是 A 也不是 B**,而是第三条路:**让模型密钥回到批次65 之前的地位(普通配置、默认继承),同时把它从锚链尾摘掉**(消掉双角色的另一半)。
|
|
71
|
+
|
|
72
|
+
理由:① 模型密钥本来就是执行器干活的必需品,机密等级与身份锚不同——批次65 把它当身份面是判据混同;② 零新变量、零新注入判据(A 会引入「任务类型决定是否注入」的第二个判据面,B 会让剥离面按任务类型而非进程类型变化);③ 锚链收窄为身份两环后,执行器即使持有模型密钥也**无法自签锚**——「执行器不持 serve 密钥」这一不变量收敛为「执行器不持**身份**密钥」,与 `hive/src/exec.rs:83-97` 的判据陈述一致。
|
|
73
|
+
|
|
74
|
+
代价(如实):这是**契约变更**——把「`HIVE_API_KEY` 不在执行器 env」从既有契约翻转为「必须在」。三条既有断言随之同步(§三末尾逐条列明),这是本批唯一的测试期望例外。
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 三、契约 C1–C6 逐条落地情况
|
|
79
|
+
|
|
80
|
+
契约全文出自本次编排的单据(`.zcode/workflow-drafts/蜂巢模型密钥配置面改造.dwf.ts:61-66`)。每条给出落地位置(本轮读码核对的现码行号)、关键实现与结论。
|
|
81
|
+
|
|
82
|
+
### C1 · Rust 剥离面收窄为身份两键 → **落地**
|
|
83
|
+
|
|
84
|
+
| 项 | 现码 |
|
|
85
|
+
|---|---|
|
|
86
|
+
| 常量 | `hive/src/exec.rs:98` `const ORCH_SECRET_ENV_KEYS: [&str; 2] = ["HIVE_ORCH_TOKEN", "HIVE_ORCH_TOKEN_FILE"];`(旧为 `[&str; 3]` 含 `HIVE_API_KEY`) |
|
|
87
|
+
| 常量 doc 改写为身份面口径 | `hive/src/exec.rs:83-97`:剥离判据是**身份**而非「键名带不带 API/TOKEN」;并写明 `HIVE_API_KEY` 是模型(网关)密钥、属普通配置、随 serve env 默认继承、既不剥离也不需条件重注 |
|
|
88
|
+
| 剥离 | `hive/src/exec.rs:151-153` `for k in ORCH_SECRET_ENV_KEYS { cmd.env_remove(k) }` |
|
|
89
|
+
| 条件重注 | `hive/src/exec.rs:154-164` 改为遍历**同一常量**(旧为字面两键数组)⇒ 重注面 = 剥离面由同一常量保证 |
|
|
90
|
+
| spawn_executor 头注 | `hive/src/exec.rs:118-136`,末段明写 `HIVE_API_KEY` 不在剥离面、两种任务形态一致到达 |
|
|
91
|
+
| 纪律核查 | 生产代码仅此一条 `const`(`grep -n "^const \|^pub const " hive/src/exec.rs hive/src/keyres.rs` 只命中 `hive/src/exec.rs:98`);全仓 `env_remove` 仅 `hive/src/exec.rs:152` 一处(本轮实跑) |
|
|
92
|
+
|
|
93
|
+
### C2 · 锚密钥链去掉 `HIVE_API_KEY` 兜底环 → **落地(复核判 partial,根因在工作区另一文件,见 §七-1)**
|
|
94
|
+
|
|
95
|
+
| 项 | 现码 |
|
|
96
|
+
|---|---|
|
|
97
|
+
| 链收窄 | `hive/src/keyres.rs:40-42`(`HIVE_ORCH_TOKEN`)→ `:43-50`(`HIVE_ORCH_TOKEN_FILE` 读全文 strip 非空)→ `:51` `None`;全文无 `env("HIVE_API_KEY")` |
|
|
98
|
+
| 头注同步 | `hive/src/keyres.rs:1-26`:去掉兜底环的理由、诚实边界「从未配身份密钥 → 锚判据整体不启用(安全方向降级,行为 = 批次53 之前的旧产物判据)」、N143 不设公开缺省常量、**同链副本必须同步**(点名 `hive/hive_mcp/mcp_server.py::_result_anchor_key`,`:24-26`) |
|
|
99
|
+
| 诚实边界可见化(超出通道声明范围的 13 行,见下方注) | `hive/src/main.rs:189-206`(serve 启动 stderr 只列身份两环、写明 `HIVE_API_KEY` 非锚链兜底);`hive/src/scheduler.rs:574-584`(`Unverifiable` 分支的 `needs_review` reason 同口径) |
|
|
100
|
+
|
|
101
|
+
> 注:`main.rs` / `scheduler.rs` 两处用户可见文案不在「Rust 通道」声明的两个文件内(属同一条锚链口径的受影响处),改动为纯字符串 + 注释、零断言依赖(全仓无测试断言这两句)——复核已由独立复核员读码确认(C2 verdict ok 的 evidence 含该两处)。如需回退,回退面即这 13 行新增文本。
|
|
102
|
+
|
|
103
|
+
### C3 · 执行器端点解析(含子代理覆盖)→ **落地**
|
|
104
|
+
|
|
105
|
+
| 项 | 现码 |
|
|
106
|
+
|---|---|
|
|
107
|
+
| 解析段(新增) | `hive/exec.py:92-158`:`USE_SUBAGENT_LLM_KEY`、模块态 `_USE_SUBAGENT_LLM`、`_llm_switch`(`:107-110`,spec 唯一读取点且**只当布尔**)、`_endpoint_parts`(`:113-125`,值只取 `os.environ`)、`_missing_key_msg`(`:128-136`,点名该配的键、不含键值)、`model_base`(`:139-142`)、`model_endpoint`(`:145-151`,缺键 `RuntimeError`)、`_bind_llm_spec`(`:154-158`) |
|
|
108
|
+
| 出站取值 | `hive/exec.py:1405-1422`:`api_key, api_base = model_endpoint(_USE_SUBAGENT_LLM)`(`:1412`)、URL(`:1413`)、`Authorization`(`:1419`)——`_post_chat` 内唯一取值点;签名保持 `(body, timeout)`(既有定参桩 mock 面不变,`:1408-1411` 写明理由) |
|
|
109
|
+
| 两个入口绑定开关 | `hive/exec.py:1430`(`call_llm`)、`:1565`(`run_with_tools`,工具路两处 `_post_chat` 调用点共用模块态) |
|
|
110
|
+
| 配对闸口径 | `hive/exec.py:1726-1733`:`model_base(spec)` 取**生效 base**(开关真且有覆盖时即子代理 base),与实际 POST 目标同口径 |
|
|
111
|
+
| web_search 回落**逐字未动** | `hive/exec.py:982-988` 仍 `HIVE_WEB_SEARCH_KEY` → `HIVE_API_KEY`(`:984-985`),仅新增 `:980-981` 的「C3 有意不改本回落链」注释 |
|
|
112
|
+
|
|
113
|
+
### C4 · 编排派发只写布尔开关 → **落地**
|
|
114
|
+
|
|
115
|
+
- `hive/orch.py:516-517`:`if (os.environ.get("HIVE_SUBAGENT_API_KEY") or "").strip(): sub["use_subagent_llm"] = True`——紧跟 `context_budget_tokens`(`:508-510`)之后,**只写布尔**(无键值 / 无 env 名 / 无地址);env 为假(未设、空串、纯空白)时该键**不出现**(子任务继承主配置,与历史 sub 键集逐位一致)。
|
|
116
|
+
- 生效条件注释同步:`hive/orch.py:458`。
|
|
117
|
+
- 写入点唯一:`grep -rn use_subagent_llm --include=*.py` 仅 `hive/orch.py:517` 一处写;读点 `hive/exec.py:99/:107/:158`。
|
|
118
|
+
|
|
119
|
+
### C5 · 运维展示面与启动前置校验 → **落地**
|
|
120
|
+
|
|
121
|
+
| 项 | 现码 |
|
|
122
|
+
|---|---|
|
|
123
|
+
| 三角色常量表 | `hive/serve_start.py:63-85`(`MODEL_KEY` / `IDENTITY_KEYS` / `SUBAGENT_KEYS` / `LLM_DISABLED_KEY` / `_ROLES` / `_ALWAYS_SHOWN` / `_WATCH_KEYS`) |
|
|
124
|
+
| 掩码单点 | `hive/serve_start.py:88-103` `mask_secret`:至多 2 字符前缀(仅 `len > 4`)+ `len=N` + `sha256[:8]`;空值返回空串。全文件仅定义 + 调用点(`:232`) |
|
|
125
|
+
| 角色 / 到达面 | `:107-109` `role_of`;`:112-120` `reaches_executor`(身份两键 `False`,其余 `True`) |
|
|
126
|
+
| 来源三形态 | `:123-134` `_source_of`(直值 / `env:名字` / `file:路径`);`:137-150` `_raw_config`(坏配置如实报错、不 fail fast) |
|
|
127
|
+
| 判据单点 | `:154-157` `model_key_ready`;`:162-174` `llm_disabled`(真值口径沿用 `md_cg/writelimit.py:54-58` 先例);`:178-185` `_model_key_problem`(start 与展示面**同判据同文案**) |
|
|
128
|
+
| `--show-config` | `:188-259` `show_config`:`{ok, config, keys[], problems[], llm_disabled, conclusion}`,只读(无 Popen、无落盘、不探测进程),缺密钥**不拒答** |
|
|
129
|
+
| 启动前置校验 | `:443-458`:在任何 Popen(`:481`)**之前**判 `_model_key_problem(merged)` 且未声明 `llm_disabled` → 返回 `ok:False` 的「启动前置校验未通过——…」;放行时回带 `llm_disabled=true` + note(`:489-502`) |
|
|
130
|
+
| CLI 接线 | `:650-671`:`--show-config` 分派(`:658-659`)在 `--rebuild`/`--restart` 之前;`--status` 附同一份 `config_summary`(`:666-670`)——同一函数、无第二套判据 |
|
|
131
|
+
| 既有语义未动 | `_jobs_from` / `_lifecycle_jobs` 函数体零改动(本轮读码 + 守卫 ⑥ 节) |
|
|
132
|
+
|
|
133
|
+
### C6 · 文档与示例件 → **落地(复核判 partial,见 §七-3)**
|
|
134
|
+
|
|
135
|
+
- `hive/README.md`:快速开始密钥装配 `:106-121`;两条拉起路径 env 口径(含裸 serve **无**前置校验)`:174-180`;spec 字段表新增 `use_subagent_llm` 行 `:278` 与「面差异」键数表述 `:281-283`;执行器契约 env 段 `:355-360`;令牌段「身份令牌的到达面」「子任务换模型凭据(可选)」`:516-529`;env 表 `:531-552`(`:535` `HIVE_API_KEY` 明写「不再作锚密钥兜底」、`:539-540` 身份两键、`:541-543` 新增子代理两键与 `HIVE_LLM_DISABLED`、`:550` `HIVE_WEB_SEARCH_KEY` 明标「回落语义不变」);新增「密钥三角色(谁进执行器、谁是锚)」表 `:553-560` + 单命令核对段与启动前置校验说明 `:561-575`;验证章两条守卫登记 `:598-606`。
|
|
136
|
+
- `hive/config.local.example.json`:`_comment` 补「下划线键被 `load_config` 跳过」(`:2`);新增 `_note_key_roles`(`:3`)、`_note_subagent_optional`(`:6`)、`_note_llm_disabled`(`:7`)、`_note_show_config`(`:8`)、`_note_web_search_key`(`:9`)。真实键仍 5 个且原序(`HIVE_API_KEY` / `HIVE_API_BASE` / `HIVE_WEB_SEARCH_KEY` / `HIVE_EXEC_PY` / `MDCG_ROOT`),形态未动(`{"env": …}` 引用形态保留)。
|
|
137
|
+
- 跳过规则一致:`hive/serve_start.py:296-298` `if k.startswith("_"): continue`(与 `_comment` 自述一致)。
|
|
138
|
+
|
|
139
|
+
### 3.1 契约同步改动的既有断言(本批唯一允许的「改测试」例外,逐条列明)
|
|
140
|
+
|
|
141
|
+
| # | 文件:行(现码) | 旧断言 | 现断言 | 为什么必须改 |
|
|
142
|
+
|---|---|---|---|---|
|
|
143
|
+
| 1 | `hive/src/exec.rs:282-286` | `assert!(env_of(&dump, "HIVE_API_KEY").is_none())` | `assert_eq!(env_of(&dump, "HIVE_API_KEY"), Some("\"DUMMY-N185-APIKEY\""), "模型密钥未到达执行器…")` | 旧断言把「`HIVE_API_KEY` 不在执行器 env」固化为契约;C1 已明文废除该行为,保留即与 C1 直接矛盾(契约翻转,不是放宽) |
|
|
144
|
+
| 2 | `hive/src/exec.rs:298-320`(orchestrate 用例同类断言) | 同上(orchestrate 任务下 `HIVE_API_KEY` 被剥离) | 翻转为「必须到达」`Some("\"DUMMY-N185-APIKEY\"")` | 同上;且编排器派发的子任务是普通任务,剥离主键只会打断编排 |
|
|
145
|
+
| 3 | `hive/src/keyres.rs:64-121` `env_chain_priority` | `assert_eq!(resolve_key_from_env().as_deref(), Some("api-fallback"))`(`HIVE_API_KEY` 兜底) | 身份两环皆缺 → `assert_eq!(resolve_key_from_env(), None, "身份两环皆缺时 HIVE_API_KEY 不得兜底…")`(`:91-95`),并新增令牌文件不可读/内容空白两条不回落断言(`:102-107`) | C2 已把兜底环删除,旧断言断言的正是本批废除的行为 |
|
|
146
|
+
|
|
147
|
+
附带(**不改断言强度**):
|
|
148
|
+
- 两个测试函数因语义变化**改名**:`hive/src/exec.rs:262` `env_secrets_stripped_from_plain_executor` → `identity_secrets_stripped_from_plain_executor`;`:298` `orchestrate_executor_gets_identity_token_not_api_key` → `orchestrate_executor_gets_identity_token_and_model_key`(旧名含「not_api_key」在新契约下是假陈述)。
|
|
149
|
+
- 模块名 `env_secrets_tests` 与 `ENV_TEST_LOCK` **未动**(跨文件引用:`hive/src/keyres.rs:66`)。
|
|
150
|
+
- `hive/test_serve_entry.py`:⑧ 用例新增环境装配 `with mock.patch.dict(os.environ, {"HIVE_API_KEY": "DUMMY-KEY-c5-precheck-not-a-credential"})`(`:258-262`)+ 文件头新增 `from unittest import mock`(`:43`)——**只补环境装配**,⑧a/⑧b 的断言文本、期望值、判据一字未动(本轮 git diff 复核:该文件仅 10 增 1 删,无断言行变动)。
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 四、验证
|
|
155
|
+
|
|
156
|
+
### 4.1 本轮实跑的命令与结果(原样)
|
|
157
|
+
|
|
158
|
+
| # | 命令 | 结果 |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| 1 | `python -X utf8 scripts/run_tests.py --jobs 4` | `===== SUMMARY 247/247 通过,5 跳过(依赖缺失/平台不符) =====`,退出码 **0**;其中 `PASS hive.test_llm_key_resolution`、`PASS hive.test_serve_show_config`、`PASS hive.test_serve_entry` 均在列 |
|
|
161
|
+
| 2 | `cd hive && cargo test` | `test result: ok. 33 passed; 0 failed`(lib)/ `ok. 9 passed; 0 failed`(main)/ `ok. 8 passed; 0 failed`(`tests/judgment_surface.rs`,含 `result_anchor_gate`、`anchor_e2e_done_with_echo_executor`)/ `0 passed`(Doc-tests),**EXIT=0**;2 条 warning 为既有(`judgment_surface.rs` unused variable `id_tag` / `da`,该文件本批零改动——`git status --porcelain` 未列该文件) |
|
|
162
|
+
| 3 | `npm run gate` | **VERDICT=PASS**,EXIT=0(**本报告落盘前**实测;含本报告这一新增未追踪件后的复跑结果见 §八-8);其中 `[PASS] R1 凭据/密钥面;文件面=0 内容面=0`、`[PASS] R2`、`[PASS] R3`、`[PASS] R4 非追踪件面;非追踪=28,允许=28`、`[PASS] R5`、`[PASS] R6`、`[OK ] 工作区索引与仓库一致(顶层目录 20 · 追踪 2037 件)` |
|
|
163
|
+
| 4 | `python -X utf8 scripts/run_tests.py hive --jobs 4` | `===== SUMMARY 21/21 通过,0 跳过 =====` |
|
|
164
|
+
| 5 | `python -X utf8 -m hive.test_llm_key_resolution` | `结果: 22 pass / 0 fail`,rc=0(逐条 `[ok]` 计 22 条) |
|
|
165
|
+
| 6 | `python -X utf8 -m hive.test_serve_show_config` | `ALL OK: serve 配置展示面与启动前置校验守卫全绿`(逐条 `OK` 计 53 条),rc=0 |
|
|
166
|
+
| 7 | `python -X utf8 -m hive.test_serve_entry` | `ALL OK: serve 入口口径守卫全绿`(逐条 `OK` 计 53 条),rc=0 |
|
|
167
|
+
| 8 | `python -X utf8 test/hive_exec_test.py` | `6/6 全绿` |
|
|
168
|
+
| 9 | 端到端只读展示面(系统临时目录 + 哑值)<br>`python -X utf8 serve_start.py --config <临时>/config.json --show-config` | RC=0、`ok=True`、`conclusion=可拉起(模型密钥就绪)`;逐键 role / `reaches_executor` 正确(`HIVE_ORCH_TOKEN`、`HIVE_ORCH_TOKEN_FILE` → `身份令牌`/`身份锚`、`reach=False` 且 note 含「仅 spec.orchestrate 任务条件重注」;`HIVE_API_KEY` → `模型密钥`、`reach=True`;子代理两键 → `子代理覆盖`);掩码形如 `du***len=31/sha256:…`;**三枚哑值明文在整份 stdout 中零命中**(`PLAINTEXT_HITS= []`);临时目录测毕删除(复查不存在) |
|
|
169
|
+
|
|
170
|
+
### 4.2 红转绿证据
|
|
171
|
+
|
|
172
|
+
| 面 | 红(旧码 + 新断言) | 绿(新码 + 新断言) | 谁跑 |
|
|
173
|
+
|---|---|---|---|
|
|
174
|
+
| Rust C1/C2(3 条翻转断言) | 临时副本 `cargo test --lib` → `FAILED. 30 passed; 3 failed`,失败者正是三条翻转断言(错误文案:模型密钥未到达执行器 / 未到达编排器 / 身份两环皆缺时 `HIVE_API_KEY` 不得兜底) | `33 passed; 0 failed`;全量 `cargo test` 50/0 | 红= **Rust 通道(材料,临时副本,本轮我未复跑)**;绿= Rust 通道 + **本轮复跑**(4.1-#2) |
|
|
175
|
+
| 执行器守卫 `hive/test_llm_key_resolution.py`(新增 22 条) | **本轮复跑**:`git show HEAD:hive/exec.py`、`orch.py` 拷入 `mktemp -d` 后同命令传该目录 → `结果: 15 pass / 7 fail`、rc=**1**;失败项含 `G1 工具路开关为真 → 同样用子代理密钥与 base`(实际用了主键)、`H1 编排者 env 有子代理键 → sub.use_subagent_llm is True(布尔)`(`键值类型=NoneType`) | `22 pass / 0 fail`、rc=0 | 红+绿 = **本轮复跑**(红基线临时目录已 `rm -rf`,复查不存在) |
|
|
176
|
+
| 运维守卫 `hive/test_serve_show_config.py`(新增 53 条) | 旧码整面不存在:`AttributeError: module 'hive.serve_start' has no attribute 'mask_secret'`、`OK=0/FAIL=2`;行为探针:旧 `start()` 在缺模型密钥配置下**照常调用 Popen**(`popen_called=True`),`--show-config` 未分派、`--status` 无 `config_summary` | `53/53`、rc=0 | 红= ops 通道(材料,沙箱);绿= **本轮复跑**(4.1-#6) |
|
|
177
|
+
|
|
178
|
+
### 4.3 独立复核结论(材料转述 + 本轮读码/实跑确认)
|
|
179
|
+
|
|
180
|
+
| 契约 | 复核 verdict | 本轮我的核对 |
|
|
181
|
+
|---|---|---|
|
|
182
|
+
| C1 | **ok** | 读码核对 `hive/src/exec.rs:98/:151-153/:154-164`;`cargo test` 绿(4.1-#2);`^const ` 扫描仅 1 条、`env_remove` 仅 1 处(§三 C1 表) |
|
|
183
|
+
| C2 | **partial** | 链已收窄(`:33-52`)、头注含诚实边界与「同链副本」点名;判 partial 的唯一原因是**同链 Python 副本未同步**——我确认 `hive/hive_mcp/mcp_server.py:269` 仍为三键含 `HIVE_API_KEY`、`:285-292` 按三键取首个非空、`:312`/`:325-327` 据此写 `result_nonce`(见 §七-1) |
|
|
184
|
+
| C3 | **ok** | 取值口单点 `hive/exec.py:1412`、`Authorization` `:1419`;开关只当布尔 `:107-110`;web_search 回落未动 `:982-988`;守卫 22/0(本轮复跑) |
|
|
185
|
+
| C4 | **ok** | `hive/orch.py:516-517` 只写布尔;写点唯一(grep) |
|
|
186
|
+
| C5 | **ok** | 掩码单点 `:88-103`;门槛在任何 Popen 之前 `:443-458` vs `:481`;`--show-config` 分派 `:658-659`;守卫 53/0(本轮复跑)+ 本轮端到端只读实跑(4.1-#9) |
|
|
187
|
+
| C6 | **partial** | 文档条目逐条在位并与实现相符(本轮读码);判 partial 的两点为 ① 锚链「同链」措辞与工作区实况的张力(同 C2 根因)② README 计数陈旧(§七-3) |
|
|
188
|
+
|
|
189
|
+
复核会话另做的两项**对抗性核实**(材料):① `exec.py` 的密钥/base 不会从 spec 取值(读码逐处取值来源 + 实跑:spec 内塞 `api_key`/`api_base`/`use_subagent_llm` 为 dict 形态均被忽略);② `serve_start` 掩码在哑值下不输出明文(实跑)。①由守卫 F1/F2 固化,我本轮复跑守卫(22/0)覆盖;②我本轮端到端实跑独立复现(哑值明文零命中)。
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 五、验收步骤(用户怎么验)
|
|
194
|
+
|
|
195
|
+
### 5.1 只读看配置:`--show-config` 看什么
|
|
196
|
+
|
|
197
|
+
```cmd
|
|
198
|
+
:: 在 hive 目录下(或给 --config 指向你的配置)
|
|
199
|
+
python serve_start.py --show-config
|
|
200
|
+
python serve_start.py --status :: 心跳 + 任务统计 + 同一份 config_summary
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
四栏读法:
|
|
204
|
+
|
|
205
|
+
1. **`source`**——确认密钥来源是你预期的形态:`直值` / `env:<系统变量名>` / `file:<路径>`。若你期望引系统变量却看到「直值」,说明密钥被写死在配置文件里了。
|
|
206
|
+
2. **`masked`**——形式为「少量前缀 + `len=N` + `sha256:<8位指纹>`」,用来比对「是不是我期望的那把 key / 有没有被换过」。**任何情况下都不出明文**(这是单点函数 `hive/serve_start.py:88-103` 的承诺)。
|
|
207
|
+
3. **`role` 与 `reaches_executor`**——本次改造的核心验收点:
|
|
208
|
+
- `HIVE_ORCH_TOKEN` / `HIVE_ORCH_TOKEN_FILE` 必须是 `身份令牌` / `身份锚` 且 `reaches_executor=False`(note 会写「仅 spec.orchestrate 任务条件重注」);
|
|
209
|
+
- `HIVE_API_KEY` 必须是 `模型密钥` 且 `reaches_executor=True`(模型密钥是执行器干活的必需品);
|
|
210
|
+
- `HIVE_SUBAGENT_API_KEY` / `_BASE` 为 `子代理覆盖`(可选,未设也逐键列出并标 `empty`)。
|
|
211
|
+
4. **`problems` 与 `conclusion`**——缺模型密钥时会点名该配哪个键(并给出 `{"HIVE_API_KEY": {"env": "DEEPSEEK_API_KEY"}}` 这样的示例形态)或提示声明 `HIVE_LLM_DISABLED`;身份面两键皆缺时会提示「锚判据整体不启用(安全方向降级,行为=旧产物判据)」。
|
|
212
|
+
|
|
213
|
+
注意语义:`ok` 的含义是「**这份配置能拉起 serve 吗**」,故缺密钥时 `--show-config` 仍输出完整 JSON,但 `ok=false` 且 CLI 退出码为 **1**(沿用 `emit` 的既有 0/1 口径)——它是诊断面,不是失败。`--show-config` / `--status` 属只读动作:不改 env、不落盘、不探测/拉起任何进程。
|
|
214
|
+
|
|
215
|
+
### 5.2 何时生效(关键)
|
|
216
|
+
|
|
217
|
+
| 改动面 | 生效时机 | 依据 |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| **C1/C2(Rust 二进制行为:剥离面、锚密钥链)** | **必须重编译 + 重启**:`python serve_start.py --rebuild`(= stop → `cargo build --release` → start) | `hive/serve_start.py:564-571` 注释与实测记录:Windows 会锁住运行中的 `hive.exe`,`--restart` 的 stop→start 中间插不进 build,等于「重启了个旧二进制」;`--rebuild` 把三步合成原子序且 build 失败保持停止态 |
|
|
220
|
+
| C3/C4(`exec.py` / `orch.py`) | 新提交的任务即用盘上最新脚本(执行器**每任务新起进程**:`hive/src/scheduler.rs:454` → `hive/src/exec.rs:137-170`,argv=`[python, exec_py, dir]`);但**依赖 env 的部分**(`HIVE_API_KEY` / `HIVE_SUBAGENT_*`)由 serve 启动时固化(`hive/serve_start.py:481-485` `env=merged`)⇒ 改 `config.local.json` 后须 `--restart` / `--rebuild` 才进入 serve env | 读码(两条均在位) |
|
|
221
|
+
| C5(`serve_start.py`) | CLI 每次运行即用最新脚本;**启动前置校验在下次 `start`/`--restart`/`--rebuild` 时生效** | `hive/serve_start.py:443-458`、`:650-671` |
|
|
222
|
+
| C6(文档/示例件) | 即读即新 | — |
|
|
223
|
+
|
|
224
|
+
**推荐验收序列**:① `--show-config` 确认三角色来源与到达面 → ② `python serve_start.py --rebuild` → ③ 提交一个最小 LLM 任务(`hive submit`,或任一既有派发入口),确认 `state=done` 且 `result.json` 带 `result_anchor`(本机锚来自 `HIVE_ORCH_TOKEN_FILE`,锚判据应处于**启用**态)→ ④ 再 `--status` 看配置摘要与任务统计。
|
|
225
|
+
|
|
226
|
+
### 5.3 关于在役 serve
|
|
227
|
+
|
|
228
|
+
本次交付**未触碰运行态**(§八)。在役二进制若尚未带上批次65 剥离面(§1.3 判定为「尚未带上」),`--rebuild` 会在生效新契约的同时把该回归一并修掉——这是本次交付的目标,不会引入新回归。是否现在 rebuild 由用户决定。
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 六、待用户复核项
|
|
233
|
+
|
|
234
|
+
1. **`HIVE_LLM_DISABLED` 命名**(新增键)。语义:显式声明「本部署不跑 LLM」,作为启动前置校验的逃生门(只跑确定性任务的部署用它放行)。真值口径沿用仓内先例(`md_cg/writelimit.py:54-58`:去空白后非空且小写不在 `{"0","false","no"}`,见 `hive/serve_start.py:160-174`)。改名的同步面:`hive/serve_start.py:70`、`hive/README.md:543`、`hive/config.local.example.json:7`、守卫 `hive/test_serve_show_config.py` ④ 节。备选:`HIVE_NO_LLM` / `HIVE_DETERMINISTIC_ONLY`。
|
|
235
|
+
2. **`HIVE_SUBAGENT_API_KEY` / `HIVE_SUBAGENT_API_BASE` 命名**。「子代理」在本仓指 **orch 派发的子任务**(子 job),与「主代理/子代理记忆架构」文档里的角色不完全是同一所指;若担心歧义可改 `HIVE_SUBTASK_*`。同步面:`hive/exec.py:98` 的注释段、`hive/orch.py:511-517`、`hive/serve_start.py:69`、README 与 example json、守卫。
|
|
236
|
+
3. **是否还要 spec 级显式声明**。现状:C4 由 `orch.py` 按 serve env **自动**写布尔 `use_subagent_llm`(子任务无需显式声明);而 MCP 面 `SPAWN_ALLOWED_KEYS`(`hive/hive_mcp/mcp_server.py:418-423`,15 键)**不含**该键 ⇒ MCP 外部调用者目前**无法**显式声明子代理覆盖(只能由父任务经 orch 自动派生)。若需要这一面,两处需一并开:MCP 白名单 + README「面差异」表述(`hive/README.md:281-283`)。
|
|
237
|
+
4. **契约选择本身**(§2.3)。本批未采纳 v24 5.1 推荐的方案 A(新增 `HIVE_LLM_API_KEY` + 条件注入),而采纳「收回批次65 剥离 + 锚链去兜底」。若用户倾向方案 A:本批改动是它的互补前件(锚链与剥离面已收敛到身份面),但需再加新变量与「何时注入」的判据(v24 5.1 的拍板点 ①②③ 依旧存在)。
|
|
238
|
+
5. **编号口径**。代码/注释/守卫把本批标注为 **N190**,而缺陷台账的正式编号是 **N200**(`docs/eval/缺陷挖掘_自主迭代_v23.md:124` 首次编号,v24 复测仍成立)。建议归一(报告员未代改源码注释)。
|
|
239
|
+
6. **`--show-config` 缺密钥时的退出码语义**。现为 `ok=false` + 退出码 1。若希望「只读面恒退出 0」需改判据(属语义选择,实施通道已书面提出)。
|
|
240
|
+
7. **MCP 面锚链副本**(§七-1)。修法明确(把 `_RESULT_KEY_KEYS` 收窄为身份两键),但该文件不在本批四通道任何文件清单内,需指派。
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 七、未覆盖面与已知边界
|
|
245
|
+
|
|
246
|
+
1. **【跨面未落地项·建议单列修复】`hive/hive_mcp/mcp_server.py` 的锚链副本未同步**。现码:`:269` `_RESULT_KEY_KEYS = ("HIVE_ORCH_TOKEN", "HIVE_ORCH_TOKEN_FILE", "HIVE_API_KEY")`(仍含兜底环,其 docstring `:274-278` 却自称「与 rust keyres::resolve_key_from_env 同链…勿再分叉」)、`:285-292` 按三键取首个非空、`:312` 与 `:325-327` 据此写 `result_nonce`。C2 落地后 Rust 侧只剩身份两环 ⇒ **提交面与 serve 面判据分叉**:仅配 `HIVE_API_KEY` 的部署,MCP 提交的任务声明锚预期(带 `result_nonce`),而 serve 侧 `resolve_key_from_env()=None` → `hive/src/scheduler.rs:574-584` 判 `Unverifiable` → 落 `needs_review`(即「提交侧在签发、校验侧已无密钥」)。`hive/src/keyres.rs:24-26` 已书面点名该副本必须同步。**本机不受影响**(锚在令牌文件,链首环即命中),但这是同一判据面的真实分叉。
|
|
247
|
+
2. **MCP 面无法声明 `use_subagent_llm`**(同 §六-3)。
|
|
248
|
+
3. **README 计数陈旧(非本批引入,本批未刷新)**:`hive/README.md:579` 写「`cargo test`:22 项全绿(lib 17 + main 5)」,本轮实测 **50 通过**(lib 33 + main 9 + `tests/judgment_surface.rs` 8);`:582` 写「`test_serve_entry.py`:38 项全绿」,本轮实测 **53 项**;`:604-606` 登记了 `hive/test_serve_show_config.py` 但未写条数(实测 53)。刷新成本极低,但涉及本批同步改动过的两个守卫,需用户/编排确认口径后改。
|
|
249
|
+
4. **`md_cg/units.py` 的 `autostart_serve` 是 serve 拉起形态的零依赖复制件,不带 C5 的前置校验**(材料自陈属复制契约内的诚实边界)⇒ 经该路径拉起不会因缺模型密钥被拦。
|
|
250
|
+
5. **未跑(如实)**:
|
|
251
|
+
- **真实 serve 端到端(rebuild 后提交 LLM 任务实测)**——纪律禁止 rebuild/restart 在役 serve,故本批只到「代码绿 + 守卫绿 + 只读展示面实跑」;
|
|
252
|
+
- **真实网关调用、真实令牌库**(全批实验只用哑值 + 系统临时目录);
|
|
253
|
+
- **Rust 红基线**未由我复跑(避免与并行通道争用 `hive/target`),我复跑的是绿态 `cargo test` 50/0;
|
|
254
|
+
- **TS 面 `npm test` / `tsc`**(`src/` 本批零改动);
|
|
255
|
+
- **掩码「无明文」的形式化证明**(只做了哑值反查,非穷举)。
|
|
256
|
+
6. **掩码比契约更严**:`--show-config` 对**所有**键一视同仁掩码(含 `HIVE_API_BASE`、`HIVE_JOBS_DIR` 等非密钥键)⇒ 运维看不到 base 全文,只能比对指纹。这是有意的最严口径(契约只要求「绝不输出完整值」)。
|
|
257
|
+
7. **不在本批覆盖面内**:密钥轮换/吊销面、网关侧限流、短时作用域凭据(v24 5.1 方案 C)、锚判据在「零身份密钥」部署下的端到端行为实测(诚实边界已在 `hive/src/keyres.rs:15-19` 声明:判据整体不启用、行为=旧产物判据、不静默)。
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 八、纪律合规声明
|
|
262
|
+
|
|
263
|
+
1. **实验环境红线**:所有实验只在**系统临时目录 + 哑值**(哑密钥 / 哑令牌 / 哑 base,哨兵域名 `*.invalid`)进行;**未触真实令牌库、未触在役数据目录、未触 DSH 探针节点、未启动/未探测任何真实 serve、未出网**(HTTP 全程桩驱动)。
|
|
264
|
+
2. **零明文**:本报告**不含任何真实密钥/令牌/PII**——哑值一律以类别名(`DUMMY-*`)或占位符(`<路径>`、`<orch.token 路径>`)表述。本轮 `--show-config` 实跑后做明文反查:三枚哑值在整份 stdout 中**零命中**。报告与代码注释**不写本机绝对路径**(盘符 / 用户目录 / 临时目录一律中性表述)。
|
|
265
|
+
3. **未 git commit**(按纪律由编排会话负责提交);本批只改代码、测试与文档。
|
|
266
|
+
4. **未 rebuild / restart / stop 任何 serve**:只跑 `cargo test`(dev profile,不产 release 二进制)与 python 侧只读动作。在役 serve 仍活(心跳 age ≈ 0.22s、workers=4、exec_mode=deterministic+llm);我**仅只读**其心跳与最近三个作业的 status/result 摘要(用途:§1.3 的现状判定),未写、未停、未重启。
|
|
267
|
+
5. **测试期望**:本批唯一例外已在 §3.1 逐条列明(Rust 三条既有断言因契约翻转必须同步 + 两个测试函数改名(不改断言强度)+ `hive/test_serve_entry.py` ⑧ 的环境装配补齐(断言文本/期望值未动,已由 git diff 复核)。除此之外未改任何测试期望。
|
|
268
|
+
6. **实验清理**:本轮自建临时目录均在同一命令内删除并复查(`cleaned=YES`);全盘复查 `n185-*` / `n190-*` 遗留**零命中**。
|
|
269
|
+
7. **本轮我实际执行的检查**:见 §4.1 的九条(python 全量 247/247、cargo test 50/50、`npm run gate` VERDICT=PASS、hive 组 21/21、三守卫计数、`test/hive_exec_test.py` 6/6、执行器守卫红基线复跑、`--show-config` 端到端只读实跑)+ §4.3 的读码核对(含 `mcp_server.py` 副本、`SPAWN_ALLOWED_KEYS`、README 计数)。**凡材料转述而未由我本轮实跑者,§4 已逐处标注来源**。
|
|
270
|
+
8. **门禁时序性(如实,实测非推测)**:
|
|
271
|
+
- **落盘前**(本批交付状态):`npm run gate` → `VERDICT=PASS`、EXIT=0(§4.1-#3)。
|
|
272
|
+
- **落盘后**(含本报告这一新增未追踪件的状态,本轮实跑):`npm run gate` → `VERDICT=FAIL`、**EXIT=1**;唯一命中为 `[FAIL] R4 非追踪件面 命中=1;非追踪=29,允许=28` → `- docs/plans/蜂巢模型密钥配置面_v1.0.md`,其余 `R1 文件面=0 内容面=0` / `R2` / `R3` / `R5` / `R6` **全 PASS**。
|
|
273
|
+
- 原因:R4 判据为「`npm pack` 清单内非追踪件只允许 `lib/`」(`scripts/check_publish_artifact.py:537-541`、`:602-604`),本报告属 `docs/` 面新增未追踪件 ⇒ **属未追踪新件的时序性**,不是规则内容红;`git add` 入库后该件转为追踪件,R4 计数回到 28/28 即自愈。编排会话提交后请重跑门禁确认。
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## 九、自查双清单
|
|
278
|
+
|
|
279
|
+
### 清单 A · 引证复核(报告中每条关键结论 ↔ 我本轮读到/跑到的证据)
|
|
280
|
+
|
|
281
|
+
| 结论 | 证据(path:line / 命令) | 类型 |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| C1 常量收为两键、重注面=剥离面同一常量 | `hive/src/exec.rs:98`、`:151-153`、`:154-164` | 读码 |
|
|
284
|
+
| C1 无新增公开缺省密钥常量 | `grep -n "^const \|^pub const " hive/src/exec.rs hive/src/keyres.rs` → 仅 `:98` 一条;`grep -rn env_remove hive/src/*.rs` → 仅 `:152` | 实跑 |
|
|
285
|
+
| C2 链只剩两环 + None、无 `env("HIVE_API_KEY")` | `hive/src/keyres.rs:40-42`、`:43-50`、`:51` | 读码 |
|
|
286
|
+
| C2 诚实边界与「同链副本」点名 | `hive/src/keyres.rs:15-19`、`:24-26` | 读码 |
|
|
287
|
+
| C2 用户可见文案同步(超通道声明 13 行) | `hive/src/main.rs:189-206`、`hive/src/scheduler.rs:574-584` | 读码 |
|
|
288
|
+
| C3 值只来自 env、spec 只当布尔 | `hive/exec.py:107-110`、`:113-125`;出站 `:1412-1419`;守卫 F1/F2 实跑绿 | 读码 + 实跑 |
|
|
289
|
+
| C3 web_search 回落逐字未动 | `hive/exec.py:980-988` | 读码 |
|
|
290
|
+
| C4 只写布尔、写点唯一 | `hive/orch.py:516-517`;`grep -rn use_subagent_llm --include=*.py` → 写点仅 `:517` | 读码 + 实跑 |
|
|
291
|
+
| C5 掩码单点、门槛在 Popen 之前 | `hive/serve_start.py:88-103`、`:443-458` vs `:481`、`:658-659`、`:666-670` | 读码 |
|
|
292
|
+
| C5 展示面与守卫全绿 | `python -X utf8 -m hive.test_serve_show_config` → 53 OK;端到端 `--show-config` 实跑 RC=0、明文零命中 | 实跑 |
|
|
293
|
+
| C6 文档条目在位 | `hive/README.md:106-121/:174-180/:278/:281-283/:355-360/:516-529/:531-560/:562-575/:598-606`;`hive/config.local.example.json:2-9` | 读码 |
|
|
294
|
+
| 三条既有断言同步(契约翻转) | `hive/src/exec.rs:282-286`、`:298-320`、`hive/src/keyres.rs:64-121` | 读码 |
|
|
295
|
+
| `test_serve_entry.py` 只补环境装配 | `git diff hive/test_serve_entry.py`(10 增 1 删,无断言行变动) | 实跑 |
|
|
296
|
+
| 全量 python / cargo / 门禁 / hive 组 | §4.1-#1/#2/#3/#4(247/247、50/50、PASS、21/21) | 实跑 |
|
|
297
|
+
| 执行器守卫红→绿 | §4.2 第 2 行(15/7 rc=1 → 22/0 rc=0) | 实跑 |
|
|
298
|
+
| 本机锚在令牌文件、在役二进制未带剥离面 | `hive/config.local.json` 逐键形态(只读列举);`hive/jobs/*/status.json`+`result.json`(三作业 LLM done、带 `result_anchor`)+ `hive/target/release/hive.exe` mtime 2026-09-26 12:44 | 实跑(只读) |
|
|
299
|
+
| MCP 面锚链副本未同步、白名单无该键 | `hive/hive_mcp/mcp_server.py:269`、`:285-292`、`:312`、`:325-327`、`:418-423` | 读码 |
|
|
300
|
+
| README 计数陈旧 | `hive/README.md:579`、`:582` vs 实测 50 / 53 | 读码 + 实跑 |
|
|
301
|
+
| N200 编号与病根 | `docs/eval/缺陷挖掘_自主迭代_v23.md:124-127`、`docs/eval/缺陷挖掘_自主迭代_v24.md:242/:245-269` | 材料(台账) |
|
|
302
|
+
|
|
303
|
+
### 清单 B · 纪律合规自查
|
|
304
|
+
|
|
305
|
+
| 条目 | 自查结论 | 证据 |
|
|
306
|
+
|---|---|---|
|
|
307
|
+
| 查文件前先读 `WORKSPACE_INDEX.md` 按职责定位(未做全盘浏览) | **是** | 首读 `WORKSPACE_INDEX.md`;文档归域按 `docs/README.md`(`plans/` = 计划/规格) |
|
|
308
|
+
| 结论均引 `path:line` 与实测输出 | **是** | 清单 A 全覆盖;材料转述处均标「材料」 |
|
|
309
|
+
| 未实跑的检查未报告为通过 | **是** | §4.2/§4.3 逐处标注「谁跑」;§七-5 列未跑项(真实 serve E2E、真实网关、Rust 红基线、TS 面) |
|
|
310
|
+
| 实验仅在系统临时目录 + 哑值;不触真实令牌库/在役数据目录/真实 serve/DSH 节点 | **是** | 全部临时目录 + `*.invalid` 哨兵;在役 serve 仅只读心跳摘要 |
|
|
311
|
+
| 不打印密钥明文(代码/日志/测试输出/报告) | **是** | 哑值反查零命中;报告无真实凭据;`--show-config` 输出掩码 |
|
|
312
|
+
| 报告与注释不写本机绝对路径 | **是** | 盘符/用户目录/临时目录一律中性表述 |
|
|
313
|
+
| 未 `git commit` | **是** | 本轮只有文件写入,无 git 写操作 |
|
|
314
|
+
| 未 rebuild / restart 在役 serve | **是** | 只跑 `cargo test`(dev)与只读 python 动作;心跳仍新鲜 |
|
|
315
|
+
| 未改测试期望(除已列明的契约同步项) | **是** | §3.1 三条 + 两处改名 + `test_serve_entry.py` 环境装配(断言未动) |
|
|
316
|
+
| 实验后清理 | **是** | 自建临时目录 `cleaned=YES`;`n185-*`/`n190-*` 零命中 |
|
|
317
|
+
| 输出中文 | **是** | 本报告 |
|
|
318
|
+
| 无法满足处明确说出(不绕过/不伪造) | **是** | §六 七项待复核 + §七 七项边界;门禁时序性见 §八-8 |
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 附:编排侧收尾(C2 同源链同步)
|
|
323
|
+
|
|
324
|
+
本节是 **C2 的同源链收尾(C2b)**:§六-7 与 §七-1 点名「MCP 面锚链副本未同步、需指派」的那件,本轮由编排侧实施。以下结论均引 `path:line` 与本轮实跑输出;前文结论一字未改,本节只补落地、守卫与回归。
|
|
325
|
+
|
|
326
|
+
### 附-1 缺口(读码实测)
|
|
327
|
+
|
|
328
|
+
| 项 | 修补前现码 |
|
|
329
|
+
|---|---|
|
|
330
|
+
| 键集 | `hive/hive_mcp/mcp_server.py:269`(HEAD 版)`_RESULT_KEY_KEYS = ("HIVE_ORCH_TOKEN", "HIVE_ORCH_TOKEN_FILE", "HIVE_API_KEY")`——三键含**模型网关密钥** |
|
|
331
|
+
| 文案 | 同文件 HEAD 版 `:272` 生效条件注仍是「三键按序首个非空字符串胜出」;`:274-278` docstring 自述「与 rust keyres::resolve_key_from_env 同链…勿再分叉」却无 N190 收窄 |
|
|
332
|
+
| Rust 对照 | `hive/src/keyres.rs:33-52` 已是身份两环(`env("HIVE_ORCH_TOKEN")` → `env("HIVE_ORCH_TOKEN_FILE")` 读文件 → `None`),`:24-26` 头注明写「同链副本必须同步」 |
|
|
333
|
+
| 服务端同判据的提交面 | `hive/src/main.rs:323-324`:Rust 提交面 nonce 由 `resolve_key_from_env()`(两环)决定 ⇒ 与 Python 提交面(三键)**同一决策点、两套键集** |
|
|
334
|
+
|
|
335
|
+
### 附-2 后果(读码所得,逐条核对成立)
|
|
336
|
+
|
|
337
|
+
只配 `HIVE_API_KEY` 的部署:Python 提交面 `_result_anchor_key()` 非 None(`_submit` 的 `is not None` 判据)⇒ `status.json` 写入 `result_nonce`(任务声明「有锚预期」);而 Rust serve 侧 `resolve_key_from_env()` 为 None ⇒ 不注入 `HIVE_RESULT_ANCHOR`(`hive/src/scheduler.rs:758-767`;执行器契约 `hive/src/exec.rs:166`)、`classify_result` 锚校验面不启用(`hive/src/scheduler.rs:550`)⇒ **提交侧在签发、校验侧已无密钥**,任务落 `AnchorVerdict::Unverifiable` 分支(`hive/src/scheduler.rs:574`、`:641`)。
|
|
338
|
+
|
|
339
|
+
另发现**同族第二处**(红基线抓到,非推理):env 形态的 `HIVE_ORCH_TOKEN_FILE` 在旧实现里被 env 环直接 `return` 其**路径串**,其下「读文件全文 strip」段(HEAD 版 `:293-302`)**不可达**——与 Rust「该键是路径、读文件、不可读即 None」(`hive/src/keyres.rs:43-50`)判据分叉。
|
|
340
|
+
|
|
341
|
+
### 附-3 修补(键集 + 环归属 + 文案)
|
|
342
|
+
|
|
343
|
+
1. 键集收窄:`hive/hive_mcp/mcp_server.py:274` → `_RESULT_KEY_KEYS = ("HIVE_ORCH_TOKEN", "HIVE_ORCH_TOKEN_FILE")`。
|
|
344
|
+
2. 环归属:新增 `:279` `_ENV_DIRECT_KEYS = ("HIVE_ORCH_TOKEN",)`——env 直值环只吃「值本身即密钥」的键 ⇒ `:309-317` 的文件环(读全文 strip)不再是死代码;旧码按 `_RESULT_KEY_KEYS` 顺序把路径串当密钥返回。
|
|
345
|
+
3. 文案口径:`:265-273` 注释、`:282` 生效条件注、`:284-294` docstring 全部改为身份两环口径——保留「与 rust keyres::resolve_key_from_env 同链(勿再分叉第二套解析)」并补「(N190:模型密钥不再兜底)」。
|
|
346
|
+
|
|
347
|
+
**读序逐位未动**:config 键按序(`{"file":…}` 由 `load_config` 解析)→ 进程 env 直值环按序 → env `HIVE_ORCH_TOKEN_FILE` 读文件(`:300-318`);config 优先仍属 serve_start 合并语义。
|
|
348
|
+
**`_submit` 逐位未动**:nonce 决策点 `:328`(`is not None`)、status 字段集与「无密钥 → 旧格式」回退语义不变。
|
|
349
|
+
|
|
350
|
+
**诚实边界(如实点名,本批未动)**:config 形态的 `HIVE_ORCH_TOKEN_FILE` 按**直值**采信(部署实况 config 里就写路径串)——判据面只问「锚是否启用」,与 serve 侧读文件后的非空判定同结论,**仅当该路径不可读时两面分叉**;env 形态已按 Rust 语义读文件(两侧由守卫 C 组冻结)。
|
|
351
|
+
|
|
352
|
+
### 附-4 守卫与红转绿两态实测
|
|
353
|
+
|
|
354
|
+
新增 `hive/test_result_anchor_chain.py`(18 项;哑值 + 系统临时目录 + 临时「假仓」,不改工作区文件、不读写真 config / 真令牌库 / 真 jobs 池、不落真仓 `__pycache__`;mcp_server 与 serve_start 复制进临时假仓后再装载)。
|
|
355
|
+
|
|
356
|
+
| 态 | 命令 | 实测输出 |
|
|
357
|
+
|---|---|---|
|
|
358
|
+
| 红基线(`git show HEAD:hive/hive_mcp/mcp_server.py` 写临时副本) | `python -X utf8 -m hive.test_result_anchor_chain --head-baseline` | `结果:7 pass / 11 fail(红项:A1, A2, A3, A4, C1, E1, E2, E3, H1, H2, H3)`,与脚本内 `EXPECTED_RED` 逐项相等 ⇒ RC=0 |
|
|
359
|
+
| 绿态(工作区) | `python -X utf8 -m hive.test_result_anchor_chain` | `结果:18 pass / 0 fail(红项:无)` ⇒ RC=0 |
|
|
360
|
+
|
|
361
|
+
红基线里三项的实测形态(引输出要点,不含路径):`A1/A3` = 只配模型密钥时 `_result_anchor_key()` 返回哑模型密钥本身;`A2/A4` = 对应 `status.json` 键集**多出 `result_nonce`**;`C1` = env 形态返回的是令牌文件路径串而非 `strip` 后内容。
|
|
362
|
+
|
|
363
|
+
覆盖对应要求:①只配 `HIVE_API_KEY`(config / env 两形态)→ 解析为 `None` 且落盘 `status.json` **不含** `result_nonce`(旧格式);②配 `HIVE_ORCH_TOKEN`(env / config)→ 取之且写 32 位 hex nonce;③只配 `HIVE_ORCH_TOKEN_FILE`:env 形态读文件全文 strip 并写 nonce、config `{"file":…}` 形态取文件内容、config 直值路径形态冻结「非 None = 锚启用」;④身份两键皆缺但模型密钥在 → `None`;⑤键集结构 = 从 `hive/src/keyres.rs` **现场解析**的两环同名同序且不含 `HIVE_API_KEY`。
|
|
364
|
+
|
|
365
|
+
### 附-5 回归与门禁(实跑)
|
|
366
|
+
|
|
367
|
+
| 命令 | 结果 |
|
|
368
|
+
|---|---|
|
|
369
|
+
| `python -X utf8 -m hive.test_mcp_jobs_pool` | `15 pass / 0 fail`,RC=0 —— **不需要补环境装配**:该测试只走 `_jobs_dir`(A–E 组 + `:154-166` 源断言),从不调用 `_result_anchor_key` / `_submit`,其 config(`:77-83`,含 `HIVE_API_KEY` 哑值)不进入锚链判据,故改链后**未变红** |
|
|
370
|
+
| `python -X utf8 -m hive.test_serve_entry` | 53 项 OK,`ALL OK`,RC=0 |
|
|
371
|
+
| `python -X utf8 -m hive.test_llm_key_resolution` | `22 pass / 0 fail`,RC=0 |
|
|
372
|
+
| `python -X utf8 -m hive.test_serve_show_config` | 53 项 OK,`ALL OK`,RC=0 |
|
|
373
|
+
| `python -X utf8 scripts/run_tests.py hive --jobs 4` | `SUMMARY 22/22 通过,0 跳过`,RC=0(含新增守卫) |
|
|
374
|
+
| `npm run gate` | **`VERDICT=FAIL`**、退出码 **1**(本次收尾实跑,明细见下) |
|
|
375
|
+
|
|
376
|
+
**门禁结论(本次收尾实跑,如实)**:`npm run gate` 唯一命中 `[FAIL] R4 非追踪件面 命中=1;非追踪=29,允许=28` → `- docs/plans/蜂巢模型密钥配置面_v1.0.md`;`[PASS] R1 凭据/密钥面;文件面=0 内容面=0`、`R2`、`R3`、`R5`、`R6` 全 PASS,末行 `VERDICT=FAIL`、退出码 1。该命中为本报告件(`docs/` 面新增未追踪件)的**时序性**,即 §八-8 已登记的同一形态,非规则内容红;入库(`git add`)后该件转追踪件,R4 计数回到 28/28 自愈,编排会话提交后请重跑确认。本批新增的 `hive/test_result_anchor_chain.py` **未新增命中**:`package.json` 的 `files`(`lib`/`src`/`md_cg`/`skills`/`README.md`/`dsh`/`codebuddy`/`zcode`/`docs`)不含 `hive/`,而 R4 只统计 `npm pack` 清单内的非追踪件(`scripts/check_publish_artifact.py`)⇒ 未追踪数仍为 29、命中数仍为 1。
|
|
377
|
+
|
|
378
|
+
本批**未改任何测试期望**,也**未给既有测试补环境装配**(上表实测无需)。**逐条定因**:`hive/test_mcp_jobs_pool.py` 只走 `_jobs_dir`(A–E 组)与 D 组源断言,从不调用 `_result_anchor_key` / `_submit` ⇒ 其 config 里的 `HIVE_API_KEY` 哑值不进锚链判据,改链后未变红,故未补哑值;`hive/test_serve_entry.py`(53 项)、`hive/test_llm_key_resolution.py`(22 项)、`hive/test_serve_show_config.py`(53 项)均原样绿、未补任何 env。清理复核:临时目录 `n190_anchor_*` 遗留零命中;真仓 `hive/hive_mcp/__pycache__` 未被本守卫写入(本次实跑复核:该目录 8 个 `.pyc` 在守卫运行前后的 `mtime_ns`/`size`/`sha256[:12]` 三元组逐位一致)。
|
|
379
|
+
|
|
380
|
+
### 附-6 未覆盖(如实)
|
|
381
|
+
|
|
382
|
+
- 真实 serve 端到端(rebuild 后提交任务实测锚校验)——纪律禁止 rebuild/restart 在役 serve,**未跑**;
|
|
383
|
+
- 真实令牌库 / 真实网关 / 真实 config.local.json——全程哑值 + 系统临时目录,**未触**;
|
|
384
|
+
- config 直值路径形态「文件不可读」时的两面分叉——读码判定(见附-3 诚实边界),**未做端到端实测**;
|
|
385
|
+
- 本节为追加件:§六-7 与 §七-1 的原判(「跨面未落地项」/「MCP 面锚链副本未同步」)由本节落地状态**取代**,前文文本按追加原则未改。
|