fix(badge): classify save-state from transcript structure, not raw text - #45
Merged
Merged
Conversation
compute_save_state() regexed the transcript JSONL as flat text, so its
patterns matched their own words wherever they appeared: in a user message,
in assistant prose, in tool output, or inside the contents of any file read
into context. That was wrong in both directions.
False "unsaved" was the benign one — reading any file containing "git commit"
faked work, and WORK_RE matched its own pattern string, so reading this module
self-triggered. False "saved" was the dangerous one: once the words
"/okfmem-save" appeared after the last real edit, the badge went green over
genuinely uncaptured work. That fires easily, since the global CLAUDE.md
proactive-reminder text contains the literal string. Measured on a real
transcript: 0 Edit/Write tool uses but 11 "git commit" and 27 "okfmem-save"
prose matches, badge "saved" — 100% false.
Classify from structure instead:
- iter_tool_uses() walks parsed dicts/lists only, never into strings. That is
what isolates file contents — a tool_result carrying a file holds it as an
opaque string, so it can never be read as a tool call.
- user_text() reads only text blocks of user-role messages, skipping
tool_result, so a command echoing "/okfmem-save" is not the user invoking it.
- Save signals are a Skill{skill: okfmem-save|primer} use, a Bash `okfmem sync`,
or an actual /okfmem-save invocation.
- runs_command() requires command position, so `grep -o 'git commit'` no longer
counts as committing. Quoted spans are blanked BEFORE segmenting: a separator
inside a quoted regex would otherwise split there and leave the quote's tail
in apparent command position — a real path to a false "saved".
- Position is line index; work and save on one record tie to "unsaved", because
a redundant save is cheap and a lost one is not.
touched_files() replaces the FILE_PATH_RE breadcrumb scan for the same reason:
that regex also listed paths quoted in prose or in a file the session only read.
Known and accepted: a command inside `bash -c "..."` is missed, since quoting is
not parsed. Edit/Write is the dominant signal and a miss costs only a nag.
Refs #44
This was referenced Jul 24, 2026
Closed
Save-state badge stuck 'unsaved': SAVE_BASH_RE misses path- and interpreter-prefixed
okfmem sync
#46
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The statusline save-state badge classified sessions by regexing the raw transcript JSONL as flat text, so its patterns matched the same words wherever they appeared — in a user message, in assistant prose, or inside the contents of any file read into context. Classification now reads the transcript's structure (
tool_useblocks, user-authored text), which prose cannot reach.The dangerous direction was a false
saved: once the words/okfmem-saveappeared after the last real edit, the badge went green over genuinely uncaptured work. That fires easily — the globalCLAUDE.mdproactive-reminder text contains the literal string. Measured on a real transcript: 0 Edit/Write tool uses but 11git commitand 27okfmem-saveprose matches → badgesaved, 100% false.Refs #44
What changed
iter_tool_uses()walks parsed dicts/lists only, never into strings — that is what isolates file contents; atool_resultcarrying a file holds it as an opaque string, so it can't be read as a tool call.user_text()reads only text blocks of user-role messages, skippingtool_result, so a command echoing/okfmem-saveisn't the user invoking it.Skill{skill: okfmem-save|primer}, Bashokfmem sync, or a real/okfmem-save//primerinvocation.runs_command()requires command position, sogrep -o 'git commit'no longer counts. Quoted spans are blanked before segmenting — a separator inside a quoted regex would otherwise split there and leave the tail in apparent command position, itself a path to a falsesaved.unsaved(a redundant save is cheap, a lost one is not).touched_files()replaces theFILE_PATH_REbreadcrumb scan, which also listed paths quoted in prose or in files the session only read.Accepted trade-off: a command inside
bash -c "..."is missed, since quoting is not parsed. Catching it needs a mini shell lexer; Edit/Write is the dominant exactly-structural signal and a miss costs only a nag, never a false green.Test plan
python3 scripts/check-leaks.pyexits 0 — Leak gate OK — scanned 62 tracked files, no leaks.python3 -m pytest tests/ -q— 197 passed, 1 skipped (10 new cases intests/test_save_state_badge.py, incl. regressions for both false directions)ruff check .reviewed (advisory) — 2 × E702, both in untouchedplugins/memory_search.py;ruff format --checkflags 29 files. Identical on unmodified HEAD (verified viagit stash) — pre-existing, out of scope.okfmem statusexits 0saved/unsaved/None) and save detection fires on real signals (<command-name>/okfmem-save, Bashokfmem sync)iter_tool_uses's permissive fallback branch across every real transcript — zero nodes match it outsidetype == "tool_use"; no false-positive surface in practicegrep -o 'okfmem[- ]save\|okfmem sync' f, segment-before-quote yields a falsesaved; the shipped order does notProvenance
Code implementation via: Claude Opus 4.8 (1M context), high effort
Review: Claude Opus 4.8 (1M context), high effort — diff review, adversarial probing of
COMMIT_REagainst 16 command variants, real-transcript validationVerification: CI
verify