Files
Cyrene_v2/internal/runtime/memory
AskaEth 4365224c9b docs(memory): N2 安全论证改成真实机制(位置锁 + 四类修饰)+ 两条 tripwire
应答 review round3 的 p2#1(要修的只有这一条)。

## 注释里的论证被证伪,改成真实机制

原句「封闭表里**没有承载内容的词**:没有动词、名词、量词」**字面不成立** ——
reviewer 逐表审过:情绪词表(既是核心也是后缀 token)含 `心情`(名词)、
`生气`/`害怕`/`紧张`(动词)、`压力大`(动宾);否定表里 `没有` 是动词;程度表里
`比较` 可作动词/名词;主语表里 `主人`/`我`/`他` 本身就是**指人实体**。

真正保安全的是**位置**:
1. **位置锁定** —— 主语 / 时间词只允许出现在**句首**、各至多一次 ⇒ `主人`/`我`/`你`/
   `他`/`今天` 这些指人/指时实体**在文法里永远不可能落到宾语位置**;
   (上一版黑名单正是死在这里:`会想我` 的 `我` 被当成主语剥掉)
2. **核心之后只允许「程度 / 否定 / 情绪 / 语气」四类修饰**,且它们只允许**紧跟**
   情绪核心之后 —— 核心必须先被消费,那一段在语义上只能是**情绪的修饰**
   (「心情不错」「不开心」),**装不下一个宾语短语**。

「上一版为什么错、黑名单为什么修不完」那一段**保留**(reviewer 确认该部分写得对)。

## 两条 tripwire(回应「后来人照字面加词、没有任何测试会红」)

- `TestExtractionRetention_PersistentFactsAreNeverDeferred`:**25 条**持久事实/习惯
  语料(塔给的 6 条 + reviewer 扩展的 19 条,来自 review round3 的对抗构造)逐条断言
  **绝不 defer**,钉住**语义后果**;语料是**可增长的**(新事故 → 一条回归断言)。
- `TestExtractionRetention_SuffixTableIsPinned`:把后缀表的**内容**逐 token 钉死
  (60 个 token 的 golden),任何增删立刻红。
  **为什么它比语料更接近「表的内容性质」**:语料只能覆盖**已经想到的**输入,而这张表
  是判据的全部自由度 —— 往后缀里加一个名词,表变了而语料可能一条都不碰;golden 钉的
  是「表变了」这个**事实本身**,改表必须显式改 golden ⇒ 变成一次可 review 的
  意图声明,而不是一次静默放宽。

两条一起才够:golden 钉「表变了」,语料钉「变了以后语义还对不对」。

## 变异自证(两条 tripwire 分别会红)

变异 A:往后缀语气词表加一个名词「**妈妈**」(语料里没有任何一条会因此变 defer)
```
--- FAIL: TestExtractionRetention_SuffixTableIsPinned (0.00s)
    后缀表 token 数 = 61, want 60 —— 表被改过。…
FAIL
```
⇒ golden 抓住了**语料抓不到**的改表。

变异 B:往后缀表加 `会`/`想`/`时`(看起来像无害虚词)
```
--- FAIL: TestExtractionRetention_PersistentFactsAreNeverDeferred (0.00s)
    --- FAIL: …/主人心情不好时会不好
        extract_retention_test.go:284: 持久事实 "主人心情不好时会不好" 被判成 "n2_emotion" —— 它会进临时层、7 天后被物理删除(不可逆)
    --- FAIL: …/主人不开心时会好好想
        extract_retention_test.go:284: 持久事实 "主人不开心时会好好想" 被判成 "n2_emotion" —— …
--- FAIL: TestExtractionRetention_SuffixTableIsPinned (…)  后缀表 token 数 = 63, want 60
FAIL
```
⇒ 语料把「会上线的那个后果」直接指了出来。两处变异均已还原。

验收:go build ./... + go vet ./... + go test -count=1 ./... 全绿;
TestExtractionRetention 六个用例共 69 个子例全 PASS。
2026-10-13 20:57:31 +08:00
..