dsh-loci 2.7.0 → 2.7.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/CHANGELOG.md +32 -0
- package/docs/ACCEPTANCE.md +48 -5
- package/package.json +1 -1
- package/src/host/index.js +1 -1
- package/src/mcp/store-facade.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,38 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project follows
|
|
5
5
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html) from 1.0.0.
|
|
6
6
|
|
|
7
|
+
## [2.7.1] — 2026-11-15
|
|
8
|
+
|
|
9
|
+
A correction, and a decision not to ship something.
|
|
10
|
+
|
|
11
|
+
### Corrected
|
|
12
|
+
|
|
13
|
+
2.7.0's acceptance note said the index does not scale — "arm C asked for 12/12 ids, so at 200
|
|
14
|
+
entries the model pulls the whole store". **That was wrong, and the error was in the
|
|
15
|
+
experiment.** Arm C asked **12 questions about 12 different entries**; fetching 12 bodies is
|
|
16
|
+
the correct answer to 12 questions. Concluding "it over-fetches" from `questions == fetches`
|
|
17
|
+
was a mistake in the arm's design, not a property of the product.
|
|
18
|
+
|
|
19
|
+
The fair version — **one** question against many candidates:
|
|
20
|
+
|
|
21
|
+
| Arm | Candidates | Result |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| D1 | 12 titles, 1 relevant | fetched **1**, the right one |
|
|
24
|
+
| D2 | 40 titles, 1 relevant, plus a decoy sharing the query word | fetched **1**, the right one |
|
|
25
|
+
| E | 40 titles, nothing relevant | answered `NOT_IN_MEMORY`, substituted nothing |
|
|
26
|
+
|
|
27
|
+
### Not shipped, on purpose
|
|
28
|
+
|
|
29
|
+
The work item was "make the index guide the model to converge". It already converges, so no
|
|
30
|
+
steering text was added to the footer. Two arms tested a footer that explicitly said "do not
|
|
31
|
+
batch-fetch titles that merely look plausible": it changed nothing. The footer is 83 bytes on
|
|
32
|
+
every request, and this design's entire argument is that prompt bytes are the scarce
|
|
33
|
+
resource — a sentence that changes no behaviour is pure cost.
|
|
34
|
+
|
|
35
|
+
The lesson is worth more than the fix would have been: **a measurement that counts fetches
|
|
36
|
+
against questions must keep those two numbers independent.** `docs/ACCEPTANCE.md` now carries
|
|
37
|
+
the correction in place, rather than quietly deleting the wrong claim.
|
|
38
|
+
|
|
7
39
|
## [2.7.0] — 2026-11-15
|
|
8
40
|
|
|
9
41
|
The acceptance was measuring less than it claimed. This release re-runs it properly and
|
package/docs/ACCEPTANCE.md
CHANGED
|
@@ -104,7 +104,51 @@ Each arm answered in one turn with no tools.
|
|
|
104
104
|
|---|---|---|---|
|
|
105
105
|
| **A — no memory** | the 20 questions only | **0/20** | answered `UNKNOWN` to all 20 — it abstained rather than hallucinating |
|
|
106
106
|
| **B — index only** | the 20 questions + 20 index lines whose titles *are* the facts | **20/20** | answered every question with the exact value |
|
|
107
|
-
| **C — index + fetch** | 12
|
|
107
|
+
| **C — index + fetch** | 12 questions, 12 summary titles, values only in bodies | asked for 12/12 ids | correct: 12 questions need 12 bodies — see the correction below |
|
|
108
|
+
| **D1 — one question, 12 candidates, one relevant** | one question + 12 summary titles | fetched **1/1**, the right one | no over-fetch |
|
|
109
|
+
| **D2 — one question, 40 candidates, one relevant** | one question + 40 summary titles (including a decoy sharing the word 发布) | fetched **1/1**, the right one | no over-fetch at 40 |
|
|
110
|
+
| **E — one question, 40 candidates, nothing relevant** | the same 40 titles, asking about something absent | answered `NOT_IN_MEMORY` | did not substitute a nearby entry |
|
|
111
|
+
|
|
112
|
+
### Correction: arm C did not show what it first appeared to show
|
|
113
|
+
|
|
114
|
+
The first write-up of this section said arm C revealed greedy fetching — "asked for 12/12
|
|
115
|
+
ids, did not discriminate, pulls the whole index at 200 entries". **That was wrong, and the
|
|
116
|
+
error was in the experiment, not the product.** Arm C asked **12 questions about 12
|
|
117
|
+
different entries**; fetching 12 bodies is the *correct* answer to 12 questions. Concluding
|
|
118
|
+
"it over-fetches" from `questions == fetches` was a design mistake in the arm.
|
|
119
|
+
|
|
120
|
+
D1 and D2 are the fair version: **one** question, many candidates, exactly one relevant.
|
|
121
|
+
Both fetched a single body, and D2 found it among 40 titles while ignoring a decoy that
|
|
122
|
+
shares the query word (发布说明 vs 发布窗口).
|
|
123
|
+
|
|
124
|
+
Two follow-up arms then tested whether the instruction text changed the behaviour, using a
|
|
125
|
+
footer that explicitly said "do not batch-fetch titles that merely look plausible":
|
|
126
|
+
|
|
127
|
+
| Variant | Result |
|
|
128
|
+
|---|---|
|
|
129
|
+
| current footer | fetched the needed ids |
|
|
130
|
+
| steering footer | fetched the same ids |
|
|
131
|
+
|
|
132
|
+
The instruction made no difference, so it was **not** added to the shipped footer. The
|
|
133
|
+
footer is 83 bytes on every request; a sentence that changes no behaviour is pure prompt
|
|
134
|
+
cost, and this repository's whole argument for the index shape is that prompt bytes are the
|
|
135
|
+
scarce resource.
|
|
136
|
+
|
|
137
|
+
### Decision: no code change, on purpose
|
|
138
|
+
|
|
139
|
+
The work item that produced arms C–E was "make the index guide the model to converge
|
|
140
|
+
instead of fetching everything". The evidence says it already converges:
|
|
141
|
+
|
|
142
|
+
| Situation | Behaviour |
|
|
143
|
+
|---|---|
|
|
144
|
+
| one question, one matching title among 12 | fetches that one |
|
|
145
|
+
| one question, one matching title among 40, with a decoy | fetches that one |
|
|
146
|
+
| one question, no matching title among 40 | `NOT_IN_MEMORY`, no substitute |
|
|
147
|
+
| N questions, N matching titles | fetches N — which is correct |
|
|
148
|
+
|
|
149
|
+
The only case that looked like over-fetching was the one where the experiment asked N
|
|
150
|
+
questions and counted N fetches. Shipping a fix for it would have been shipping a change
|
|
151
|
+
justified by a badly designed measurement.
|
|
108
152
|
|
|
109
153
|
Read honestly:
|
|
110
154
|
|
|
@@ -113,10 +157,9 @@ Read honestly:
|
|
|
113
157
|
- **The abstention in arm A is a good sign.** The model did not invent values; a
|
|
114
158
|
memory-less assistant says "I don't know" instead of confabulating. So the value here is
|
|
115
159
|
recall, not anti-hallucination.
|
|
116
|
-
- **
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
is a design problem, not a formatting problem.
|
|
160
|
+
- **The index scales better than the first draft of this page claimed.** One question
|
|
161
|
+
against 40 candidate titles resolved to a single body. The scaling worry this section
|
|
162
|
+
raised was the author's, not the design's.
|
|
120
163
|
|
|
121
164
|
## B.5 What §B still does not measure
|
|
122
165
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-loci",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "Layered long-term memory for DeepSeek Harness: the prompt sees only a stable index, full text is one lookup away. Bi-temporal facts, strict scope isolation, verified-only injection.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/host/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import { registerCommands } from './commands.js';
|
|
|
23
23
|
import { runDoctor } from './doctor.js';
|
|
24
24
|
|
|
25
25
|
/** Version stamped into the database and diagnostics. */
|
|
26
|
-
export const VERSION = '2.7.
|
|
26
|
+
export const VERSION = '2.7.1';
|
|
27
27
|
|
|
28
28
|
/** Optional collaborators; without them the plugin still serves tools. */
|
|
29
29
|
export const inject = ['systemPrompt', 'tools'];
|