@a9i5k4/dsh-auto-memory 2.5.3 → 3.0.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 +189 -7
- package/README.zh-CN.md +189 -7
- package/docs/CONTRIBUTORS.html +471 -0
- package/docs/FRONTEND-CO-CREATION.md +191 -0
- package/docs/GM53-HOMEPAGE-PROMPT.md +323 -0
- package/docs/HANDOFF-CRITERIA.md +92 -0
- package/docs/HOMEPAGE-CONTENT-FOR-GM53.md +299 -0
- package/docs/INTEGRATION-ANALYSIS.md +350 -348
- package/docs/PROMO-PROMPT-3.0.md +100 -0
- package/docs/USER-GUIDE.en.md +58 -3
- package/docs/USER-GUIDE.zh-CN.md +59 -4
- package/docs/WHITEPAPER.md +207 -0
- package/docs/internal/ACCEPT-35-LIVE.md +143 -0
- package/docs/internal/ACCEPTANCE-20260914.md +90 -0
- package/docs/internal/ARCH-REVIEW-BRIEF.md +411 -0
- package/docs/internal/ARCH-REVIEW-REQUEST.md +201 -0
- package/docs/internal/ARCH-REVIEW-ROUND2.md +169 -0
- package/docs/internal/ARCH-REVIEW-ROUND3.md +206 -0
- package/docs/internal/ARCHITECTURE-FOR-ZCODE-20260920.md +397 -0
- package/docs/internal/ART-DIRECTION-DEEPSEEK-20260920.md +351 -0
- package/docs/internal/ART-DIRECTION-WIREFRAME.md +191 -181
- package/docs/internal/ART-DIRECTION-WIREFRAME.md.bak-superseded +181 -0
- package/docs/internal/AUDIT-WB-GRAPH-FULL-20260916.md +314 -0
- package/docs/internal/BATTLE-PLAN-20260917.md +871 -0
- package/docs/internal/CONCURRENCY-INVESTIGATION-20260917.md +192 -0
- package/docs/internal/CROSS-SESSION-SEARCH-PATH-DECISION.md +72 -0
- package/docs/internal/CROSS-SESSION-SEARCH-RESEARCH.md +131 -0
- package/docs/internal/DECISIONS-20260914-SESSION.md +269 -0
- package/docs/internal/DESIGN-P1-STATE-COMMIT-20260915.md +219 -0
- package/docs/internal/DIRECTION-CHECK-WB-GRAPH-20260916.md +132 -0
- package/docs/internal/FEATURE-INVENTORY.md +531 -0
- package/docs/internal/FEEDBACK-TO-DSHAPI-RELAY.md +13 -0
- package/docs/internal/G-SERIES-EXECUTION-20260917.md +248 -0
- package/docs/internal/G3-DESIGN-20260918.md +82 -0
- package/docs/internal/G3-DISK-FORMAT-GAP-20260919.md +92 -0
- package/docs/internal/GH-DISCUSSION-5732-COMMENT.md +74 -0
- package/docs/internal/GPT-ACCEPTANCE-PROMPT-20260916.md +352 -0
- package/docs/internal/GPT-REVIEW-PROMPT.md +216 -0
- package/docs/internal/GROUP-WEBHOOK-SETUP.md +33 -0
- package/docs/internal/HANDOFF-TO-ZCODE-20260920.md +309 -0
- package/docs/internal/HERMES-DATA-VERIFICATION-20260919.md +120 -0
- package/docs/internal/HERMES-LEGACY-STATUS-20260919.md +74 -0
- package/docs/internal/ISSUE-55-58-VERIFICATION-20260918.md +175 -0
- package/docs/internal/ISSUE10-FIX-EXECUTION-20260919.md +389 -0
- package/docs/internal/ISSUE10-PLAN-20260919.md +254 -0
- package/docs/internal/ISSUE10B-FORENSICS-20260919.md +468 -0
- package/docs/internal/ISSUE9-PURGE-AND-R1-PLAIN-20260919.md +150 -0
- package/docs/internal/ISSUE9-RESIDUAL-FORENSICS-20260919.md +114 -0
- package/docs/internal/KICKOFF-P0.md +254 -0
- package/docs/internal/LESSON-TO-CANDIDATE-STATUS-20260919.md +79 -0
- package/docs/internal/MASTER-PLAN-3.0.md +411 -0
- package/docs/internal/MEMORY-GOVERNANCE-20260917.md +309 -0
- package/docs/internal/MEMORY-MUTATION-AND-INDEX-DESIGN.md +85 -0
- package/docs/internal/MERGE-CONFLICT-SCAN-20260914.md +222 -0
- package/docs/internal/PENDING-FIXES-20260916.md +289 -0
- package/docs/internal/PRE-FRONTEND-CHECKLIST-20260919.md +705 -0
- package/docs/internal/PRE-FRONTEND-CHECKLIST-20260919.md.bak-s10 +649 -0
- package/docs/internal/PROCEDURAL-MEMORY-AND-APPROVAL-DESIGN-20260918.md +225 -0
- package/docs/internal/PROGRESS-20260917.md +93 -0
- package/docs/internal/PROMPT-GAP-AUDIT-20260920.md +128 -0
- package/docs/internal/R1-DEGRADE-AUDIT-20260918.md +163 -0
- package/docs/internal/R1-READABILITY-FORENSICS-20260919.md +127 -0
- package/docs/internal/R2-EVIDENCE-DEEP-AUDIT-20260918.md +140 -0
- package/docs/internal/R3-DEGRADE-LEDGER-DESIGN-20260918.md +138 -0
- package/docs/internal/R4-RECALL-QUOTA-PLAN-20260918.md +218 -0
- package/docs/internal/RAG-KARPATHY-PROGRAM.md +229 -0
- package/docs/internal/REPORT-P0-NIGHTLY.md +212 -0
- package/docs/internal/REPORT-P5-ACCEPTANCE.md +31 -0
- package/docs/internal/REPORT-WB-GRAPH-NIGHTLY.md +153 -0
- package/docs/internal/RESUME-20260918.md +171 -0
- package/docs/internal/RESUME-20260919.md +104 -0
- package/docs/internal/REVIEW-WB-GRAPH-SELF.md +81 -0
- package/docs/internal/RHINELAB-TO-DEEPSEEK-FEASIBILITY.md +198 -0
- package/docs/internal/ROADMAP-20260917-WEEK.md +439 -0
- package/docs/internal/ROADMAP.md +106 -0
- package/docs/internal/RUN-P0-NIGHTLY.md +227 -0
- package/docs/internal/S10-CONSTRUCTION-HANDOFF-20260917.md +185 -0
- package/docs/internal/S10-GAP-INVENTORY-20260917.md +239 -0
- package/docs/internal/S10-GAPS-PLAIN-20260917.md +125 -0
- package/docs/internal/SEMANTIC-ARCHITECTURE-SPEC.md +360 -0
- package/docs/internal/SESSION-FILE-REPAIR-PROTOCOL.md +90 -0
- package/docs/internal/T6-EXECUTION-20260920.md +130 -0
- package/docs/internal/TELEMETRY-EFFECT-REPORT-DESIGN-20260918.md +146 -0
- package/docs/internal/THESIS-GAP-ANALYSIS-20260918.md +89 -0
- package/docs/internal/THESIS-OUTLINE-20260918.md +147 -0
- package/docs/internal/THREE-LAYER-CONTRACT.md +219 -0
- package/docs/internal/TODO-BACKLOG.md +263 -142
- package/docs/internal/TODO-GRAPH.html +715 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260914-v2 +493 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-alsfix +710 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-p1 +710 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-p6a-rev +703 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260915-wshint +710 -0
- package/docs/internal/TODO-GRAPH.html.bak-20260916-batch +715 -0
- package/docs/internal/UPSTREAM-ISSUE-PR-TRIAGE-20260919.md +297 -0
- package/docs/internal/UPSTREAM-ISSUES-3RD-AUDIT-20260920.md +104 -0
- package/docs/internal/WB-FORMAT-CONVENTION.md +112 -0
- package/docs/internal/WB-GRAPH-DECISIONS-20260914.md +71 -0
- package/docs/internal/reviews/CLAIM-VERIFICATION-20260914.md +56 -0
- package/docs/internal/reviews/PLAN-gpt6astra-round2-20260914.md +787 -0
- package/docs/internal/reviews/REVIEW-gpt6astra-20260914.md +112 -0
- package/docs/internal/reviews/ROUND3-REVIEW-INTEGRATION-20260914.md +230 -0
- package/docs/prompts/M8-3-enable-verify.md +49 -49
- package/docs/screenshots/promo/promo-0-banner-v3.png +0 -0
- package/lib/acceptance.js +71 -0
- package/lib/activation-host.js +153 -18
- package/lib/activation-inbox.js +25 -7
- package/lib/board-mode.js +30 -0
- package/lib/client.js +1758 -90
- package/lib/config-io.js +156 -0
- package/lib/context-bridge.js +5 -2
- package/lib/context-host.js +86 -15
- package/lib/degrade.js +385 -0
- package/lib/dsh-home.js +143 -0
- package/lib/engine-identity.js +149 -0
- package/lib/engine-switch.js +247 -0
- package/lib/episodic-store.js +63 -12
- package/lib/evidence-store.js +10 -3
- package/lib/fact-store.js +22 -3
- package/lib/fs-retry.js +46 -0
- package/lib/index-sync.js +13 -1
- package/lib/index.js +3446 -263
- package/lib/intent-clean-safe.js +258 -0
- package/lib/intent-clean.js +12 -16
- package/lib/l0-extract.js +478 -149
- package/lib/l0-index-sync.js +195 -0
- package/lib/l0-index.js +349 -239
- package/lib/ledger-criteria.js +142 -0
- package/lib/m4-corpus.js +8 -2
- package/lib/m7-index-sync-host.js +73 -5
- package/lib/m7-wire.js +3 -3
- package/lib/memory-anchor.js +56 -1
- package/lib/memory-envelope.js +257 -0
- package/lib/memory-hub.js +138 -13
- package/lib/memory-index.js +4 -2
- package/lib/memory-mutation.js +246 -0
- package/lib/memory-writer.js +204 -24
- package/lib/note-status-apply.js +118 -0
- package/lib/note-status.js +196 -0
- package/lib/procedure-observation.js +48 -0
- package/lib/procedure-store.js +118 -20
- package/lib/python-setup.js +1 -1
- package/lib/python-sidecar-client.js +29 -3
- package/lib/recall-fusion.js +83 -12
- package/lib/rerank-host.js +160 -0
- package/lib/rules-edit.js +159 -0
- package/lib/rules-layer.js +261 -0
- package/lib/semantic-decide.js +41 -8
- package/lib/semantic-js.js +66 -6
- package/lib/shadow-host.js +3 -5
- package/lib/shadow-retrieval.js +3 -3
- package/lib/skill-export-host.js +153 -0
- package/lib/skill-export.js +239 -0
- package/lib/state-commit.js +245 -0
- package/lib/storage-manage.js +6 -0
- package/lib/subagent-gc.js +4 -8
- package/lib/temporal-parse.js +191 -159
- package/lib/tier-layer-inject.js +650 -0
- package/lib/tier0-catalog.js +735 -0
- package/lib/water-window.js +263 -186
- package/lib/wb-contract.js +691 -0
- package/lib/wb-sidecar.js +890 -0
- package/lib/ws-overview-rank.js +2 -2
- package/package.json +1 -1
- package/python/m7_embedding_v1.py +5 -5
- package/python/worker_semantic_v1.py +17 -6
- package/python/worker_v1.py +38 -4
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# R1 · 长期记忆可读性 · 取证报告(2026-09-19)
|
|
2
|
+
|
|
3
|
+
> **本文件回答 R1 的待答问题一(取证)与问题三(归因)。**
|
|
4
|
+
> 方法:`artifacts/_probe-r1-readability.mjs`(可重跑),对两份真实记忆文件做**无预设**的六类缺陷量化。
|
|
5
|
+
> **不声称已解决**——修法属问题四,需用户拍板。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 0. 结论先行(三句话)
|
|
10
|
+
|
|
11
|
+
1. **可读性差的主因在「写入/整理侧」,不在「渲染侧」** —— 空行、重复标题、缺主语都是**文件本身**的属性。
|
|
12
|
+
2. **但渲染侧确有一处独立的、结构性的可读性缺陷**:注入文本**保留了对人无意义的 `<!-- memory:mem_<32hex> -->` 锚点注释**,且**每条各自带一个 `## <日期>`**,导致同一天出现 N 个重复日期标题。
|
|
13
|
+
3. **⇒ 修法是两个方向各自独立的改法**(写入侧结构模板 + 渲染侧呈现),**不是一个**。这正是 R1 问题三要分清的。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. 取证数据(真实文件,可复跑)
|
|
18
|
+
|
|
19
|
+
| 指标 | 用户级 `~/.dsh/memory/MEMORY.md` | 项目 `.../workspaces/--D--dsh-auto-memory--/MEMORY.md` |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| 体量 | 13,160 字符 / 290 行 | 23,693 字符 / 444 行 |
|
|
22
|
+
| **开头连续空行** | 3 行 | **50 行** ← ★ **打开即空白** |
|
|
23
|
+
| ≥5 行空行块 | 0 处 | 1 处(第 1–50 行) |
|
|
24
|
+
| **空行占比** | 92/290 = **32%** | 165/444 = **37%** |
|
|
25
|
+
| `## ` 段数 | 55 | 27 |
|
|
26
|
+
| **纯日期标题重复** | **15 种**(`2026-08-19`×5、`2026-08-16`×4、`2026-08-17`×3…) | **2 种**(`2026-09-18`×**19**、`2026-09-19`×5) |
|
|
27
|
+
| 缺主语(以标识符/文件名/编号开头) | 0/40 = 0% | **10/66 = 15%** |
|
|
28
|
+
| 过短或无完整句 | 10/40 = 25% | 20/66 = **30%** |
|
|
29
|
+
| 术语密度 ≥1.2/20 字 | 5/40 = 13% | 9/66 = 14% |
|
|
30
|
+
| 单条含 ≥3 分号 | 1 条 | 1 条 |
|
|
31
|
+
|
|
32
|
+
### 典型样本(逐字取自真机)
|
|
33
|
+
|
|
34
|
+
**A. 缺主语**(读者不知「谁」):
|
|
35
|
+
```
|
|
36
|
+
M1 契约行渲染设计定案:不新建独立文件(那会新增状态源,违反 S10.4「不建状态机」)…
|
|
37
|
+
`lib/tier0-catalog-pre.js`:新增 `TIER0_ANCHOR_ID_RE = /^mem_[0-9a-f]…
|
|
38
|
+
isRetrievablePre 只对**未知值** fail-closed(防未来新增枚举时静默放行)。
|
|
39
|
+
```
|
|
40
|
+
⇒ 这三条**都对**,但读者要先知道「M1 是什么」「这个文件在项目里干什么」才能读懂。
|
|
41
|
+
**缺的不是信息,是入口**:一句话说明「这是什么、为什么有这条」。
|
|
42
|
+
|
|
43
|
+
**B. 无背景**(只有结论):
|
|
44
|
+
```
|
|
45
|
+
本轮无新增跨项目通用规则。
|
|
46
|
+
无
|
|
47
|
+
无
|
|
48
|
+
```
|
|
49
|
+
⇒ 这类**空转条目**在用户级笔记里占了相当比例(25% 过短),它们不承载信息却占版面。
|
|
50
|
+
|
|
51
|
+
**C. 结构污染**:
|
|
52
|
+
项目笔记**前 50 行纯空行**;两份文件空行都占三分之一 ⇒ 人工翻阅时大量「翻页无内容」。
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 2. 归因(R1 问题三)
|
|
57
|
+
|
|
58
|
+
### 2.1 主因:写入/整理侧(占绝大多数症状)
|
|
59
|
+
|
|
60
|
+
| 症状 | 归属 | 证据 |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| 开头 50 行空行 | **整理侧** | 归档/折叠后未回收空占位(体积从大变小,行号槽位留下) |
|
|
63
|
+
| 同日 N 个重复日期标题 | **写入/整理侧** | 每次 append 都新起一个 `## <日期>`(见 §3 渲染样本) |
|
|
64
|
+
| 空转条目「无」「本轮无新增」 | **写入侧** | 模型在无内容时仍写一条 |
|
|
65
|
+
| 缺主语 / 堆术语 / 无完整句 | **写入侧** | 条目语体无约束(本仓记忆纪律已要求「客观陈述」,但**未要求「自解释」**) |
|
|
66
|
+
|
|
67
|
+
### 2.2 次因:渲染侧(独立且真实,但症状不同)
|
|
68
|
+
|
|
69
|
+
**从本会话系统提示逐字摘录**(这是模型实际收到的样子):
|
|
70
|
+
```
|
|
71
|
+
[项目长期笔记 …\MEMORY.md]
|
|
72
|
+
<!-- memory:mem_cbd99fb31f5045e29ccef19f2eb94615 -->
|
|
73
|
+
## 2026-09-18
|
|
74
|
+
- M1 契约行渲染设计定案:…
|
|
75
|
+
<!-- memory:mem_c0e799eb1cfa4247949733b481a9bece -->
|
|
76
|
+
## 2026-09-18
|
|
77
|
+
- 本仓降级纪律(长期):…
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**三个可读性问题(渲染侧独有)**:
|
|
81
|
+
1. **`<!-- memory:mem_<32hex> -->` 直接进正文** —— 这是给**系统**用的锚点 ID,**对人类读者零信息量**,却每两条占一行;
|
|
82
|
+
2. **每条前各带一个 `## <日期>`** —— 同一天被切成 N 段(项目笔记 `2026-09-18` 出现 **19 次**);
|
|
83
|
+
3. **超长内容被截断**(本会话可见 `…(截断,完整内容用 memory_recall_pre 或 GUI 面板)`)—— 属**有意的预算控制**,不算缺陷,但用户读到的确实不是全貌。
|
|
84
|
+
|
|
85
|
+
⇒ **渲染侧的修法是独立的**:锚点可改为不可见/尾注;日期可合并为「同日分组」。
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 3. 判据建议(R1 问题二,供拍板时参考)
|
|
90
|
+
|
|
91
|
+
一条「好读的记忆」应满足(可验收):
|
|
92
|
+
1. **一句话可答「这是什么」** —— 条目首句必须是自解释的完整句(不是标识符开头);
|
|
93
|
+
2. **有适用范围** —— 说清「在哪个项目/哪一层用」;
|
|
94
|
+
3. **结论与来源可分离** —— 来源(路径/行号/commit)可折叠或后置;
|
|
95
|
+
4. **不依赖隐藏上下文** —— 不需要读者先知道 M1/R4/G3 是什么。
|
|
96
|
+
|
|
97
|
+
**可自动化验收的候选探针**(本报告脚本已实现前三条):
|
|
98
|
+
- 开头空行 = 0、空行占比 < 15%
|
|
99
|
+
- 同日重复 `## ` 标题 = 0(或渲染时合并)
|
|
100
|
+
- 缺主语条目占比 < 5%
|
|
101
|
+
- 空转条目(「无」「无新增」)占比 = 0
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 4. 待用户拍板(问题四 · 修法)
|
|
106
|
+
|
|
107
|
+
| # | 方案 | 改哪里 | 成本 | 影响面 |
|
|
108
|
+
|---|---|---|---|---|
|
|
109
|
+
| **A** | **写入侧结构模板**:强制条目自解释(首句完整句 + 可选「适用范围」) | `index.js` 写侧提示 + 整理器 | 低 | 新条目变好;**旧条目不变**(除非批量重写) |
|
|
110
|
+
| **B** | **渲染侧呈现**:隐藏锚点注释、同日合并标题、清理空行 | `tier0-catalog-pre.js` / 注入渲染 | 低 | 立刻改善**已存在的**条目观感 |
|
|
111
|
+
| **C** | **整理侧清理**:压缩空行、合并同日段、删空转条目 | 整理器(`maintain`/折叠) | 中 | 一次性改善存量;需防误删 |
|
|
112
|
+
| **D** | 检索侧逐条摘要句 | 检索侧 | 高 | 需模型调用,成本最高 |
|
|
113
|
+
|
|
114
|
+
**Agent 倾向(供参考,不作结论)**:**B + C 先做**(立竿见影且不动写入语义),**A 随后**(防新增)。
|
|
115
|
+
理由:B/C 不改变任何记忆**内容**,只改呈现与排版 ⇒ 风险最低、可回退;A 属写入语义变更,按本仓纪律**需用户拍板**。
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 5. 与 ⑪(skill 导出)的关系
|
|
120
|
+
|
|
121
|
+
⑪ 的导出物是给人/给模型读的 `SKILL.md`。
|
|
122
|
+
**若 ⑩ 的 A 方案落地,⑪ 的导出模板可直接复用同一套「自解释条目」判据** ⇒ 两项有复用价值,但**互不阻塞**。
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
**取证脚本**:`artifacts/_probe-r1-readability.mjs`(可重跑,零依赖)
|
|
127
|
+
**本报告不修改任何代码或记忆内容**,仅取证。
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# R2 · 静默降级深查报告(evidence 读写不对称)
|
|
2
|
+
|
|
3
|
+
> 2026-09-18 · 承接 `R1-DEGRADE-AUDIT-20260918.md`
|
|
4
|
+
> 探针:`artifacts/_probe-r2-evidence.mjs`
|
|
5
|
+
> 状态:**根因已定位到代码级**;用户侧触发条件**未复现**(本机无法重放),列明待确认项
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 0. 一句话结论
|
|
10
|
+
|
|
11
|
+
**读侧无条件扫描 + 写侧有条件写入 ⇒ 对满足「写入条件永不成立」的用户,每次 recall 都必然 ENOENT 且静默降级。**
|
|
12
|
+
|
|
13
|
+
**关键新发现**:**正确的守卫函数 `evidenceRootExists()` 已经存在,却没有用在读侧守卫上** ——
|
|
14
|
+
它只被 `:785` 的**展示统计**(`durableEventsOnDisk`)使用。**这是「有正确工具但没接到该接的地方」。**
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. 读侧:确认无守卫(附行号)
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// index.js:5889-5897
|
|
22
|
+
const evDir = path.join(dshHome(), 'memory', 'evidence-pre', 'events') // :5891
|
|
23
|
+
const agg = aggregateEvidenceEventsPre(scanEvidenceEventsPre({
|
|
24
|
+
listFiles: () => readdirSync(evDir).filter((x) => x.endsWith('.jsonl')), // :5893 ← 无条件
|
|
25
|
+
readFile: (name) => readFileSync(path.join(evDir, name), 'utf8'), // :5894
|
|
26
|
+
}, {}))
|
|
27
|
+
} catch (eImp) { try { diag('evidence-agg 降级为中性(impMap 空): ' + ...) } catch (_) {} } // :5897
|
|
28
|
+
```
|
|
29
|
+
- **无 `existsSync` 前置**;目录不存在 ⇒ `readdirSync` 抛 ENOENT ⇒ catch ⇒ `impMap` 空
|
|
30
|
+
- 后果:`computeImportancePre` 全体中性(0.5)⇒ dense 臂因子恒 0.75 ⇒ **importance 加权对该用户完全无效**
|
|
31
|
+
|
|
32
|
+
**★ 同时存在的正确守卫(未被用于此处)**:
|
|
33
|
+
```js
|
|
34
|
+
// context-host-pre.js:167-170
|
|
35
|
+
function evidenceRootExists() {
|
|
36
|
+
const p = path.join(dshHome(), 'memory', 'evidence-pre')
|
|
37
|
+
try { return existsSync(p) } catch (_) { return false }
|
|
38
|
+
}
|
|
39
|
+
// 唯一调用点 :785(展示用)
|
|
40
|
+
// durableEventsOnDisk: evidenceRootExists() ? storeFor().loadEvents().events.length : 0,
|
|
41
|
+
```
|
|
42
|
+
⇒ **同一文件里既有正确守卫、又知道要防目录不存在,却没把它用到读侧**。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 2. 写侧:确认「有条件」(附行号)
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// context-host-pre.js:709-717
|
|
50
|
+
async function persistEvidence(list) {
|
|
51
|
+
if (!list.length) return // ← 条件1:列表非空
|
|
52
|
+
const st = storeFor()
|
|
53
|
+
for (const ev of list) { const r = await st.append(ev) ... }
|
|
54
|
+
```
|
|
55
|
+
```js
|
|
56
|
+
// evidence-store-pre.js:109-130
|
|
57
|
+
async append(evidence, opts = {}) {
|
|
58
|
+
...
|
|
59
|
+
mkdirSync(this.eventsDir, { recursive: true }) // :126 ← 懒建:只在首次成功 append 时创建
|
|
60
|
+
appendFileSync(path.join(this.eventsDir, fname), line + '\n', 'utf8')
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**两个调用点都带内容前置条件**:
|
|
65
|
+
| 位置 | 函数 | 前置条件(读源码所得) |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `:653` | `emitTextEvidence`(`:614`) | 需 `cites`/`corrections`/`attributed` 至少一类非空;`attributed` 还需 P9a 归因命中 |
|
|
68
|
+
| `:699` | 覆盖观察(`observeToolResult` 链路) | 需 `ok=true` **且** `resultPreview` 含**完整 memoryId token** **且**该 token 在**当前授权 corpus** 中,且 coverage>0 |
|
|
69
|
+
|
|
70
|
+
**接线本身完整**:`index.js:8531` 无条件 `createContextHost({ engine })`;
|
|
71
|
+
`:9223` 每次工具结果都调 `observeToolResult`;`:1702` 每次 segment 都调 `onToolResult`。
|
|
72
|
+
⇒ **不是"没接线",而是"接了线但内容条件永不满足"**。
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 3. 本机 vs 用户侧(硬证据对照)
|
|
77
|
+
|
|
78
|
+
| | 本机(开发机) | 用户侧(`C:\Users\Administrator\`) |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `evidence-pre/events/` | **存在,21 个文件**,09-18 仍在写 | **不存在** ⇒ 从未成功 append |
|
|
81
|
+
| 推测原因 | 长期有会话活动 ⇒ 内容条件被满足过 | 新装 / 用法未触发任一条件 |
|
|
82
|
+
| 表现 | 无报错 | **每次 recall 都 ENOENT** + 用户可感知功能异常 |
|
|
83
|
+
|
|
84
|
+
**★ 路径不是拼错**:`release.mjs:93` 有 `['memory/evidence-pre','memory/evidence']`(发布版重命名)
|
|
85
|
+
⇒ 用户报的 `evidence\events` 是**发布版正确路径**。
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 4. 缺陷定性
|
|
90
|
+
|
|
91
|
+
**不是「设计内降级」,是「读写不对称」**:
|
|
92
|
+
|
|
93
|
+
| 侧 | 契约应是 | 实际是 |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| 写 | 有内容才写;目录**可不存在** | ✅ 懒建,符合预期 |
|
|
96
|
+
| 读 | 目录可能不存在 ⇒ **必须先判存在** | ❌ **无条件扫描** |
|
|
97
|
+
|
|
98
|
+
⇒ **两侧对"目录可能不存在"这一事实没有共识**。写侧把"不存在"当正常态(懒建),
|
|
99
|
+
读侧把"不存在"当异常(抛 ENOENT)。**这是契约缺口,不是容错不足。**
|
|
100
|
+
|
|
101
|
+
与 M8/M9 同族:**功能存在、代码在跑、输入永远为空**。
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 5. 修法(候选,待用户批准后实施)
|
|
106
|
+
|
|
107
|
+
| 方案 | 内容 | 评价 |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| **E-1** | 读侧加守卫:`existsSync(evDir)` 为假 ⇒ **静默返回空**(不报错、不计降级) | ✅ 消除噪音与异常开销;**与写侧契约对齐** |
|
|
110
|
+
| **E-2** | 写侧改为**注册期确定性建目录** | ⚠️ 需先确认是否该让所有用户都建(**未验证**) |
|
|
111
|
+
| **E-3** | 走 R3 留痕:把「importance 恒中性(因无证据事件)」变成**可见状态** | ✅ 让"这条臂没在工作"可查 |
|
|
112
|
+
|
|
113
|
+
**倾向 E-1 + E-3**:
|
|
114
|
+
- E-1 是**契约对齐**(读侧承认"目录可不存在"),非补丁
|
|
115
|
+
- E-3 满足 R3 判据(这属**预期外失败**还是**预期内分支**?
|
|
116
|
+
⇒ 判定为**预期内分支**:无证据事件是合法状态,**不该报错**;但**"这条臂未生效"应当可见**)
|
|
117
|
+
|
|
118
|
+
**E-2 暂缓**:为何该用户从未触发写入**未查清**(内容条件依赖真实用法,本机无法重放)。
|
|
119
|
+
在未查清前改写入时机有风险(可能改变既有用户的数据行为)。
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 6. 待确认(未下结论,不得当结论用)
|
|
124
|
+
|
|
125
|
+
1. **用户侧内容条件为何永不满足?** 三个候选,**均未验证**:
|
|
126
|
+
(a) 新装无历史 ⇒ `corpus` 为空 ⇒ memoryId token 匹配不上
|
|
127
|
+
(b) 用法不触发(纯对话、无工具结果引用记忆)
|
|
128
|
+
(c) 其他配置/版本差异
|
|
129
|
+
⇒ 需用户侧配置或复现步骤;**本机无法重放**。
|
|
130
|
+
2. `evidence` 与 `evidence-pre` 两套目录在发布版是否都存活?
|
|
131
|
+
⇒ 本机只有 `evidence-pre`(无 `evidence`);`release.mjs:169` 有文件重命名映射。
|
|
132
|
+
(**待查**:发布版是否也把目录名一并改掉,即用户侧应是 `evidence` 而非 `evidence-pre` —— 报障路径显示是 `evidence`,**与重命名一致**。)
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 7. 对后续的影响
|
|
137
|
+
|
|
138
|
+
- **R3 留痕层的判据在此得到实例**:E-1 属「预期内分支」(静默、不留痕);
|
|
139
|
+
但**"importance 臂整体未生效"应作为状态可见**(E-3)。
|
|
140
|
+
- **优先级**:本项不阻塞 M2.5b(layer 臂);但**建议与 R3 同批**,因为留痕层正好覆盖它。
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# R3 · 降级留痕层 设计定稿(待批准)
|
|
2
|
+
|
|
3
|
+
> 2026-09-18 · 上游:`R1-DEGRADE-AUDIT-20260918.md`、`R2-EVIDENCE-DEEP-AUDIT-20260918.md`、`BATTLE-PLAN-20260917.md §3.6`
|
|
4
|
+
> **状态:设计待用户批准,尚未写代码**
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 0. 一句话目标
|
|
9
|
+
|
|
10
|
+
**让「某条臂静默失效」从"用户只感到检索不太对"变成"可查询的状态"。**
|
|
11
|
+
不是消灭降级(fail-soft 是对的),而是**让降级可见**。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. 核心判据(R1/R2 已得出,这里是设计前提)
|
|
16
|
+
|
|
17
|
+
**必须区分两类,绝不能一律报:**
|
|
18
|
+
|
|
19
|
+
| 类别 | 定义 | 实例 | 处置 |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| **预期内分支** | 该状态是**合法业务状态** | 无证据事件(R2-E1)、查询无时间表达(`tr=null`) | **静默,不报** |
|
|
22
|
+
| **预期外失败** | 该状态**不该发生** | 引擎抛错、目录 ENOENT、worker 拒绝 | **留痕** |
|
|
23
|
+
|
|
24
|
+
**若一律报** ⇒ 每次 recall 都会刷"无时间臂"(因为绝大多数查询不含时间表达)⇒ **噪音淹没信号**。
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. 形态选择(三选一,我推荐 A)
|
|
29
|
+
|
|
30
|
+
| | 方案 | 评价 |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| **A** | **内存环形缓冲 + 状态文件**:`degrade()` 写内存(有界 N 条)+ **定时/按需 flush 到一个 JSON 状态文件**;面板读该文件 | ✅ **零新增常驻状态机**(符合 S10.4);面板与宿主解耦,不要求宿主常驻 |
|
|
33
|
+
| B | 纯内存 + debugView 暴露 | ❌ 宿主重启即丢;用户报障后无法回看 |
|
|
34
|
+
| C | 每次降级直接写日志文件 | ❌ 高频写盘 + 与既有 diag 重复 |
|
|
35
|
+
|
|
36
|
+
**推荐 A 的理由**:本项目已有同类先例 —— `.dsh/memory/` 下的状态文件(如 `evidence-pre/`、`l0-index-*.json`)
|
|
37
|
+
都是**可查询的磁盘状态**。留痕层应复用这个范式,而不是新造一个状态机。
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 3. 接口设计
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
// lib/degrade-pre.js(新文件,纯函数 + 一个有界收集器)
|
|
45
|
+
export function createDegradeSinkPre({ now, cap = 200 })
|
|
46
|
+
→ {
|
|
47
|
+
record(kind, reason, detail) // kind: 'semantic-arm' | 'evidence-arm' | 'temporal-arm' | 'l0-sync' | ...
|
|
48
|
+
snapshot() // 返回当前缓冲(含 counts + 最近 N 条)
|
|
49
|
+
counts() // { kind: n } 便于断言
|
|
50
|
+
reset()
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**纪律(写进代码注释与套件)**:
|
|
55
|
+
1. **只记录、不阻断** —— `record()` 内部整体 try/catch,任何异常都被吞掉
|
|
56
|
+
2. **不得因留痕失败而二次失败** —— 留痕自身 fail-soft 到静默(这是 R3 的元规则)
|
|
57
|
+
3. **有界** —— cap=200 + 每 kind 计数(防内存增长)
|
|
58
|
+
4. **不含原文** —— 只存 kind/reason/时间/计数,**隐私边界与既有 diag 一致**
|
|
59
|
+
5. **不新增配置键用于开关** —— 默认开启(这是观测面,不是业务功能)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 4. 接线点(最小集,先接 4 条臂)
|
|
64
|
+
|
|
65
|
+
| 位置 | 现有代码 | 改为 |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `index.js:5877` | `catch (eBest) { diag('recall 语义臂择优降级…') }` | `+ sink.record('semantic-arm', ...)` |
|
|
68
|
+
| `index.js`(evidence 段) | `catch (eImp) { diag('evidence-agg 降级…') }` | `+ sink.record('evidence-arm', ...)` |
|
|
69
|
+
| `index.js:5908` | `catch (eTr) { diag('temporal-parse 降级…') }` | **不动**(预期内分支) |
|
|
70
|
+
| `index.js:8795` | `catch (e) { diag('l0-index sync 降级…') }` | `+ sink.record('l0-sync', ...)` |
|
|
71
|
+
|
|
72
|
+
**注意 `:5908` 不动** —— 这是判据的实际应用:无时间表达是**正常路径**,记它只会制造噪音。
|
|
73
|
+
**但**:若 `parseTemporalQueryPre` **本身抛错**(而非返回 null),那是预期外 ⇒ 应当记。
|
|
74
|
+
⇒ 需在实现时**把"返回 null"与"抛错"分开**(当前两者混在同一个 catch 里,这本身也是个小缺陷)。
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 5. 可见性(面板/状态文件)
|
|
79
|
+
|
|
80
|
+
**产出物**:`<dshHome>/memory/degrade-pre/latest.json`
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"schemaVersion": 1,
|
|
84
|
+
"updatedAt": "2026-09-18T20:10:00+08:00",
|
|
85
|
+
"counts": { "semantic-arm": 3, "evidence-arm": 0, "l0-sync": 1 },
|
|
86
|
+
"recent": [ { "kind": "semantic-arm", "reason": "...", "at": "..." } ]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**E-3 落地方式**:额外记录一条**臂健康快照**(不是降级,是状态):
|
|
91
|
+
```json
|
|
92
|
+
"arms": { "semantic": "active", "evidence": "no-input", "temporal": "on-demand", "l0Sync": "ok" }
|
|
93
|
+
```
|
|
94
|
+
⇒ 这样用户/面板能直接看到「**evidence 臂 = no-input**」,
|
|
95
|
+
而不是靠"每次 recall 都 ENOENT"来推断。
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 6. 与既有机制的边界(防重复建设)
|
|
100
|
+
|
|
101
|
+
| 已有 | 关系 |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `diag()` | **保留**。diag 是**过程日志**(滚动、即时);degrade 是**状态**(可查询、可聚合)。两者互补,不替代 |
|
|
104
|
+
| `_lastIndexDegrade`(index.js:5015 提到) | **需先查清**它是否已是一个同类机制 ⇒ 若是,R3 应**并入**而非新建(避免第二个状态源) |
|
|
105
|
+
| 白板 lint「只读+留痕」 | **同源纪律**:lint 只读不写盘但留痕;degrade 同理 |
|
|
106
|
+
| S10.4「不建状态机」 | ✅ 本设计是**观测面**,不参与业务判断 |
|
|
107
|
+
|
|
108
|
+
**★ 建前必做(已完成 2026-09-18 20:05)**:查 `_lastIndexDegrade` 与 `debugView()`,确认不重复造轮子。
|
|
109
|
+
|
|
110
|
+
**前置检查结论(已证实无需并入,可新建)**:
|
|
111
|
+
|
|
112
|
+
| 查什么 | 实证结果 | 判定 |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `_lastIndexDegrade` | `context-host-pre.js:112` `let lastIndexDegrade = null` + `:373` 赋值 —— 是 **单值兼容投影**(供旧读取方),**非收集器** | ❌ 不是同类机制 |
|
|
115
|
+
| `debugView()` | 存在于 7 个 host(shadow/context/activation/activation-inbox/index-sync/rerank/python-sink),各返回**本域局部状态** | ❌ 非跨臂统一台账 |
|
|
116
|
+
| `createDegrade*` / `recordDegrade` 等 | 全仓 grep **零命中** | ✅ 无重复 |
|
|
117
|
+
|
|
118
|
+
⇒ **R3 是新建,与既有机制互补**:
|
|
119
|
+
- `diag()` = **过程日志**(滚动、即时、人读)
|
|
120
|
+
- `debugView()` = **各域局部状态**(分散、按 host)
|
|
121
|
+
- `degrade` = **跨臂统一台账**(聚合、可查询、面向"哪条臂失效了")
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 7. 验收
|
|
126
|
+
|
|
127
|
+
1. 新增套件 `smoke-test-r3-degrade-pre.mjs`:接口契约 / fail-soft / 有界 / 隐私 / 计数正确
|
|
128
|
+
2. **变异演示**:故意在 `catch` 里抛错 ⇒ 断言**主流程不受影响**(留痕自身 fail-soft 生效)
|
|
129
|
+
3. 断言 `:5908`(无时间表达)**不产生留痕**(判据的正确性)
|
|
130
|
+
4. 全量回归维持 **PASS 115+ / FAIL 0**
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 8. 待用户拍板的三个点
|
|
135
|
+
|
|
136
|
+
1. **形态 A(内存+状态文件)是否认可?** 还是希望纯面板内存(B)?
|
|
137
|
+
2. **状态文件位置**:`<dshHome>/memory/degrade-pre/latest.json` 是否合适?
|
|
138
|
+
3. **是否同意"**先查 `_lastIndexDegrade` 再动手**"作为硬前置**?
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# R4 · 检索区分度与配额治理(2026-09-18 用户批准立项)
|
|
2
|
+
|
|
3
|
+
> **来源**:用户 2026-09-18 对话中提出的三个真实痛点 + 一处实测 bug。
|
|
4
|
+
> **用户原话**:
|
|
5
|
+
> - 「现在其实还是区分度有点问题,更加有含金量的结论和每一次都有的日志会混在一起。在 memory recall(记忆唤起)的时候,有什么好的处理方式吗?」
|
|
6
|
+
> - 「配合这个问题也困扰我很久。有的时候配额太少,效果完全没有,或者有些大条目可能就被过滤掉了,一点用都没有;有的时候配额多了,我又怕浪费 token」
|
|
7
|
+
> - 「我尝试把其中一个固定额度加大成两倍的时候,还遇到了一个锁死的问题。所以现在确实需要整一整额度的问题了。不过,确实得基于长期的观察,科学的(测量),不能拍脑子。」
|
|
8
|
+
> **归口**:本节独立于 L/M/S 执行顺序(不参与层级冻结),但**用户已批准纳入作战计划**。
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 0. 一句话
|
|
13
|
+
|
|
14
|
+
**结论与流水在检索里区分度不足** —— 语义臂内部完全不分层,融合层的层次优势(≈0.001)被流水层的数量优势(本机 449 vs 16)淹没。同时,**配额系统存在一个已确认的「锁死」缺陷**(见 §3),必须一并治理。
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. 实测证据(本次勘查,附行号)
|
|
19
|
+
|
|
20
|
+
### 1.1 语义臂内部完全不分层
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
index.js:6048-6057 corpus 收集:所有来源**平铺**进一个数组(layer 字段存了但没用)
|
|
24
|
+
index.js:6068 filter(sc >= minScore) ← 只看分数
|
|
25
|
+
index.js:6069 sort((a, b) => b[1] - a[1]) ← ★ 纯分数倒序,不看 layer
|
|
26
|
+
index.js:6070 slice(0, max(2, limit))
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 1.2 检索输出**不显示 layer**
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
index.js:6093 out.push('· ' + s.label + ' [' + s.id8 + '] ×' + s.score.toFixed(2) + ' ' + s.l0)
|
|
33
|
+
index.js:5977 out.push('· [' + c.id + '] ×' + sc + fr + ' ' + reason + ' ' + label + ' — ' + l0)
|
|
34
|
+
```
|
|
35
|
+
⇒ 模型看到的两个 `MEMORY.md`(结论)与三个 `2026-09-xx.md`(流水)**视觉上完全同级**。
|
|
36
|
+
|
|
37
|
+
### 1.3 层次优势被数量优势碾压
|
|
38
|
+
|
|
39
|
+
| 层 | rank 1 时的 RRF 贡献 | 本机语料量 |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| project(结论) | `1/(60+1)` = 0.01639 | **16 条** |
|
|
42
|
+
| log(流水) | `1/(60+5)` = 0.01538 | **449 条** |
|
|
43
|
+
|
|
44
|
+
差距 **0.001**,而流水数量是结论的 **28 倍**。⇒ 结论在检索中几乎必然被淹没。
|
|
45
|
+
|
|
46
|
+
### 1.4 ★ 但这个能力**注入侧早就有了**(可直接复用)
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
tier0-catalog-pre.js:391 TIER0_QUOTA_DEFAULTS = {
|
|
50
|
+
projectRatio: 0.6,
|
|
51
|
+
floorRatio: 0.1,
|
|
52
|
+
projectLayer: 'project',
|
|
53
|
+
floorLayers: ['whiteboard', 'user'],
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
其 docblock 原话点明了同一个问题:「语料实测 77 块把 800 token 全占,whiteboard/user/log 一条都进不来,**分层退化成单层**」。
|
|
57
|
+
|
|
58
|
+
⇒ **注入侧已解决,检索侧没有。** 这是本项工作的核心不对称。
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 2. 三个方案(用户已批准"可以加进作战计划")
|
|
63
|
+
|
|
64
|
+
### ★ 方案 A:作废条目**返回但显式标记** + 指向最新结论
|
|
65
|
+
|
|
66
|
+
**现状**:`index.js:5838` `if (!isCurrentPre(it)) continue` ⇒ 作废条目**被完全跳过**,模型不知道它存在过,也不知道有过"此路不通"的教训。
|
|
67
|
+
|
|
68
|
+
**改为**:
|
|
69
|
+
```
|
|
70
|
+
✗ [已作废] MEMORY.md [a1b2c3d4] — 旧结论:方案用 A 实现
|
|
71
|
+
↳ 已被取代,最新结论见 mem_x9y8z7w6
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**关键前置**:需要 `supersededBy` 指针字段(记录"被谁取代")。
|
|
75
|
+
- 现状:`status` 只有三值,**没有指向后继的字段**
|
|
76
|
+
- 建议:G3 写 `superseded` 时**顺便记下取代者 id**
|
|
77
|
+
- ⚠️ **待确认**:这是否违反 S10.4「不新建状态源」?
|
|
78
|
+
(**倾向不算** —— 它是 `status` 的伴生属性,与 `status` 同级;但需用户/文档明确)
|
|
79
|
+
|
|
80
|
+
### ★ 方案 B:检索结果**分层展示**(用户:「分层显示可以先做」)
|
|
81
|
+
|
|
82
|
+
**不改排序**,只改**呈现**:
|
|
83
|
+
```
|
|
84
|
+
【结论层 · 项目笔记/用户级】
|
|
85
|
+
· MEMORY.md [e5f6g7h8] ×0.79 项目铁律:写入前必须备份
|
|
86
|
+
· MEMORY.md [m3n4o5p6] ×0.77 架构决策:语义臂可降级
|
|
87
|
+
|
|
88
|
+
【流水层 · 每日日志】
|
|
89
|
+
· 2026-09-18.md [a1b2c3d4] ×0.82 今天修了个 bug
|
|
90
|
+
```
|
|
91
|
+
**零排序风险** —— 直接解决"看不见层次"的问题。**建议先做这个。**
|
|
92
|
+
|
|
93
|
+
### ★ 方案 C:检索侧**层次保底配额**(用户:「单独评估」)
|
|
94
|
+
|
|
95
|
+
复用注入侧 `TIER0_QUOTA_DEFAULTS` 的思路:语义臂输出时给 project/whiteboard/user **保底条数**,即使分数低也保证露面。
|
|
96
|
+
|
|
97
|
+
⚠️ **会改变排序结果** ⇒ 必须单独评估、单独验证。
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 3. ★ 「锁死」缺陷(用户实测踩到,本次定位到代码级)
|
|
102
|
+
|
|
103
|
+
**用户原话**:「我尝试把其中一个固定额度加大成两倍的时候,还遇到了一个锁死的问题。」
|
|
104
|
+
|
|
105
|
+
### 机制(附行号)
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
:4621 capacityLimit(layer) 读 userCapacityChars/noteCapacityChars,<500 视为脏值回落默认
|
|
109
|
+
:4655 ensureBudget 超限 → 进入整理循环(最多 3 轮)
|
|
110
|
+
:4744 const allowFold = !(last && now - last < COMPACT_THROTTLE_MS)
|
|
111
|
+
:227 COMPACT_THROTTLE_MS = 10 * 60 * 1000 ← ★ 10 分钟节流
|
|
112
|
+
:4799 / :4917 return { ok: false, reason: 'no-removable' }
|
|
113
|
+
:4832 this._lastCompactAt[layer] = Date.now() ← 整理过一次就上锁 10 分钟
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### ⛔ 本节的「节流锁死」推断已被实测证伪(2026-09-18 23:15 更正)
|
|
117
|
+
|
|
118
|
+
> **下面从"锁死的三步成因"起的整段分析作废,保留仅为记录推断过程。**
|
|
119
|
+
> 复现证据见 `artifacts/_probe-budget-lockup.mjs`(抽取生产方法体真实执行,10/0)与
|
|
120
|
+
> `tests/smoke/smoke-test-r4-budget-lockup-pre.mjs`(25/25)。
|
|
121
|
+
|
|
122
|
+
**证伪的三条硬证据**:
|
|
123
|
+
|
|
124
|
+
1. **`reason:'throttled'` 是死分支** —— 全仓 grep 仅有 6 处命中,其中**没有任何生产者**,
|
|
125
|
+
只有 `budgetRefusalTextPre` 里的文案。既然没有代码路径返回它,"被 throttled 拒绝"不可能发生。
|
|
126
|
+
2. **节流只挡 AI 折叠、不挡整条归档** —— `compactLayer` 的注释(`:4742` 附近)即如此声明;
|
|
127
|
+
实测「整理一次 → 10 分钟窗口内第二次写入」**成功**,不存在 10 分钟锁。
|
|
128
|
+
3. **真缺陷在别处,且是 legacy 路径(出厂默认走这条)**,两处:
|
|
129
|
+
- **`keepBudget` 口径用错变量**:旧式 `Math.max(COMPACT_PROTECT_RECENT_CHARS, limit - deficit - 1)`
|
|
130
|
+
展开即 `2*limit − curChars − add − 1` ⇒ **保留目标随额度单调递增**(方向反了),
|
|
131
|
+
且把保护窗口从**软**下限变成**硬**下限 ⇒ 额度落进死亡区间时被拒、**更小和更大的额度却能写** = **非单调**。
|
|
132
|
+
修为 `Math.max(0, curChars - deficit - 1)`。
|
|
133
|
+
- **回写量护栏缺失**:「AI 不可用」分支把刚归档的老段落**原样写回**主文件
|
|
134
|
+
(实测 `[compacted] note: 1729 -> 1730 chars`,不降反升)⇒ **归档发生了、空间却没腾出来**
|
|
135
|
+
⇒ 三轮后返回 `still-over-capacity`。补上锚点路径同款护栏。
|
|
136
|
+
|
|
137
|
+
**为什么原推断看起来很合理**:`:4832` 确实在成功路径上无条件打 `_lastCompactAt` 时间戳,
|
|
138
|
+
`compactLayer` 也真的读了 `allowFold` —— 但那个标志**只决定"要不要再跑一次昂贵的 AI 折叠"**,
|
|
139
|
+
与"能不能写入"无关。**教训(可复用):看到时间戳 + 节流常量,不等于看到拒绝路径;
|
|
140
|
+
判断一个 reason 是否是活分支,grep 生产者而不是读消费者文案。**
|
|
141
|
+
|
|
142
|
+
### (已作废)原推断:锁死的三步成因
|
|
143
|
+
|
|
144
|
+
1. ~~用户调大配额 ⇒ 但文件里已有内容不变 ⇒ 本不该再拒绝~~
|
|
145
|
+
2. ~~若仍超限 ⇒ 触发整理~~
|
|
146
|
+
3. ~~整理成功一次后上锁 ⇒ 10 分钟内任何再写入都被 `throttled` 拒绝~~
|
|
147
|
+
|
|
148
|
+
### (已作废)原推断:更隐蔽的一层
|
|
149
|
+
|
|
150
|
+
~~`:4689` `still-over-capacity` 时 10 分钟锁同样生效 ⇒ "没腾出空间"与"节流中"叠加。~~
|
|
151
|
+
**实际成因**:是回写护栏缺失(见上),与节流无关。
|
|
152
|
+
|
|
153
|
+
### 待办 → 已全部完成(2026-09-18)
|
|
154
|
+
|
|
155
|
+
- [x] **复现**:已写探针与套件,**推翻了原假设**(不是 throttled,是 keepBudget 口径 + 缺护栏)
|
|
156
|
+
- [x] **判定**:判定为**缺陷**(非设计),且是**默认可达、用户可见**的缺陷
|
|
157
|
+
- [x] **修复**:`keepBudget` 修为 `max(0, curChars - deficit - 1)` + 补回写护栏
|
|
158
|
+
- [x] **验收**:套件 25/25 · 变异 5/5 真红 · SHA256 逐字节还原 · 全量回归 PASS 121
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 4. 配额调优:用户要的「科学测量」而非拍脑袋
|
|
163
|
+
|
|
164
|
+
**用户原话**:「确实得基于长期的观察,科学的(测量),不能拍脑子。」
|
|
165
|
+
|
|
166
|
+
### 现状:配额是**静态配置**,没有测量回路
|
|
167
|
+
|
|
168
|
+
| 键 | 默认 | 作用 |
|
|
169
|
+
|---|---|---|
|
|
170
|
+
| `injectBudgetChars` | 8000 | 每轮注入总预算(**与容量上限是两回事**,见 `:296` docblock) |
|
|
171
|
+
| `tier0MaxTokens` | 400 | Tier-0 目录 token 上限 |
|
|
172
|
+
| `tier0BudgetShare` | 0.25 | 目录占总预算比例 |
|
|
173
|
+
| `noteCapacityChars` / `userCapacityChars` | 24000 | **文件本体**容量(M9 刚调过) |
|
|
174
|
+
|
|
175
|
+
### 已有的观测面(可复用,不新建状态源)
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
index.js:6537 budgets: (() => { ... }) ← debugInfo 已暴露
|
|
179
|
+
index.js:5099 state.tier0Meta = { tokens, items, candidates, dropped, perLayer }
|
|
180
|
+
index.js:5040 const budgetChars = Math.max(Number(cfg.injectBudgetChars) || 1600, 400)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**`tier0Meta` 已含 `candidates / dropped / perLayer`** ⇒ **"因为配额被丢掉多少条"这个数据已经在采集了**,只是没被用来调参。
|
|
184
|
+
|
|
185
|
+
### 建议的测量闭环(不新建状态源,复用 degrade 台账)
|
|
186
|
+
|
|
187
|
+
1. **采集**:每轮把 `tier0Meta.dropped / perLayer` 追加到 degrade 台账(已有落盘通道)
|
|
188
|
+
2. **观察**:面板展示「近 N 轮各层 dropped 趋势」
|
|
189
|
+
3. **判定**:某层**长期 dropped > 0** ⇒ 配额偏小;**长期 dropped = 0 且远未用满** ⇒ 配额偏大、浪费 token
|
|
190
|
+
4. **再调整**:按观察结果改默认值,**不拍脑袋**
|
|
191
|
+
|
|
192
|
+
> **与 R3 降级台账同源**:degrade 台账本来就是「跨轮可查询的观测面」,配额测量是它的第二个消费者(第一个是降级事件)。**零新建状态源。**
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 5. 优先级与依赖
|
|
197
|
+
|
|
198
|
+
| 项 | 风险 | 依赖 | 建议顺序 |
|
|
199
|
+
|---|---|---|---|
|
|
200
|
+
| **B 分层展示** | 极低(只改呈现) | 无 | **第 1** |
|
|
201
|
+
| **降级留痕补齐**(py→C2→词法每一跳) | 低 | 无 | **第 1**(与 B 同批) |
|
|
202
|
+
| **§3 锁死复现 + 修复** | 中 | 需先写复现套件 | **第 2** |
|
|
203
|
+
| **§4 配额测量闭环** | 低(只采集) | 复用 degrade 台账 | **第 2** |
|
|
204
|
+
| **A 作废标记 + supersededBy** | 中 | G3 实施后 | **第 3**(随 G3) |
|
|
205
|
+
| **C 层次保底配额** | 高(改排序) | 需 A/B 先跑出数据 | **第 4**(单独评估) |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 6. 与既有工作的关系
|
|
210
|
+
|
|
211
|
+
- **G3**(结论层状态写入):A 方案依赖 G3 写 `supersededBy` ⇒ **两者合并实施**
|
|
212
|
+
- **R3 降级台账**:§4 配额测量复用其通道;降级留痕补齐也是 R3 的收尾
|
|
213
|
+
- **M2.5b 层次臂**:本项是它的直接延续 —— 层次臂"只能放大已有优势",而 **C 方案是"给结论保底露面"**,二者互补
|
|
214
|
+
- **S10.4**:全项**不新建状态源**(A 的 `supersededBy` 需确认边界)
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
*本文档为专项立项,执行细节并入 BATTLE-PLAN 的 R 系列。*
|