Files
Geralt2026 3f4ecf9529 fix(memory,time-tracker): prevent silent JSONL data loss and slug corruption
Two CRITICAL data-integrity bugs surfaced by the audit, fixed under TDD
(regression tests added first, confirmed RED, then GREEN).

C4 — non-atomic JSONL append:
  events.jsonl / interactions.jsonl were appended with open("a") and no
  trailing-newline guard. If a prior write was truncated mid-line (crash /
  power loss, no final newline), the next record was concatenated onto the
  broken line, the merged line failed to parse, and the reader silently
  dropped it via `except JSONDecodeError: continue` — losing both the
  corrupt fragment AND the new valid event. meta counts also drifted because
  event_count/interaction_count were blindly incremented.
  Fix: prepend a newline when the file does not end in one; recount
  event_count/interaction_count from actually-readable lines; log corrupt
  lines (line number + snippet) instead of dropping them silently.

C5 — frontmatter numeric coercion corrupted the primary key:
  _parse_frontmatter coerced any all-digit value to int, so `slug: 007`
  parsed to 7 and, after the parse->render round-trip update_state performs
  on every call, was permanently rewritten as `slug: 7`, breaking all
  slug-based directory lookups silently.
  Fix: restrict int/float coercion to a numeric-key whitelist
  (age/score/signal_score/...); identifier fields like slug stay strings.

Deferred (noted in audit, not in this commit): cross-process file locking
for concurrent writers; write-side slug quoting in skill_writer.py.
2026-06-03 14:26:32 +08:00
..