主人原话:「收窄提取器,确实要给他一个主动式的记忆留存规则,不能想到什么都 往记忆里写」「.env 只做兜底用 …这些键优先从面板配置上取」「临时记忆到期删除」。 按 design/23 §18(D3 第五态 defer)、§19(到期处置)、design/03 §9.6 (tempTtlSec 默认 7 天 + 坏值口径)、§10(提取留存规则)落地。 - IngestDecision 闭集加第五态 defer:照常 active 落库 + 写短 expires_at 落 临时层(不删行、不改正文,回滚 = 清空该列);IngestRuleVersion d3.2 → d3.3。 - 落点:ingestGatePlan 增 ExpiresAt + expiresAt()(走 expiryText/formatTime 的 定宽 30 字节 UTC,与读侧时效闸同一套文本口径),由 finishIngest 在 defer 一态 补写 expires_at(INSERT 与补写之间的短暂窗口如实登记,方向 = 宁可多留)。 非 defer 三态一笔都不多写。 - T0 提取留存规则闸(extract_retention.go):design/03 §10.5 的 N1~N5 纯规则, 接进 judgeIngest 的候选比对之前,命中即 defer + reason=t0_low_value,不进 T1; 两道护栏(显式「记住」/ 持久信号)一票放行,fail-safe 方向 = 宁可多留。 - T1 闭集扩为 merge/modify/keep/defer(同一个 prompt、同一次调用,绝不新增 第二次模型调用):只有关系判为真新时才问价值;defer 要求 target=0,否则判 非法回落 create(reason=t1_reply_invalid)。 - 提取器提示词加固(design/03 §10.3 B):正向清单 + 反例清单 + 「允许返回 []」。 - 临时记忆 TTL:代码默认 tempTtlSec = 604800(7 天);面板 $DATA_DIR/config/memory-tidy.json 的 tempTtlSec 优先(ApplyReviewTuning 逐键 解析,坏值回落默认 + WARN,绝不写进 cfg)。该键在 .env 里没有出处且不新增 (.env 已冻结)⇒ 实际生效链是「面板 > 代码默认」。启动播种同步该键(*int + omitempty,nil 省略、绝不写 null),保证播种文件与生效值逐字一致。 - preinsert_store.go 的 listReviewCandidatesSQL 原位注释:这条内部召回 SQL 刻意不过时效闸的裁定与理由(design/03 §11.2 第 3 条)。 - 测试:defer 落库带短 expires_at(闸 + T1 两条路径)、写入口径与时效闸同源、 TTL 坏值与回落、规则版本 d3.3、整理候选幂等键不含 IngestRuleVersion、 提取规则正例 11 条 / 反例 11 条。 验收:go build ./... + go vet ./... + go test ./... 全绿;windows/darwin 交叉 编译通过(GOOS=darwin GOARCH=arm64 / GOOS=windows GOARCH=amd64)。
92 lines
5.0 KiB
Go
92 lines
5.0 KiB
Go
package memory
|
||
|
||
import (
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/config/runtimeconfig"
|
||
)
|
||
|
||
// 本文件是「启动播种」的**值来源**:把 `$DATA_DIR/config/memory-tidy.json` 十一键的
|
||
// **当前生效值**拍成一份完整快照,交给 runtimeconfig.SeedMemoryTidy 落盘。
|
||
//
|
||
// 它回应主人 2026-10-07 的两条口径:
|
||
//
|
||
// - 「**`.env` 只做兜底用** —— 后端**自动创建**独立的面板配置文件之后就走面板
|
||
// 配置文件,这些键优先从面板配置上取」⇒ 播种的时机与「此后以面板为准」;
|
||
// - 「后端**自动创建**独立的面板配置文件**要做**」⇒ 这份快照就是「自动创建」的
|
||
// 内容,**零新 env 键**(`.env` 已冻结,design/13 §2.1)。
|
||
//
|
||
// 为什么放在 memory 而不是 runtimeconfig:runtimeconfig 只管**文件形状与读写**,
|
||
// 「缺位/坏值怎么回落、默认值是多少」属于 TidyConfig / ReviewConfig 的归一化语义
|
||
// (与 normalizeTidyConfig / normalizeReviewConfig 同一层)。
|
||
//
|
||
// 为什么快照取**归一化之后**的值:主人要的是「播种那一刻行为零变化」——把当时真正
|
||
// 生效的值写成文件,读回来叠上去之后(面板这一档等于生效值本身)结果逐字相同。
|
||
// 若快照取的是「未归一化的中间值」(比如四键还是 0),写下去的就是一份**比现状更空**
|
||
// 的配置,只是侥幸等价;取归一化后的值,等价性才是结构性的(见
|
||
// TestTidyTuningSnapshot_PanelRoundTripKeepsEffectiveConfig)。
|
||
//
|
||
// 为什么只有一处实现:十一键的默认值在 memory 侧各只有一处定义
|
||
// (tidy_config.go / preinsert_config.go 的 default* 常量),快照直接复用那两个
|
||
// normalize,**不另写一份默认值** —— 否则播种写下去的就是第二份「差不多」的默认值,
|
||
// 会与运行期悄悄分叉。
|
||
//
|
||
// 十一键与它们的生效来源:
|
||
//
|
||
// 键 生效来源(无面板文件时) 快照值
|
||
// autoApply DisableAutoApply 的反向(代码默认开) true
|
||
// autoApplyPerRound defaultTidyAutoApplyPerRound 50
|
||
// ingestGate DisableIngestGate 的反向(默认开) true
|
||
// t1Judge DisableT1 的反向(默认开) true
|
||
// t1PerWindow defaultT1PerWindow 120
|
||
// t1WindowSec defaultT1Window 3600
|
||
// tempTtlSec ReviewConfig.TempTTL(默认 7 天 = 604800) 归一化值
|
||
// intervalSec TidyConfig.IntervalSec(env 或 86400) 归一化值
|
||
// quietIntervalSec 缺省 = intervalSec 归一化值
|
||
// quietStartHour TidyConfig.QuietStartHour(env 或 23) 归一化值
|
||
// quietEndHour TidyConfig.QuietEndHour(env 或 7) 归一化值
|
||
|
||
// TidyTuningSnapshot 拍下十一键的**当前生效值**,返回一份可直接落盘的面板快照。
|
||
//
|
||
// 入参是**已经叠过面板层的**两个配置(组合根的次序:TidyConfigFromConfig →
|
||
// ApplyTidyScheduleTuning → 本函数;审查侧同理),本函数只做最后一步归一化并翻成
|
||
// 文件形状 —— 它不读盘、不读 env、不认识面板文件:
|
||
//
|
||
// - tidy 侧四键(intervalSec / quietIntervalSec / quietStartHour / quietEndHour)
|
||
// 与自动档两键(autoApply / autoApplyPerRound);
|
||
// - review 侧五键(ingestGate / t1Judge / t1PerWindow / t1WindowSec /
|
||
// tempTtlSec):这五项在 `.env` 里**没有出处**(`.env` 已冻结),只由面板文件
|
||
// 与代码默认决定,而播种只发生在**面板文件不存在**时 —— 那正是「零值 +
|
||
// normalizeReviewConfig」这一条路径,与运行期(wireMemoryReview 的四个 helper)
|
||
// 逐字一致。
|
||
//
|
||
// 两个开关是**反向**字段(DisableX),快照要把它们翻回正向的 JSON 键:文件里的
|
||
// `"autoApply": true` 才是「没配时到底开不开」的如实陈述。
|
||
func TidyTuningSnapshot(tidy TidyConfig, review ReviewConfig) runtimeconfig.MemoryTidyTuning {
|
||
tidy = normalizeTidyConfig(tidy)
|
||
review = normalizeReviewConfig(review)
|
||
|
||
autoApply := !tidy.DisableAutoApply
|
||
ingestGate := !review.DisableIngestGate
|
||
t1Judge := !review.DisableT1
|
||
intervalSec := tidy.IntervalSec
|
||
quietIntervalSec := tidy.QuietIntervalSec
|
||
quietStartHour := tidy.QuietStartHour
|
||
quietEndHour := tidy.QuietEndHour
|
||
// 临时记忆 TTL(design/03 §9.6):normalize 之后恒为正(7 天 = 604800),
|
||
// 因此快照写下去的**必然是有效值**,不会播出一份自己读回都要 WARN 的配置。
|
||
tempTtlSec := int(review.TempTTL.Seconds())
|
||
|
||
return runtimeconfig.MemoryTidyTuning{
|
||
AutoApply: &autoApply,
|
||
AutoApplyPerRound: tidy.AutoApplyPerRound,
|
||
IngestGate: &ingestGate,
|
||
T1Judge: &t1Judge,
|
||
T1PerWindow: review.T1PerWindow,
|
||
T1WindowSec: int(review.T1Window.Seconds()),
|
||
TempTtlSec: &tempTtlSec,
|
||
IntervalSec: &intervalSec,
|
||
QuietIntervalSec: &quietIntervalSec,
|
||
QuietStartHour: &quietStartHour,
|
||
QuietEndHour: &quietEndHour,
|
||
}
|
||
}
|