Skip to content

v7.13.9 测试不再能写真实数据;被污染的中枢能体检、能修 - #16

Merged
sixgodgit merged 2 commits into
mainfrom
claude/intelligent-hawking-oeyjx8
Oct 13, 2026
Merged

sixgodgit merged 2 commits into
mainfrom
claude/intelligent-hawking-oeyjx8

Conversation

@sixgodgit

@sixgodgit sixgodgit commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

背景

2026-09-13 生产事故:测试把 107 条合成记忆(sender=golden / test / e2e / mcp)写进了生产 ID 中枢(日志里没有),真实记忆被覆盖,agent 把「用户喜欢喝拿铁」「预算 2000 欧」当成真记忆说了出来。doctor 三项红:hub_vs_journal、fts_index、erasure_integrity。

在 v7.13.8 上复现:NEXSANDBASE_HOME 指着真实数据目录(或不设)时跑测试,真实日志里会多出合成记录。

防复发

  • tests/conftest.py:测试会话一开始、任何模块 import 之前,把数据目录无条件改到临时目录
  • core/prodguard.py:pytest 进程里,开临时目录以外的库、往那里的日志追加、把数据目录解析到那里,都直接报错。生产进程不受影响(判据是 PYTEST_CURRENT_TEST / PYTEST_VERSION;单凭 _pytest 已加载不算)。豁免:NYX_ALLOW_PROD_DB=1
  • tests/test_prod_guard.py:指着一个「生产目录」真跑一个会写合成记忆的测试文件,带 conftest 与 --noconftest 各一次,「生产目录」必须一个字节不变

修复工具 python3 -m nexsandglass.repair(core/forensics.py)

按内容身份(mem_id = 原文哈希)逐条核对,不按 seq:

  • 只读体检:分出对得上 / 错位 / 被覆盖 / 中枢缺的 / 合成孤儿 / 指错位置的墓碑(含被误报的「泄漏」)/ 遗忘没做完;只给计数和 seq 范围,不输出正文
  • --apply:
    • 在日志锁里先备份,再按日志重写中枢;mem_id 与写入时绑定的来源都保留
    • 被遗忘的不复活;抹过的行先按 mem= 标记认,隔离区还原仍然有效
    • 合成记录的派生数据按 mem_id 撤下:信念三元组、engram、实体、向量
    • 被合成事实截断的真实信念会恢复
    • 日志不改
  • --finish-erasures:在日志里抹掉没做完的遗忘,只动身份已核实的那几行
  • --forget-senders:对齐之后,把这些发送者的记录送进隔离区

另外:

  • erasure._select 支持 sender / senders;和别的条件一起用时是收窄,不会扩大选中范围
  • doctor 这三项红时会提示先体检,并提醒不要按 seq 去 forget

验证

  • tests/test_incident_0913.py(12 项):原样造出事故现场,验收以下各项:
    • 分类正确,体检不写任何东西
    • 修复后日志字节不变,备份存在
    • 信念恢复,向量对齐
    • 正文带 \r 的记忆不被误撤
    • 抹除标记优先,隔离区还原有效
    • 备份在锁里做
    • CLI 不输出正文
  • 后加的 3 项在上一版实现上失败、在这一版上通过
  • 全量测试:547 passed, 2 skipped
  • 在非测试进程里冒烟:新装目录体检干净;中枢里有合成孤儿和错位的目录,修复后 doctor 全绿

🤖 Generated with Claude Code

https://claude.ai/code/session_019ZZeQFn5F6mEbmX8vPsf4g

…gnosed and repaired

2026-09-13 incident: tests wrote 107 synthetic memories into the production
ID hub (not in the journal), real memories were overwritten, and the agent
repeated fabricated facts. Reproduced on v7.13.8: running the suite with
NEXSANDBASE_HOME pointing at (or defaulting to) the real data dir appends
synthetic records to the real journal.

Prevention:
- tests/conftest.py forces a per-session temp data dir before any import
- core/prodguard.py: in pytest processes, opening a DB, appending to a
  journal, or resolving the data dir outside the temp dir raises
  (override: NYX_ALLOW_PROD_DB=1); production processes are unaffected
- tests/test_prod_guard.py replays the incident with and without conftest

Repair (python3 -m nexsandglass.repair, core/forensics.py):
- read-only diagnosis by content identity: aligned / misplaced /
  overwritten / missing / synthetic orphans / stray tombstones (incl. false
  leaks) / unfinished erasures; counts and seq ranges only
- --apply: backup, then rewrite the hub to match the journal under the
  journal lock; keep mem_ids and bound provenance; never resurrect forgotten
  memories; remove synthetic derived data by mem_id (triples, engram,
  entities, vectors) and reopen real beliefs truncated by synthetic facts;
  journal untouched unless --finish-erasures
- erasure selector: sender/senders (narrows when combined)
- doctor points to the repair tool and warns against forgetting by seq
- tests/test_incident_0913.py stages the incident and verifies the repair

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZZeQFn5F6mEbmX8vPsf4g
…the lock

- Redacted journal lines are matched to deleted hub rows by their mem=
  marker before any positional fallback, so a legacy (marker-less) line can
  no longer take the row another line's marker names; legacy lines match by
  (ts, sender) before seq. Quarantine restore keeps working after a repair.
- Text that contains \r reads back from the journal as \n; compare
  normalized text so such memories are not treated as synthetic orphans.
- Take the backup while holding the journal lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZZeQFn5F6mEbmX8vPsf4g
@sixgodgit
sixgodgit merged commit 9a4fce8 into main Oct 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants