personal memory agent
1# SPDX-License-Identifier: AGPL-3.0-only
2# Copyright (c) 2026 sol pbc
3
4"""Tests for output path generation with facet support."""
5
6import os
7from pathlib import Path
8
9from think.talent import get_output_name, get_output_path
10
11os.environ.setdefault("_SOLSTONE_JOURNAL_OVERRIDE", "tests/fixtures/journal")
12
13
14class TestGetOutputName:
15 """Tests for get_output_name."""
16
17 def test_simple_key(self):
18 assert get_output_name("activity") == "activity"
19
20 def test_app_key(self):
21 assert get_output_name("chat:sentiment") == "_chat_sentiment"
22
23 def test_entities_app_key(self):
24 assert get_output_name("entities:observer") == "_entities_observer"
25
26
27class TestGetOutputPath:
28 """Tests for get_output_path."""
29
30 def test_daily_output_md(self):
31 path = get_output_path("/journal/20250101", "activity", output_format="md")
32 assert path == Path("/journal/20250101/agents/activity.md")
33
34 def test_daily_output_json(self):
35 path = get_output_path("/journal/20250101", "facets", output_format="json")
36 assert path == Path("/journal/20250101/agents/facets.json")
37
38 def test_segment_output(self):
39 path = get_output_path(
40 "/journal/20250101", "activity", segment="120000_300", output_format="md"
41 )
42 assert path == Path("/journal/20250101/120000_300/agents/activity.md")
43
44 def test_app_key_output(self):
45 path = get_output_path(
46 "/journal/20250101", "entities:observer", output_format="md"
47 )
48 assert path == Path("/journal/20250101/agents/_entities_observer.md")
49
50 def test_facet_daily_output(self):
51 """Multi-facet agent output uses a facet subdirectory."""
52 path = get_output_path(
53 "/journal/20250101", "newsletter", output_format="md", facet="work"
54 )
55 assert path == Path("/journal/20250101/agents/work/newsletter.md")
56
57 def test_facet_segment_output(self):
58 """Multi-facet segment output uses a facet subdirectory."""
59 path = get_output_path(
60 "/journal/20250101",
61 "summary",
62 segment="120000_300",
63 output_format="json",
64 facet="personal",
65 )
66 assert path == Path("/journal/20250101/120000_300/agents/personal/summary.json")
67
68 def test_facet_with_app_key(self):
69 """App-qualified key with facet uses both prefixes."""
70 path = get_output_path(
71 "/journal/20250101", "entities:observer", output_format="md", facet="work"
72 )
73 assert path == Path("/journal/20250101/agents/work/_entities_observer.md")
74
75 def test_facet_none_same_as_omitted(self):
76 """Explicit facet=None produces same path as omitting facet."""
77 path_none = get_output_path(
78 "/journal/20250101", "activity", output_format="md", facet=None
79 )
80 path_omit = get_output_path("/journal/20250101", "activity", output_format="md")
81 assert path_none == path_omit
82
83
84class TestGetActivityOutputPath:
85 """Tests for get_activity_output_path."""
86
87 def test_markdown_output(self):
88 from think.activities import get_activity_output_path
89
90 path = get_activity_output_path(
91 "work", "20260209", "coding_100000_300", "session_review"
92 )
93 journal = os.environ["_SOLSTONE_JOURNAL_OVERRIDE"]
94 expected = (
95 Path(journal)
96 / "facets/work/activities/20260209/coding_100000_300/session_review.md"
97 )
98 assert path == expected
99
100 def test_json_output(self):
101 from think.activities import get_activity_output_path
102
103 path = get_activity_output_path(
104 "work",
105 "20260209",
106 "meeting_090000_300",
107 "analysis",
108 output_format="json",
109 )
110 assert path.name == "analysis.json"
111 assert "facets/work/activities/20260209/meeting_090000_300" in str(path)
112
113 def test_app_key(self):
114 from think.activities import get_activity_output_path
115
116 path = get_activity_output_path(
117 "personal", "20260210", "coding_100000_300", "chat:review"
118 )
119 assert path.name == "_chat_review.md"
120 assert "facets/personal/activities/20260210/coding_100000_300" in str(path)