repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources15d ago| #1 | """Regression tests for [C23]: `mnemosyne stats` printed zeros and N/A |
| #2 | because cli.cmd_stats read flat keys (working_count, episodic_count, |
| #3 | triple_count, db_path) that Mnemosyne.get_stats() never returned. |
| #4 | |
| #5 | Tests verify: |
| #6 | 1. cmd_stats prints real counts, not zeros, when data exists. |
| #7 | 2. cmd_stats prints the actual DB path, not "N/A". |
| #8 | 3. get_stats() exposes triples and banks in shapes the CLI expects. |
| #9 | """ |
| #10 | |
| #11 | import argparse |
| #12 | |
| #13 | import pytest |
| #14 | |
| #15 | from mnemosyne.core.memory import Mnemosyne |
| #16 | |
| #17 | |
| #18 | def _seed(db_path): |
| #19 | """Populate an isolated DB with one working + one episodic + one triple.""" |
| #20 | from mnemosyne.core.triples import TripleStore |
| #21 | mem = Mnemosyne(session_id="c23", db_path=db_path) |
| #22 | wm_id = mem.remember("Working memory item", source="user", importance=0.5) |
| #23 | mem.beam.consolidate_to_episodic( |
| #24 | summary="Episodic summary", |
| #25 | source_wm_ids=[wm_id], |
| #26 | source="consolidation", |
| #27 | importance=0.6, |
| #28 | ) |
| #29 | triples = TripleStore(db_path=db_path) |
| #30 | triples.add(subject="alice", predicate="likes", object="python", source="test") |
| #31 | return mem |
| #32 | |
| #33 | |
| #34 | def _run_cmd_stats(monkeypatch, db_path, capsys): |
| #35 | """Invoke cmd_stats with cli.DATA_DIR pointing at the isolated DB's parent.""" |
| #36 | from mnemosyne import cli |
| #37 | monkeypatch.setattr(cli, "DATA_DIR", str(db_path.parent)) |
| #38 | cli.cmd_stats(argparse.Namespace()) |
| #39 | return capsys.readouterr().out |
| #40 | |
| #41 | |
| #42 | def _line_value(out, prefix): |
| #43 | """Return the integer value after `<prefix>:` in cmd_stats output. |
| #44 | Fails the test loudly if the line is missing or non-numeric.""" |
| #45 | for line in out.splitlines(): |
| #46 | if line.strip().startswith(prefix): |
| #47 | value = line.split(":", 1)[1].strip() |
| #48 | try: |
| #49 | return int(value) |
| #50 | except ValueError: |
| #51 | pytest.fail(f"{prefix} value not an int: {value!r}") |
| #52 | pytest.fail(f"{prefix!r} line missing from stats output:\n{out}") |
| #53 | |
| #54 | |
| #55 | class TestCliStatsRegression: |
| #56 | def test_stats_prints_working_count_not_zero(self, tmp_path, monkeypatch, capsys): |
| #57 | db_path = tmp_path / "mnemosyne.db" |
| #58 | _seed(db_path) |
| #59 | out = _run_cmd_stats(monkeypatch, db_path, capsys) |
| #60 | assert _line_value(out, "Working memory") >= 1 |
| #61 | |
| #62 | def test_stats_prints_episodic_count(self, tmp_path, monkeypatch, capsys): |
| #63 | db_path = tmp_path / "mnemosyne.db" |
| #64 | _seed(db_path) |
| #65 | out = _run_cmd_stats(monkeypatch, db_path, capsys) |
| #66 | assert _line_value(out, "Episodic memory") >= 1 |
| #67 | |
| #68 | def test_stats_prints_triple_count(self, tmp_path, monkeypatch, capsys): |
| #69 | db_path = tmp_path / "mnemosyne.db" |
| #70 | _seed(db_path) |
| #71 | out = _run_cmd_stats(monkeypatch, db_path, capsys) |
| #72 | assert _line_value(out, "Knowledge triples") >= 1 |
| #73 | |
| #74 | def test_stats_prints_zero_triples_on_fresh_db(self, tmp_path, monkeypatch, capsys): |
| #75 | """Fresh DB with no triples must still show 'Knowledge triples: 0', |
| #76 | consistent with how Working / Episodic always render 0.""" |
| #77 | db_path = tmp_path / "mnemosyne.db" |
| #78 | Mnemosyne(session_id="c23-fresh", db_path=db_path) |
| #79 | out = _run_cmd_stats(monkeypatch, db_path, capsys) |
| #80 | assert _line_value(out, "Knowledge triples") == 0 |
| #81 | |
| #82 | def test_stats_prints_real_db_path_not_na(self, tmp_path, monkeypatch, capsys): |
| #83 | db_path = tmp_path / "mnemosyne.db" |
| #84 | _seed(db_path) |
| #85 | out = _run_cmd_stats(monkeypatch, db_path, capsys) |
| #86 | for line in out.splitlines(): |
| #87 | if line.strip().startswith("DB path:"): |
| #88 | value = line.split(":", 1)[1].strip() |
| #89 | assert value != "N/A", "DB path printed as 'N/A' instead of real path" |
| #90 | assert "mnemosyne.db" in value, \ |
| #91 | f"DB path missing expected db filename: {value!r}" |
| #92 | return |
| #93 | pytest.fail("'DB path:' line missing from stats output") |
| #94 | |
| #95 | |
| #96 | class TestGetStatsShape: |
| #97 | """Direct tests on get_stats() shape — independent of CLI rendering.""" |
| #98 | |
| #99 | def test_get_stats_includes_triples_in_beam(self, tmp_path): |
| #100 | """get_stats() should expose a triple count, not silently omit it.""" |
| #101 | from mnemosyne.core.triples import TripleStore |
| #102 | db_path = tmp_path / "mnemosyne.db" |
| #103 | mem = Mnemosyne(session_id="c23", db_path=db_path) |
| #104 | triples = TripleStore(db_path=db_path) |
| #105 | triples.add(subject="a", predicate="b", object="c", source="test") |
| #106 | triples.add(subject="d", predicate="e", object="f", source="test") |
| #107 | stats = mem.get_stats() |
| #108 | # Canonical shape: nested under "beam" matching working_memory/episodic_memory. |
| #109 | assert "triples" in stats["beam"], \ |
| #110 | "get_stats() must expose triples under stats['beam']" |
| #111 | assert stats["beam"]["triples"]["total"] >= 2 |
| #112 | |
| #113 | def test_get_stats_includes_banks_at_top(self, tmp_path): |
| #114 | """get_stats() should expose bank list so CLI can render it.""" |
| #115 | db_path = tmp_path / "mnemosyne.db" |
| #116 | mem = Mnemosyne(session_id="c23", db_path=db_path) |
| #117 | stats = mem.get_stats() |
| #118 | assert "banks" in stats, "get_stats() must expose top-level 'banks' list" |
| #119 | assert isinstance(stats["banks"], list) |
| #120 | # 'default' is always present per BankManager.list_banks() contract. |
| #121 | assert "default" in stats["banks"] |
| #122 |