# SPDX-License-Identifier: AGPL-3.0-only # Copyright (c) 2026 sol pbc import json import threading def test_locked_modify_serializes_concurrent_edits(tmp_path, monkeypatch): from solstone.think.activities import ( append_activity_record, append_edit, load_activity_records, locked_modify, ) monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path)) facet = "work" day = "20260418" record_id = "coding_090000_300" record_path = tmp_path / "facets" / facet / "activities" / f"{day}.jsonl" append_activity_record( facet, day, { "id": record_id, "activity": "coding", "description": "Initial description", "segments": ["090000_300"], "created_at": 1, }, ) first_inside_lock = threading.Event() release_first = threading.Event() def worker(actor: str, note: str, hold_lock: bool = False) -> None: def modify_fn(records: list[dict]) -> list[dict]: updated = [] for record in records: if record.get("id") == record_id: record = append_edit( record, actor=actor, fields=["details"], note=note, ) if hold_lock: first_inside_lock.set() release_first.wait(timeout=2) updated.append(record) return updated locked_modify(record_path, modify_fn) first = threading.Thread( target=worker, args=("cli:update", "first writer"), kwargs={"hold_lock": True} ) second = threading.Thread( target=worker, args=("cli:mute", "second writer café"), kwargs={"hold_lock": False}, ) first.start() assert first_inside_lock.wait(timeout=2) second.start() release_first.set() first.join(timeout=2) second.join(timeout=2) assert not first.is_alive() assert not second.is_alive() records = load_activity_records(facet, day, include_hidden=True) assert len(records) == 1 assert [edit["note"] for edit in records[0]["edits"]] == [ "first writer", "second writer café", ] raw_text = record_path.read_text(encoding="utf-8") assert "café" in raw_text assert "\\u00e9" not in raw_text raw_lines = raw_text.splitlines() assert len(raw_lines) == 1 assert json.loads(raw_lines[0])["edits"][1]["actor"] == "cli:mute"