refactor(memory): M45 裁决 D —— temporal 位撤出判定,只保留观测
按 r1 复审裁决 D:这一位先只做观测,`resolveRetention` 不许读它。理由(实测):
无条件 one_off ⇒ temp 会当天删 21 条长期约定;只放开 N6 位置判据能翻的 13 条
逐条是约定、而复审点名的三条目标行 0/3 救得了。在「模型真实标签分布」这份证据
缺位时不该做 7 天后物理删的不可逆决定。
撤接线(结论集逐字回到 M45 之前):
- retention.go:resolveRetention 不再读 item.Temporal;与之对比 dev base
(af61b8c)本文件**只有注释差异**,规则与判定入口逐字未变。
- extract_retention.go:judgeExtractionRetention 签名回退单参;删除
judgeRetentionTimepointWide 与 n6_timepoint_wide 规则码。与 dev base 对比
**同样只有注释差异** ⇒ 「结论集 = 不含 temporal 的那个集合」是结构性的,
不是靠调用点记得别传。
- 连带取消初版的 durable / recurring ⇒ long(零影响必须是双向的)。
保留观测面(一律未动):迁移 0027 的列、自举前滚、提取器的 temporal 产出、
prompt 枚举、闭集与 normalizeTemporal、store_temporal.go 的校验/编码。
另外把 prompt 里「标成 one_off 会让它进临时层、到期消失」这句**撤接线后已是假话**
改成中性标注说明 —— 否则会诱导模型避开 one_off,观测数据直接被污染。
测试:
- TestTemporalBitDoesNotAffectRetention —— 4 类语料 × 5 个取值,(档位,规则码)
与未分型逐字相同(核心正断言);
- TestTemporalOneOffDoesNotMakeAnythingTemporary / ...DoesNotRescueRuleHitRows
—— 零影响的双向点名;
- TestTemporalIsStillRecorded —— one_off 的约定行仍落 temporal='one_off' 而档位
long、expires 空(观测在、判定不动);
- TestTemporalDoesNotTouchExplicitTierOrRestrictedSource —— 人工入口与受限来源不变。
变异实测:把 `if item.Temporal == TemporalOneOff { return temp }` 插回
resolveRetention ⇒ 上述四条用例全红(FAIL 输出已贴给塔),恢复后全绿。
IngestRuleVersion 保持 d3.5,注释改准为「记录 temporal 信号,但不参与判定」
(留痕面变了:库里多了「模型当时标了什么」这一维,回退会让新旧留痕混在一起)。
P2 三条保留:store.go 500 行(拆 store_temporal.go)、temporal.go 头注('' 的口径
+ 两次被否的接线方案 + 接线前必须看的那两条统计 SQL)、报告语境段。
回归:go build ./... + go vet ./... 全绿;memory/db 包测试全绿;memory -race
38.2s 全绿。
This commit is contained in:
1 parent
3b9ae3f918
commit
c7c0294a16
11 files changed
+280
-551
No files matched your search
@@ -18,14 +18,6 @@ import (
|
||||
// **不进灰区**(于是 T1 一个 token 都花不出去);把闸摘掉时那条断言会立刻变红
|
||||
// (判成 create 且灰区非空)。
|
||||
|
||||
// judgeRetentionNoTemporal 是**本文件与 transient 测试的便捷封装**:不带时间性位
|
||||
// (= 0027 之前的旧规则)。切片 M45 把 `temporal` 作为入参加进了规则函数(它只在
|
||||
// N6 的位置判据上起作用),因此「旧规则」的每一处断言都显式传 TemporalUnset,
|
||||
// 而不是靠一个隐式默认值 —— 「不带这一位时行为逐字不变」这件事必须在调用点看得见。
|
||||
func judgeRetentionNoTemporal(content string) retentionRule {
|
||||
return judgeExtractionRetention(content, TemporalUnset)
|
||||
}
|
||||
|
||||
// retentionPositiveCases 是正向清单(design/03 §10.4)的脱敏样本与**两道护栏**
|
||||
// 的样本:它们必须**全部**放行(retentionNone)。
|
||||
func retentionPositiveCases() []struct {
|
||||
@@ -126,8 +118,8 @@ func TestExtractionRetention_EmotionWithObjectIsNotDeferred(t *testing.T) {
|
||||
t.Fatalf("%q:余部为空 = %t 与 wantDefer = %t 不一致",
|
||||
tc.content, rest == "", tc.wantDefer)
|
||||
}
|
||||
if rule := judgeRetentionNoTemporal(tc.content); (rule == retentionEmotion) != tc.wantDefer {
|
||||
t.Fatalf("judgeRetentionNoTemporal(%q) = %q, wantEmotionDefer=%t —— 带宾语的与纯情绪的必须给出相反结论",
|
||||
if rule := judgeExtractionRetention(tc.content); (rule == retentionEmotion) != tc.wantDefer {
|
||||
t.Fatalf("judgeExtractionRetention(%q) = %q, wantEmotionDefer=%t —— 带宾语的与纯情绪的必须给出相反结论",
|
||||
tc.content, rule, tc.wantDefer)
|
||||
}
|
||||
})
|
||||
@@ -169,7 +161,7 @@ func TestExtractionRetention_PositivesAreNeverDeferred(t *testing.T) {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if rule := judgeRetentionNoTemporal(tc.content); rule != retentionNone {
|
||||
if rule := judgeExtractionRetention(tc.content); rule != retentionNone {
|
||||
t.Fatalf("正例 %q 被拦成 %q —— 那是把真记忆丢进临时层(fail-safe 方向被违反)",
|
||||
tc.content, rule)
|
||||
}
|
||||
@@ -185,7 +177,7 @@ func TestExtractionRetention_NegativesAreDeferred(t *testing.T) {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if rule := judgeRetentionNoTemporal(tc.content); rule != tc.rule {
|
||||
if rule := judgeExtractionRetention(tc.content); rule != tc.rule {
|
||||
t.Fatalf("反例 %q 命中 %q, want %q", tc.content, rule, tc.rule)
|
||||
}
|
||||
})
|
||||
@@ -197,7 +189,7 @@ func TestExtractionRetention_NegativesAreDeferred(t *testing.T) {
|
||||
func TestExtractionRetention_UpperCaseASCII(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, content := range []string{"HI", "Thanks", "hello~"} {
|
||||
if rule := judgeRetentionNoTemporal(content); rule != retentionChatter {
|
||||
if rule := judgeExtractionRetention(content); rule != retentionChatter {
|
||||
t.Fatalf("%q 命中 %q, want %q(ASCII 词应先折小写)", content, rule, retentionChatter)
|
||||
}
|
||||
}
|
||||
@@ -302,7 +294,7 @@ func TestExtractionRetention_PersistentFactsAreNeverDeferred(t *testing.T) {
|
||||
content := content
|
||||
t.Run(content, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if rule := judgeRetentionNoTemporal(content); rule != retentionNone {
|
||||
if rule := judgeExtractionRetention(content); rule != retentionNone {
|
||||
t.Fatalf("持久事实 %q 被判成 %q —— 它会进临时层、7 天后被物理删除(不可逆)",
|
||||
content, rule)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user