每日回忆:用跨天答案差异观察记忆漂移

AI 速览

还没总结过 —— 过一会儿再看。

每日回忆(Daily Recall)#

每天问几道关于「昨天」的题,同一个日子隔几天再问一次,用跨天答案的差异观察记忆漂移。 定位是可开源的本地优先工具:零后端、零账号,数据只在浏览器 localStorage 里。 起点是「我记忆力差,想练一练」——但真正的价值在于它顺手产出了记忆漂移的证据和一份自动日记。

速查#

项值
稳定版https://memory.hsfp.cn
测试版https://memory_dev.hsfp.cn
开源仓库https://github.com/glwhappen/daily-recall(public,MIT,v1.0.0 tag = 纯静态版)
代码/root/memory
应用容器daily-recall(:4470→3000)、daily-recall-dev(:4471)
数据库daily-recall-db(宿主 :4472)、daily-recall-db-dev(:4473),PostgreSQL 17
统一登录Authentik 应用 daily-recall,issuer https://auth.hsfp.cn/application/o/daily-recall/
反代NPM proxy-host id=189(生产)/ 188(测试),复用证书 id=11 *.hsfp.cn
栈Next.js 15 服务端 + 手写 CSS + pg(无 ORM、无 UI 库、无认证框架)
测试63 个单测 + 题库校验,npm test
部署配置/root/memory/.env(不提交),密钥与 OIDC 凭据都在里面

四个核心设计(容易做错的地方)#

  1. 题目模板化 + 按目标日期锚定。题库里不写死「昨天」,而是 {日期} 占位符 + offsets 列表; 作答记录的唯一键是 (题目 ID, 目标日期, 偏移天数)。 于是「9-20 出门了吗」能在 9-21(昨天)、9-22(前天)、9-27(一周前)各问一次。

    ⚠️ 易错点:同一天被问两次发生在不同的 today,不是同一次 buildCandidates() 调用里。 在 9-21 那天,offset=2 指的是 9-19 而不是 9-20。我写测试时就在这里错过一次。

  2. 作答记录不可变。用户核对记忆时追加一条带 revisionOf 的新记录,绝不覆盖原始答案。 否则「他第一次答错了」这个信号会被删掉,记忆漂移率就算不出来。 实测确认:复核后记录数 7→8,待办 3→2。

  3. 不一致分三类,不是一类(这是项目区别于普通刷题 App 的地方):

    • conflict 事实互相矛盾 → 报警

    • decay 以前记得、后来忘了 → 正常遗忘,画曲线不报警

    • upgrade 越久反而越清晰 → 最可疑,通常是把别的事记混了(虚构记忆)

  4. 按回忆距离分档看覆盖率。总覆盖率会掩盖「昨天全记得、一周以上全忘」这个最关键的特征。 加权覆盖率只在混合偏移时有区分度——全是同一个偏移时它恒等于普通覆盖率(因为它是比例)。

常用命令#

cd /root/memory
npm run dev                # 开发
npm test                   # 48 个单测 + 题库校验
npm run build              # 静态导出到 out/
docker compose up -d --build                              # 生产 :4470
docker compose -f docker-compose.dev.yml up -d --build     # 预览 :4471

题库是 questions/zh-CN.yaml(57 题 / 8 分类),改完必须跑 npm test—— 校验在构建期执行,坏题会让构建直接失败。出题规范见项目内 docs/question-guide.md。

v2:服务端、账号、反馈(2026-09-28)#

三个开关都由部署者配置,不配任何东西仍然可用(降级回纯本地模式):

开关开法关掉后
服务端配 DATABASE_URL数据只在浏览器里
注册登录AUTH_ENABLED有同步能力但不要账号
题目反馈FEEDBACK_ENABLED隐藏 👍👎

关键设计:

  • 同步就是集合并集。作答记录不可变 + UUID 主键,所以客户端把本地全量丢给服务端就行, 不需要 diff、不需要冲突处理。客户端和服务端调用的是同一个 mergeAnswers。

  • 点踩 = 个人屏蔽,不等于下线题目。「别再问我这个」是个人边界,只影响自己; 「这题对所有人都不好」才需要管理员在后台介入。点踩后当场跳过并补一道新题,保证题数不变。

  • 后台下线写数据库,不改 YAML。题库文件是 Git 管理的唯一事实源、容器里也只读; 改了会在下次部署时丢掉。后台另给「同步回仓库」清单。

  • 认证自建不引框架:OIDC 授权码 + PKCE + 用 Node 内置 crypto 验签,约 200 行。

OIDC 接入(auth.hsfp.cn)#

Provider + Application 已用 Authentik API 建好(见 Authentik接入指南 里两个 API 建 Provider 的坑)。 配在 .env 的 OIDC_ISSUER / OIDC_CLIENT_ID / OIDC_CLIENT_SECRET。 管理员用 ADMIN_GROUPS=authentik Admins 判定,人员变动不用改部署。

踩坑#

  • 本机 npm install 不装 devDependencies:新项目 npm install 后只有 25 个包, tsc / vitest 都不在。必须用 npm i --include=dev。 npm config get omit 显示空、NODE_ENV 也没设,原因不明——这台机器上所有新项目都会踩,先记住这个解法。

  • NPM 建反代必须显式写 http2_support: true,漏了会随机返回 421 Misdirected Request, 详见 nginx-proxy-manager使用手册。

  • agent-browser 不能用默认 session:default 之前连过 9223,会一直尝试连 CDP 并失败。 用一个新 session 名(如 --session recall)才会自起本地 Chrome;9223 没开时也只能这样。

  • Next.js build 会自动改 tsconfig.json(往 include 里塞 .next/types/**/*.ts),属正常。

  • offsets 要按记忆类型定:估计型(屏幕时长、刷手机时长)和细节型(上衣颜色)衰减极快, 配上 14/30 天只会让人一路点「不记得」,既挫败又污染远期那一档的统计。已收窄 6 道题。

待办#

  • 英文题库 questions/en.yaml(UI 文案已双语,题库仍只有中文)

  • service worker 让断网可用(现在只有 manifest,能装到主屏但离线打不开)

  • 用真实「不记得率」反向校准每道题的 offsets,取代现在的人工判断

跨天校验的判定口径(迭代了三轮,别退回旧写法)#

要报给用户的判断错了就是在误导人,所以这里反复调过:

  1. 按作答时间取首末两次比较 → 在导入/合并的乱序数据上会把方向判反。

  2. 用「问得最远」那次的距离做门槛 → 「昨天」和「前天」问同一天只差一天, 却因为最远那次是 3 天前而判成可疑。

  3. 当前:用「问得最近」和「问得最远」的两次比;upgrade(越久反而越清晰) 要求两次提问的距离差 ≥ 2 天;距离差不足或偏移相同则不入列表(没信息量)。 decay(正常遗忘)不加门槛——遗忘曲线宁可多收数据。

相关:我的服务 · Docker与容器运维手册 · nginx-proxy-manager使用手册 · 提示词

<!-- project: path:/root/memory -->

讨论 0

还没有人说话。

    登录登录后可以参与讨论