# TenseMem 0.1.0: test plan (pre-registered 2026-10-29 UTC+8, committed before running any test script)

Tool: TenseMem (github.com/tensemem/tensemem, Apache-2.0), `pip install tensemem` 0.1.0 (PyPI), repo HEAD 48a9cf7 (2026-10-25).
Setup: fresh venv, Python 3.13, `FakeExtractor` (the README's no-key rule-based extractor). Each scenario uses a new SQLite file in a fresh temp dir.
No API key anywhere in the environment. Network check: Python audit hook on socket.connect/getaddrinfo, plus a second run inside `unshare -rn` (no network).
I read fake.py and memory.py signatures beforehand to phrase messages the rule-based extractor understands; that is how a user would use it.

## Claims (README, verbatim) and pass marks
Core claims (overall = worst core; any core V0 caps at V1; score = mean of tested claims, V2=10, V1=5, F=0, V0 excluded):
- C1 "One current truth per ONE slot. A new city supersedes the old one. History still answers 'where did I live before?'"
  Scenario: u1 add() in order "I live in Delhi", "I moved to Bangalore", "Maybe I will move to Mumbai" (hedge), "I moved to Pune"; u2 "I live in Paris".
  Ground truth (5 checks): state(u1).lives_in == Pune; history(u1, lives_in) has Pune ACTIVE; Bangalore and Delhi SUPERSEDED; no Mumbai fact; state(u2).lives_in == Paris and u1 unaffected.
  V2 = 5/5; V1 = 4/5; F <= 3/5.
- C2 "Every read reports freshness. as_of_seq, pending, is_current. Wait for a message, or see that it is not applied yet."
  20 rounds: add(u5, "I moved to City<i>") then immediately context(min_seq=seq, wait=0) and state(); then context(min_seq=seq, wait=2.0).
  A "lie" = a read with is_current True while the newest city is not the current value. V2 = 0 lies and 20/20 current+correct after wait;
  V1 = 0 lies and 15-19/20; F = any lie or < 15/20.
- C3 "No self-echo. Recalled context() is fenced. Extract needs a verbatim quote from the user."
  (a) Take u1's fenced context() text and add() it as a message for a new user u3: no facts for u3 may appear.
  (b) Scripted lying extractor (the vendor's FakeExtractor responses mode) proposes lives_in=Tokyo with evidence "I live in Tokyo" for the message "Hello there": no Tokyo fact may appear.
  V2 = both blocked; V1 = one; F = neither.
- C4 "Corrections stick. correct() restores the displaced value and survives rebuild() with a newer model."
  u4: "I live in Delhi", "I moved to Bangalore"; correct(<Bangalore fact id>) -> state Delhi; then close, reopen the file with a new Memory + new FakeExtractor and rebuild(u4, wait=True) -> still Delhi, Bangalore not ACTIVE.
  V2 = both; V1 = only the first; F = neither.
Non-core:
- C5 TenseBench: "`tensemem bench` scores the packaged 101 conversations with FakeExtractor (no network)" -> 1.00 / 0.00 / 1.00 / 0.00.
  V2 = exact; V1 = all within 0.05; F otherwise. Caveat: FakeExtractor and the bench come from the same vendor, so this checks reproducibility, not real-world extraction.
- C6 "No infrastructure. Default store is one SQLite file inside your process." V2 = 0 network calls by audit hook, scenario also passes in unshare -rn, and the temp dir holds only the .db file (+ -wal/-shm). V1 = one of these fails; F = more.
- C7 Real-LLM extraction quality (OpenAI/Anthropic/Gemini/Ollama): V0, not tested (no key; out of scope today).
