personal memory agent
1# SPDX-License-Identifier: AGPL-3.0-only
2# Copyright (c) 2026 sol pbc
3
4from pathlib import Path
5
6
7def test_root_agents_md_is_hand_maintained():
8 project_root = Path(__file__).resolve().parent.parent
9 agents_path = project_root / "AGENTS.md"
10 content = agents_path.read_text(encoding="utf-8")
11
12 assert content.startswith("# solstone Developer Guide")
13 assert "generated from identity/identity.md" not in content
14 assert "docs/project-structure.md" in content
15 assert "journal/AGENTS.md" in content
16
17
18def test_root_agent_symlinks_point_to_agents():
19 project_root = Path(__file__).resolve().parent.parent
20 claude_path = project_root / "CLAUDE.md"
21 gemini_path = project_root / "GEMINI.md"
22
23 assert claude_path.is_symlink()
24 assert gemini_path.is_symlink()
25 assert claude_path.readlink() == Path("AGENTS.md")
26 assert gemini_path.readlink() == Path("AGENTS.md")
27
28
29def test_generation_params_thinking_budget_zero_disables_thinking():
30 """An explicit thinking_budget=0 must pass through (disable thinking), not
31 coalesce to the default — regression for the `or 8192*2` bug that turned 0
32 into 16384, making thinking impossible to disable from talent config."""
33 from solstone.think.talents import _generation_params
34
35 # explicit 0 -> 0 (disabled), not the default
36 assert _generation_params({"thinking_budget": 0})["thinking_budget"] == 0
37 # unset -> default
38 assert _generation_params({})["thinking_budget"] == 8192 * 2
39 # explicit None -> default
40 assert _generation_params({"thinking_budget": None})["thinking_budget"] == 8192 * 2
41 # explicit positive value -> passes through unchanged
42 assert _generation_params({"thinking_budget": 4096})["thinking_budget"] == 4096
43
44
45def test_json_extraction_talents_pin_output_cap_and_timeout():
46 from solstone.think.talent import get_talent
47 from solstone.think.talents import _generation_params
48
49 largest_observed_legitimate_completion = 3560
50
51 sense_config = get_talent("sense")
52 sense_params = _generation_params(sense_config)
53 assert sense_params["max_output_tokens"] == 6144
54 assert sense_config.get("timeout_s") == 480
55 assert "temperature" not in sense_config
56
57 participation_config = get_talent("participation")
58 participation_params = _generation_params(participation_config)
59 participation_tokens = participation_params["max_output_tokens"]
60 # Participation did not change and still keeps 2x headroom over the
61 # largest legitimate completion observed when this guard was added.
62 assert participation_tokens == 12288
63 assert participation_tokens >= 2 * largest_observed_legitimate_completion
64 assert participation_tokens < 8192 * 6
65 assert participation_config.get("timeout_s") == 480
66 resolved = participation_config.get("timeout_s") or min(
67 480,
68 max(
69 120,
70 (participation_tokens + participation_params["thinking_budget"]) // 100,
71 ),
72 )
73 assert resolved == participation_config["timeout_s"]
74 assert resolved >= 480
75 assert "temperature" not in participation_config