personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

style: apply formatter cleanup from audit pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+257 -140
+1 -1
apps/health/routes.py
··· 6 6 from pathlib import Path 7 7 8 8 from flask import Blueprint, jsonify, request 9 - from think.streams import stream_name 10 9 11 10 from convey import state 11 + from think.streams import stream_name 12 12 13 13 health_bp = Blueprint("app:health", __name__, url_prefix="/app/health") 14 14
+3 -1
apps/home/events.py
··· 55 55 ) 56 56 except Exception: 57 57 logger.debug( 58 - "Failed to record conversation exchange for agent %s", agent_id, exc_info=True 58 + "Failed to record conversation exchange for agent %s", 59 + agent_id, 60 + exc_info=True, 59 61 )
+6 -2
apps/home/routes.py
··· 96 96 return None, None, [] 97 97 98 98 99 - def _load_briefing_md(today: str | None = None) -> tuple[dict[str, str], dict | None, list[str]]: 99 + def _load_briefing_md( 100 + today: str | None = None, 101 + ) -> tuple[dict[str, str], dict | None, list[str]]: 100 102 """Load today's briefing.md sections and needs_attention bullets.""" 101 103 try: 102 104 today = today or _today() ··· 148 150 return {}, None, [] 149 151 150 152 151 - def _compute_briefing_phase(segment_count: int, hour: int, briefing_exists: bool) -> str: 153 + def _compute_briefing_phase( 154 + segment_count: int, hour: int, briefing_exists: bool 155 + ) -> str: 152 156 """Compute briefing display phase from current time and activity.""" 153 157 if hour >= BRIEFING_EOD_HOUR: 154 158 return "eod"
+8 -6
apps/remote/tests/test_observer_client.py
··· 22 22 23 23 @pytest.fixture 24 24 def mock_config(): 25 - with patch("observe.remote_client.get_config") as mock, patch( 26 - "observe.remote_client.read_service_port" 27 - ) as mock_port: 25 + with ( 26 + patch("observe.remote_client.get_config") as mock, 27 + patch("observe.remote_client.read_service_port") as mock_port, 28 + ): 28 29 mock.return_value = {} 29 30 mock_port.return_value = 8000 30 31 yield mock ··· 53 54 """When no config URL and no convey.port file, _url is empty.""" 54 55 from observe.remote_client import ObserverClient 55 56 56 - with patch("observe.remote_client.get_config") as cfg, patch( 57 - "observe.remote_client.read_service_port" 58 - ) as port: 57 + with ( 58 + patch("observe.remote_client.get_config") as cfg, 59 + patch("observe.remote_client.read_service_port") as port, 60 + ): 59 61 cfg.return_value = {} 60 62 port.return_value = None 61 63 client = ObserverClient("main-stream")
+44 -11
apps/remote/tests/test_routes.py
··· 791 791 key = resp.get_json()["key"] 792 792 793 793 # Query segments - should be empty 794 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 794 + resp = env.client.get( 795 + "/app/remote/ingest/segments/20250103", 796 + headers={"Authorization": f"Bearer {key}"}, 797 + ) 795 798 assert resp.status_code == 200 796 799 assert resp.get_json() == [] 797 800 ··· 800 803 """Test segments endpoint rejects invalid key.""" 801 804 env = remote_env() 802 805 803 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": "Bearer invalid-key"}) 806 + resp = env.client.get( 807 + "/app/remote/ingest/segments/20250103", 808 + headers={"Authorization": "Bearer invalid-key"}, 809 + ) 804 810 assert resp.status_code == 401 805 811 806 812 ··· 816 822 ) 817 823 key = resp.get_json()["key"] 818 824 819 - resp = env.client.get("/app/remote/ingest/segments/2025-01-03", headers={"Authorization": f"Bearer {key}"}) 825 + resp = env.client.get( 826 + "/app/remote/ingest/segments/2025-01-03", 827 + headers={"Authorization": f"Bearer {key}"}, 828 + ) 820 829 assert resp.status_code == 400 821 830 assert "Invalid day format" in resp.get_json()["error"] 822 831 ··· 847 856 assert resp.status_code == 200 848 857 849 858 # Query segments 850 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 859 + resp = env.client.get( 860 + "/app/remote/ingest/segments/20250103", 861 + headers={"Authorization": f"Bearer {key}"}, 862 + ) 851 863 assert resp.status_code == 200 852 864 data = resp.get_json() 853 865 ··· 900 912 assert resp.status_code == 200 901 913 902 914 # Query segments 903 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 915 + resp = env.client.get( 916 + "/app/remote/ingest/segments/20250103", 917 + headers={"Authorization": f"Bearer {key}"}, 918 + ) 904 919 data = resp.get_json() 905 920 906 921 assert len(data) == 1 ··· 945 960 ).unlink() 946 961 947 962 # Query segments 948 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 963 + resp = env.client.get( 964 + "/app/remote/ingest/segments/20250103", 965 + headers={"Authorization": f"Bearer {key}"}, 966 + ) 949 967 data = resp.get_json() 950 968 951 969 assert len(data) == 1 ··· 986 1004 original_path.rename(new_path) 987 1005 988 1006 # Query segments - should detect relocation by inode 989 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 1007 + resp = env.client.get( 1008 + "/app/remote/ingest/segments/20250103", 1009 + headers={"Authorization": f"Bearer {key}"}, 1010 + ) 990 1011 data = resp.get_json() 991 1012 992 1013 assert len(data) == 1 ··· 1047 1068 env.client.delete(f"/app/remote/api/{key_prefix}") 1048 1069 1049 1070 # Query segments - should be rejected 1050 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 1071 + resp = env.client.get( 1072 + "/app/remote/ingest/segments/20250103", 1073 + headers={"Authorization": f"Bearer {key}"}, 1074 + ) 1051 1075 assert resp.status_code == 403 1052 1076 assert "Remote revoked" in resp.get_json()["error"] 1053 1077 ··· 1097 1121 assert resp.get_json()["status"] == "duplicate" 1098 1122 1099 1123 # Query segments - should have only one segment (duplicate was rejected) 1100 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 1124 + resp = env.client.get( 1125 + "/app/remote/ingest/segments/20250103", 1126 + headers={"Authorization": f"Bearer {key}"}, 1127 + ) 1101 1128 data = resp.get_json() 1102 1129 1103 1130 # Should have 1 segment (duplicate rejected, not 2 segments) ··· 1135 1162 assert resp.status_code == 200 1136 1163 1137 1164 # Query segments - should show observed: false 1138 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 1165 + resp = env.client.get( 1166 + "/app/remote/ingest/segments/20250103", 1167 + headers={"Authorization": f"Bearer {key}"}, 1168 + ) 1139 1169 data = resp.get_json() 1140 1170 assert len(data) == 1 1141 1171 assert data[0]["observed"] is False ··· 1148 1178 f.write('{"ts": 1704312345000, "type": "observed", "segment": "120000_300"}\n') 1149 1179 1150 1180 # Query again - should now show observed: true 1151 - resp = env.client.get("/app/remote/ingest/segments/20250103", headers={"Authorization": f"Bearer {key}"}) 1181 + resp = env.client.get( 1182 + "/app/remote/ingest/segments/20250103", 1183 + headers={"Authorization": f"Bearer {key}"}, 1184 + ) 1152 1185 data = resp.get_json() 1153 1186 assert len(data) == 1 1154 1187 assert data[0]["observed"] is True
+2 -1
apps/settings/routes.py
··· 424 424 against the provider API, and stores results in providers.key_validation. 425 425 """ 426 426 try: 427 - from think.providers import PROVIDER_METADATA, validate_key as _validate_key 427 + from think.providers import PROVIDER_METADATA 428 + from think.providers import validate_key as _validate_key 428 429 429 430 config = get_journal_config() 430 431 env_config = config.get("env", {})
+27 -3
apps/todos/tests/test_call.py
··· 395 395 _, src_facet, dst_facet = move_env([{"text": "Draft Q1 plan"}], day="20240102") 396 396 result = runner.invoke( 397 397 call_app, 398 - ["todos", "add", "Draft Q1 plan", "--day", "20240102", "--facet", dst_facet], 398 + [ 399 + "todos", 400 + "add", 401 + "Draft Q1 plan", 402 + "--day", 403 + "20240102", 404 + "--facet", 405 + dst_facet, 406 + ], 399 407 ) 400 408 assert result.exit_code == 1 401 409 assert "Duplicate detected" in result.output ··· 424 432 _, src_facet, dst_facet = move_env([{"text": "Buy groceries"}], day="20240102") 425 433 result = runner.invoke( 426 434 call_app, 427 - ["todos", "add", "Draft Q1 plan", "--day", "20240102", "--facet", dst_facet], 435 + [ 436 + "todos", 437 + "add", 438 + "Draft Q1 plan", 439 + "--day", 440 + "20240102", 441 + "--facet", 442 + dst_facet, 443 + ], 428 444 ) 429 445 assert result.exit_code == 0 430 446 assert "Draft Q1 plan" in result.output ··· 434 450 _, src_facet, dst_facet = move_env([{"text": "Draft Q1 plan"}], day="20240102") 435 451 result = runner.invoke( 436 452 call_app, 437 - ["todos", "add", "Draft Q1 plan", "--day", "20240102", "--facet", dst_facet], 453 + [ 454 + "todos", 455 + "add", 456 + "Draft Q1 plan", 457 + "--day", 458 + "20240102", 459 + "--facet", 460 + dst_facet, 461 + ], 438 462 ) 439 463 assert result.exit_code == 1 440 464 assert "100%" in result.output
+7 -5
apps/transcripts/call.py
··· 145 145 sources = {"transcripts": True, "percepts": False, "agents": True} 146 146 147 147 # Validate mutually exclusive selection modes 148 - mode_count = sum([ 149 - segment is not None, 150 - segments is not None, 151 - start is not None or length is not None, 152 - ]) 148 + mode_count = sum( 149 + [ 150 + segment is not None, 151 + segments is not None, 152 + start is not None or length is not None, 153 + ] 154 + ) 153 155 if mode_count > 1: 154 156 typer.echo( 155 157 "Error: Cannot mix --segment, --segments, and --start/--length.",
-3
convey/bridge.py
··· 11 11 12 12 import json 13 13 import logging 14 - import os 15 14 import threading 16 15 import time 17 16 from typing import Any, Dict, List, Optional ··· 20 19 from simple_websocket import ConnectionClosed 21 20 22 21 from think.callosum import CallosumConnection 23 - 24 - from . import state 25 22 26 23 logger = logging.getLogger(__name__) 27 24
+4 -2
muse/chat_context.py
··· 175 175 return changed 176 176 177 177 178 - def _get_eligible_suggestion(routines_config: dict, journal_config: dict) -> dict | None: 178 + def _get_eligible_suggestion( 179 + routines_config: dict, journal_config: dict 180 + ) -> dict | None: 179 181 """Evaluate 5-gate chain and return the best eligible suggestion, or None.""" 180 182 meta = routines_config.get("_meta", {}) 181 183 ··· 352 354 f"First seen: {suggestion['first_trigger']}\n\n" 353 355 "### Etiquette\n" 354 356 "- Mention this ONCE, naturally, at the end of your response\n" 355 - '- Frame as observation: "I\'ve noticed you often... — would a ' 357 + "- Frame as observation: \"I've noticed you often... — would a " 356 358 'routine help?"\n' 357 359 "- If $name declines or ignores, do not bring it up again this " 358 360 "conversation\n"
+1 -1
observe/remote_cli.py
··· 143 143 print("Remote observer created:") 144 144 print(f" Name: {name}") 145 145 print(f" Prefix: {key[:8]}") 146 - print(f" server url: (set during server configuration)") 146 + print(" server url: (set during server configuration)") 147 147 print(f" api key: {key}") 148 148 return 0 149 149
+1
observe/transcribe/revai.py
··· 33 33 import numpy as np 34 34 import requests 35 35 import soundfile as sf 36 + 36 37 API_BASE = "https://api.rev.ai/speechtotext/v1" 37 38 38 39 # Default configuration
+1 -1
tests/baselines/api/graph/graph.json
··· 615 615 "stats": { 616 616 "co_occurrence_edge_count": 26, 617 617 "explicit_edge_count": 20, 618 - "total_entities": 34, 618 + "total_entities": 33, 619 619 "total_signals": 124 620 620 } 621 621 }
+1 -1
tests/baselines/api/search/day-results.json
··· 14 14 "id": "20260304/agents/knowledge_graph.md:7", 15 15 "idx": 7, 16 16 "path": "20260304/agents/knowledge_graph.md", 17 - "score": -2.6, 17 + "score": -2.0, 18 18 "stream": null, 19 19 "text": "# Part 1: Entity Extraction and Relationship Mapping\n\n## Relationship Mapping\n\n| Source Name | Target Name | Relationship Type | Context |\n| :--- | :--- | :--- | :--- |\n| **Romeo Montague** | **Juliet Capulet** | `met-at-conference` | First <strong>meeting</strong> at Denver Tech Summit keynote. |\n" 20 20 }
+34 -34
tests/baselines/api/search/search.json
··· 85 85 "id": "20260306/default/093000_300/agents/audio.md:0", 86 86 "idx": 0, 87 87 "path": "20260306/default/093000_300/agents/audio.md", 88 - "score": -2.6, 88 + "score": -1.7, 89 89 "stream": "default", 90 90 "text": "# Audio Summary Morning standup. Benvolio noticed <strong>Romeo</strong>'s late-night GitHub activity and pressed him about API gateway commits. <strong>Romeo</strong> deflected, calling it a personal mesh routing prototype. Mercutio covered for him. Balthasar reported progress on the mesh routing fallback PR with an edge case for <strong>Romeo</strong> to review. Benvolio scheduled..." 91 91 }, ··· 101 101 "id": "facets/montague/entities/20260306.jsonl:0", 102 102 "idx": 0, 103 103 "path": "facets/montague/entities/20260306.jsonl", 104 - "score": -3.2, 104 + "score": -2.1, 105 105 "stream": null, 106 106 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nContinued Verona Platform development\n\n" 107 107 }, ··· 117 117 "id": "facets/montague/entities/20260306.jsonl:3", 118 118 "idx": 3, 119 119 "path": "facets/montague/entities/20260306.jsonl", 120 - "score": -3.1, 120 + "score": -2.0, 121 121 "stream": null, 122 122 "text": "### Person: Balthasar Davi\n\n\nReviewed mesh routing PR with <strong>Romeo</strong>\n\n" 123 123 }, ··· 133 133 "id": "facets/montague/entities/20260306.jsonl:4", 134 134 "idx": 4, 135 135 "path": "facets/montague/entities/20260306.jsonl", 136 - "score": -3.2, 136 + "score": -2.0, 137 137 "stream": null, 138 138 "text": "### Person: Mercutio Escalus\n\n\nCovered for <strong>Romeo</strong> during standup\n\n" 139 139 }, ··· 149 149 "id": "20260306/default/093000_300/agents/screen.md:0", 150 150 "idx": 0, 151 151 "path": "20260306/default/093000_300/agents/screen.md", 152 - "score": -2.8, 152 + "score": -1.8, 153 153 "stream": "default", 154 154 "text": "# Screen Summary\n\nSlack standup channel. Benvolio questioning <strong>Romeo</strong> about late-night commits.\n" 155 155 } ··· 174 174 "id": "facets/verona/logs/20260309.jsonl:1", 175 175 "idx": 1, 176 176 "path": "facets/verona/logs/20260309.jsonl", 177 - "score": -2.4, 177 + "score": -1.6, 178 178 "stream": null, 179 179 "text": "### Deploy Complete by <strong>romeo</strong>_montague\n\n**Source:** deploy | **Time:** 13:45:00\n\n**Parameters:**\n- service: verona-gateway\n- version: 0.9.0\n" 180 180 }, ··· 190 190 "id": "20260309/default/090000_300/agents/audio.md:0", 191 191 "idx": 0, 192 192 "path": "20260309/default/090000_300/agents/audio.md", 193 - "score": -2.3, 193 + "score": -1.5, 194 194 "stream": "default", 195 195 "text": "# Audio Summary\n\n<strong>Romeo</strong> confessed the project to Benvolio and asked for infrastructure help. Benvolio agreed to spin up a Kubernetes staging cluster.\n" 196 196 }, ··· 206 206 "id": "facets/montague/entities/20260309.jsonl:0", 207 207 "idx": 0, 208 208 "path": "facets/montague/entities/20260309.jsonl", 209 - "score": -3.1, 209 + "score": -2.0, 210 210 "stream": null, 211 211 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nConfessed project to Benvolio, preparing demo\n\n" 212 212 }, ··· 222 222 "id": "facets/montague/calendar/20260309.jsonl:0", 223 223 "idx": 0, 224 224 "path": "facets/montague/calendar/20260309.jsonl", 225 - "score": -2.6, 225 + "score": -1.7, 226 226 "stream": null, 227 227 "text": "### Event: Team Standup\n\n\n**Time Occurred:** 09:00 - 09:30\n**Participants:** <strong>Romeo</strong> Montague, Benvolio Montague\n\nDaily sync\n" 228 228 }, ··· 238 238 "id": "facets/verona/calendar/20260309.jsonl:0", 239 239 "idx": 0, 240 240 "path": "facets/verona/calendar/20260309.jsonl", 241 - "score": -2.3, 241 + "score": -1.5, 242 242 "stream": null, 243 243 "text": "### Event: Demo Sprint\n\n\n**Time Occurred:** 09:00 - 21:00\n**Participants:** <strong>Romeo</strong> Montague, Juliet Capulet, Benvolio Montague\n\nFull day board presentation preparation\n" 244 244 } ··· 263 263 "id": "20260307/default/100000_300/agents/audio.md:0", 264 264 "idx": 0, 265 265 "path": "20260307/default/100000_300/agents/audio.md", 266 - "score": -3.1, 266 + "score": -2.0, 267 267 "stream": "default", 268 268 "text": "# Audio Summary\n\nHeated confrontation. Tybalt Capulet accused <strong>Romeo</strong> of stealing Capulet IP. Mercutio defended <strong>Romeo</strong> and had his Capulet consulting contract terminated by Tybalt.\n" 269 269 }, ··· 279 279 "id": "20260307/default/150000_300/agents/audio.md:0", 280 280 "idx": 0, 281 281 "path": "20260307/default/150000_300/agents/audio.md", 282 - "score": -3.3, 282 + "score": -2.2, 283 283 "stream": "default", 284 284 "text": "# Audio Summary\n\nEmergency meeting at Montague Tech. Benvolio questioned <strong>Romeo</strong> about the secret project. <strong>Romeo</strong> clarified no company IP was shared. Team discussed legal exposure. <strong>Romeo</strong> proposed Professor Lawrence as mediator.\n" 285 285 }, ··· 295 295 "id": "facets/montague/entities/20260307.jsonl:0", 296 296 "idx": 0, 297 297 "path": "facets/montague/entities/20260307.jsonl", 298 - "score": -3.1, 298 + "score": -2.0, 299 299 "stream": null, 300 300 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nConfronted by Tybalt, called emergency meeting\n\n" 301 301 }, ··· 311 311 "id": "facets/montague/calendar/20260307.jsonl:0", 312 312 "idx": 0, 313 313 "path": "facets/montague/calendar/20260307.jsonl", 314 - "score": -2.4, 314 + "score": -1.5, 315 315 "stream": null, 316 316 "text": "### Event: Emergency Team Meeting\n\n\n**Time Occurred:** 15:00 - 16:00\n**Participants:** <strong>Romeo</strong> Montague, Benvolio Montague\n\nCrisis response to Capulet situation\n" 317 317 }, ··· 327 327 "id": "facets/montague/events/20260307.jsonl:0", 328 328 "idx": 0, 329 329 "path": "facets/montague/events/20260307.jsonl", 330 - "score": -2.9, 330 + "score": -1.9, 331 331 "stream": null, 332 332 "text": "### Meeting: Confrontation with Tybalt\n\n\n**Time Occurred:** 10:00 - 10:30\n**Participants:** <strong>Romeo</strong> Montague, Tybalt Capulet, Mercutio Escalus\n\nTybalt accused <strong>Romeo</strong> of IP theft\n\nMercutio fired from Capulet contract\n" 333 333 } ··· 352 352 "id": "facets/montague/entities/20260308.jsonl:0", 353 353 "idx": 0, 354 354 "path": "facets/montague/entities/20260308.jsonl", 355 - "score": -3.1, 355 + "score": -2.0, 356 356 "stream": null, 357 357 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nUnder board pressure, planning board presentation\n\n" 358 358 }, ··· 368 368 "id": "facets/verona/events/20260308.jsonl:0", 369 369 "idx": 0, 370 370 "path": "facets/verona/events/20260308.jsonl", 371 - "score": -2.1, 371 + "score": -1.3, 372 372 "stream": null, 373 373 "text": "### Meeting: Strategy Call with Professor Lawrence\n\n\n**Time Occurred:** 10:00 - 11:00\n**Participants:** <strong>Romeo</strong> Montague, Juliet Capulet, Friar Lawrence\n\nJoint venture strategy planning\n\nProposed board presentation strategy\n" 374 374 }, ··· 384 384 "id": "20260308/agents/knowledge_graph.md:2", 385 385 "idx": 2, 386 386 "path": "20260308/agents/knowledge_graph.md", 387 - "score": -2.0, 387 + "score": -1.3, 388 388 "stream": null, 389 389 "text": "# Part 1: Entity Extraction and Relationship Mapping ## Entity Profiles | Entity Name | Entity Type | First Appearance | Total Engagement | Context | | :--- | :--- | :--- | :--- | :--- | | **<strong>Romeo</strong> Montague** | Person | 10:00 | High | Under board pressure,..." 390 390 }, ··· 400 400 "id": "20260308/agents/meetings.md:0", 401 401 "idx": 0, 402 402 "path": "20260308/agents/meetings.md", 403 - "score": -2.9, 403 + "score": -1.9, 404 404 "stream": null, 405 405 "text": "# Meetings\n\n- 10:00 Strategy Call with Professor Lawrence, <strong>Romeo</strong>, and Juliet\n" 406 406 } ··· 425 425 "id": "facets/verona/logs/20260305.jsonl:0", 426 426 "idx": 0, 427 427 "path": "facets/verona/logs/20260305.jsonl", 428 - "score": -2.5, 428 + "score": -1.6, 429 429 "stream": null, 430 430 "text": "### Repo Created by <strong>romeo</strong>_montague\n\n**Source:** github | **Time:** 22:05:00\n\n**Parameters:**\n- repo: balcony-app\n- visibility: private\n" 431 431 }, ··· 441 441 "id": "20260305/default/090000_300/agents/audio.md:0", 442 442 "idx": 0, 443 443 "path": "20260305/default/090000_300/agents/audio.md", 444 - "score": -2.9, 444 + "score": -1.9, 445 445 "stream": "default", 446 446 "text": "# Audio Summary\n\nMorning standup at Montague Tech. Benvolio reported CI pipeline is green. <strong>Romeo</strong> mentioned wanting to explore ideas from the conference. Mercutio teased about <strong>Romeo</strong> meeting someone.\n" 447 447 }, ··· 457 457 "id": "facets/montague/entities/20260305.jsonl:0", 458 458 "idx": 0, 459 459 "path": "facets/montague/entities/20260305.jsonl", 460 - "score": -3.1, 460 + "score": -2.0, 461 461 "stream": null, 462 462 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nStarted Balcony App prototype with Juliet\n\n" 463 463 }, ··· 473 473 "id": "facets/verona/entities/20260305.jsonl:0", 474 474 "idx": 0, 475 475 "path": "facets/verona/entities/20260305.jsonl", 476 - "score": -3.1, 476 + "score": -2.0, 477 477 "stream": null, 478 478 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nSet up private repo for collaboration\n\n" 479 479 }, ··· 489 489 "id": "facets/montague/events/20260305.jsonl:0", 490 490 "idx": 0, 491 491 "path": "facets/montague/events/20260305.jsonl", 492 - "score": -3.1, 492 + "score": -2.0, 493 493 "stream": null, 494 494 "text": "### Meeting: Montague Tech Daily Standup\n\n\n**Time Occurred:** 09:00 - 09:30\n**Participants:** <strong>Romeo</strong> Montague, Benvolio Montague, Mercutio Escalus\n\nTeam standup\n\n<strong>Romeo</strong> mentioned conference ideas\n" 495 495 } ··· 514 514 "id": "facets/montague/entities/20260310.jsonl:0", 515 515 "idx": 0, 516 516 "path": "facets/montague/entities/20260310.jsonl", 517 - "score": -2.9, 517 + "score": -1.9, 518 518 "stream": null, 519 519 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nNamed co-lead of Verona Platform joint venture\n\n" 520 520 }, ··· 530 530 "id": "facets/verona/entities/20260310.jsonl:0", 531 531 "idx": 0, 532 532 "path": "facets/verona/entities/20260310.jsonl", 533 - "score": -3.0, 533 + "score": -1.9, 534 534 "stream": null, 535 535 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nNamed co-lead of approved joint venture\n\n" 536 536 }, ··· 546 546 "id": "facets/montague/calendar/20260310.jsonl:0", 547 547 "idx": 0, 548 548 "path": "facets/montague/calendar/20260310.jsonl", 549 - "score": -2.3, 549 + "score": -1.5, 550 550 "stream": null, 551 551 "text": "### Event: Joint Board Meeting\n\n\n**Time Occurred:** 10:00 - 12:00\n**Participants:** <strong>Romeo</strong> Montague, Benvolio Montague\n\nQuarterly review with Verona Platform presentation\n" 552 552 }, ··· 562 562 "id": "facets/verona/calendar/20260310.jsonl:0", 563 563 "idx": 0, 564 564 "path": "facets/verona/calendar/20260310.jsonl", 565 - "score": -2.3, 565 + "score": -1.5, 566 566 "stream": null, 567 567 "text": "### Event: Board Presentation\n\n\n**Time Occurred:** 10:00 - 12:00\n**Participants:** <strong>Romeo</strong> Montague, Juliet Capulet, Friar Lawrence\n\nVerona Platform joint venture pitch\n" 568 568 }, ··· 578 578 "id": "20260310/agents/meetings.md:0", 579 579 "idx": 0, 580 580 "path": "20260310/agents/meetings.md", 581 - "score": -3.0, 581 + "score": -1.9, 582 582 "stream": null, 583 583 "text": "# Meetings\n\n- 08:30 Pre-Board Meeting Prep (<strong>Romeo</strong>, Juliet, Benvolio)\n" 584 584 } ··· 603 603 "id": "20260304/default/180000_300/agents/audio.md:0", 604 604 "idx": 0, 605 605 "path": "20260304/default/180000_300/agents/audio.md", 606 - "score": -2.9, 606 + "score": -1.9, 607 607 "stream": "default", 608 608 "text": "# Audio Summary\n\nEvening mixer at Denver Tech Summit. <strong>Romeo</strong> and Juliet had their first extended conversation about combining their API approaches. Mercutio tried to pull <strong>Romeo</strong> away to karaoke.\n" 609 609 }, ··· 619 619 "id": "facets/capulet/entities/20260304.jsonl:1", 620 620 "idx": 1, 621 621 "path": "facets/capulet/entities/20260304.jsonl", 622 - "score": -3.2, 622 + "score": -2.1, 623 623 "stream": null, 624 624 "text": "### Person: Tybalt Capulet\n\n\nConfronted <strong>Romeo</strong> at hackathon\n\n" 625 625 }, ··· 635 635 "id": "facets/montague/entities/20260304.jsonl:0", 636 636 "idx": 0, 637 637 "path": "facets/montague/entities/20260304.jsonl", 638 - "score": -3.0, 638 + "score": -1.9, 639 639 "stream": null, 640 640 "text": "### Person: <strong>Romeo</strong> Montague\n\n\nAttended Denver Tech Summit, met Juliet Capulet\n\n" 641 641 }, ··· 651 651 "id": "facets/capulet/events/20260304.jsonl:1", 652 652 "idx": 1, 653 653 "path": "facets/capulet/events/20260304.jsonl", 654 - "score": -3.2, 654 + "score": -2.1, 655 655 "stream": null, 656 656 "text": "### Social: Conference Mixer\n\n\n**Time Occurred:** 18:00 - 20:00\n**Participants:** Juliet Capulet, <strong>Romeo</strong> Montague\n\nNetworking event\n\nJuliet and <strong>Romeo</strong> exchanged Signal contacts\n" 657 657 }, ··· 667 667 "id": "facets/montague/events/20260304.jsonl:1", 668 668 "idx": 1, 669 669 "path": "facets/montague/events/20260304.jsonl", 670 - "score": -3.1, 670 + "score": -2.0, 671 671 "stream": null, 672 672 "text": "### Hackathon: Hackathon - API Bridge Challenge\n\n\n**Time Occurred:** 14:00 - 18:00\n**Participants:** <strong>Romeo</strong> Montague, Mercutio Escalus\n\nBuilt API bridge prototype\n\nTybalt confronted <strong>Romeo</strong>\n" 673 673 }
+1 -3
tests/test_activity_state_machine.py
··· 63 63 64 64 sm = ActivityStateMachine() 65 65 sm.update(_sense(content_type="coding"), "090000_300", "20260304") 66 - changes = sm.update( 67 - _sense(content_type="meeting"), "090500_300", "20260304" 68 - ) 66 + changes = sm.update(_sense(content_type="meeting"), "090500_300", "20260304") 69 67 70 68 assert len(changes) == 2 71 69 ended = [c for c in changes if c["state"] == "ended"]
+3 -1
tests/test_awareness.py
··· 1026 1026 def test_self_md_wrapper_still_works(self, tmp_path): 1027 1027 from think.awareness import update_self_md_section 1028 1028 1029 - self_md = "# self\n\n## my name\nsol (default)\n\n## who I'm here for\nTest User\n" 1029 + self_md = ( 1030 + "# self\n\n## my name\nsol (default)\n\n## who I'm here for\nTest User\n" 1031 + ) 1030 1032 (tmp_path / "sol").mkdir(exist_ok=True) 1031 1033 (tmp_path / "sol" / "self.md").write_text(self_md) 1032 1034
+1
tests/test_cogitate_coder.py
··· 177 177 cmd = mock_runner_cls.call_args.kwargs["cmd"] 178 178 assert "--allowed-tools" not in cmd 179 179 180 + 180 181 # --------------------------------------------------------------------------- 181 182 # muse/coder.md existence and frontmatter 182 183 # ---------------------------------------------------------------------------
+7 -2
tests/test_dream_preflight.py
··· 31 31 from think import awareness 32 32 from think.dream import _should_skip_preflight 33 33 34 - monkeypatch.setattr(awareness, "get_onboarding", lambda: {"status": "observing"}) 34 + monkeypatch.setattr( 35 + awareness, "get_onboarding", lambda: {"status": "observing"} 36 + ) 35 37 assert _should_skip_preflight( 36 38 "firstday_checkin", 37 39 day="20240115", ··· 46 48 monkeypatch.setattr( 47 49 awareness, 48 50 "get_onboarding", 49 - lambda: {"status": "complete", "firstday_checkin_sent": "20260402T10:00:00"}, 51 + lambda: { 52 + "status": "complete", 53 + "firstday_checkin_sent": "20260402T10:00:00", 54 + }, 50 55 ) 51 56 assert _should_skip_preflight( 52 57 "firstday_checkin",
+19 -6
tests/test_dream_segment.py
··· 190 190 monkeypatch.setattr( 191 191 dream, 192 192 "get_muse_configs", 193 - lambda schedule=None, **kwargs: _segment_configs("sense", "entities", "screen"), 193 + lambda schedule=None, **kwargs: _segment_configs( 194 + "sense", "entities", "screen" 195 + ), 194 196 ) 195 197 monkeypatch.setattr( 196 198 dream, ··· 238 240 monkeypatch.setattr( 239 241 dream, 240 242 "get_muse_configs", 241 - lambda schedule=None, **kwargs: _segment_configs("sense", "entities", "screen"), 243 + lambda schedule=None, **kwargs: _segment_configs( 244 + "sense", "entities", "screen" 245 + ), 242 246 ) 243 247 monkeypatch.setattr( 244 248 dream, ··· 264 268 265 269 @pytest.mark.parametrize( 266 270 ("has_embeddings", "expected"), 267 - [(False, ["sense", "entities"]), (True, ["sense", "entities", "speaker_attribution"])], 271 + [ 272 + (False, ["sense", "entities"]), 273 + (True, ["sense", "entities", "speaker_attribution"]), 274 + ], 268 275 ) 269 276 def test_conditional_speaker_attribution( 270 277 self, ··· 370 377 monkeypatch.setattr( 371 378 dream, 372 379 "get_muse_configs", 373 - lambda schedule=None, **kwargs: _segment_configs("sense", "entities", "screen"), 380 + lambda schedule=None, **kwargs: _segment_configs( 381 + "sense", "entities", "screen" 382 + ), 374 383 ) 375 384 monkeypatch.setattr( 376 385 dream, ··· 407 416 monkeypatch.setattr( 408 417 dream, 409 418 "get_muse_configs", 410 - lambda schedule=None, **kwargs: _segment_configs("sense", "entities", "pulse"), 419 + lambda schedule=None, **kwargs: _segment_configs( 420 + "sense", "entities", "pulse" 421 + ), 411 422 ) 412 423 monkeypatch.setattr( 413 424 dream, ··· 543 554 segment_dir, 544 555 {"density": "active", "recommend": {}, "facets": []}, 545 556 ) 546 - (segment_dir / "agents" / "entities.md").write_text("entities", encoding="utf-8") 557 + (segment_dir / "agents" / "entities.md").write_text( 558 + "entities", encoding="utf-8" 559 + ) 547 560 548 561 monkeypatch.setattr( 549 562 dream,
+24 -24
tests/test_engage.py
··· 29 29 30 30 assert result.exit_code == 0 31 31 assert "agent-123" in result.output 32 - mock_cr.assert_called_once_with( 33 - prompt="fix the bug", name="coder", config=None 34 - ) 32 + mock_cr.assert_called_once_with(prompt="fix the bug", name="coder", config=None) 35 33 36 34 def test_empty_stdin(self): 37 35 result = _invoke_engage("coder", input_text="") ··· 49 47 assert result.exit_code == 1 50 48 51 49 def test_wait_success(self): 52 - with patch( 53 - "think.cortex_client.cortex_request", return_value="agent-123" 54 - ), patch( 55 - "think.cortex_client.wait_for_agents", 56 - return_value=({"agent-123": "finish"}, []), 57 - ), patch( 58 - "think.cortex_client.read_agent_events", 59 - return_value=[{"event": "finish", "result": "All fixed!"}], 50 + with ( 51 + patch("think.cortex_client.cortex_request", return_value="agent-123"), 52 + patch( 53 + "think.cortex_client.wait_for_agents", 54 + return_value=({"agent-123": "finish"}, []), 55 + ), 56 + patch( 57 + "think.cortex_client.read_agent_events", 58 + return_value=[{"event": "finish", "result": "All fixed!"}], 59 + ), 60 60 ): 61 61 result = _invoke_engage("coder", "--wait", input_text="fix the bug\n") 62 62 ··· 64 64 assert "All fixed!" in result.output 65 65 66 66 def test_wait_error(self): 67 - with patch( 68 - "think.cortex_client.cortex_request", return_value="agent-123" 69 - ), patch( 70 - "think.cortex_client.wait_for_agents", 71 - return_value=({"agent-123": "error"}, []), 67 + with ( 68 + patch("think.cortex_client.cortex_request", return_value="agent-123"), 69 + patch( 70 + "think.cortex_client.wait_for_agents", 71 + return_value=({"agent-123": "error"}, []), 72 + ), 72 73 ): 73 74 result = _invoke_engage("coder", "--wait", input_text="fix the bug\n") 74 75 75 76 assert result.exit_code == 1 76 77 77 78 def test_wait_timeout(self): 78 - with patch( 79 - "think.cortex_client.cortex_request", return_value="agent-123" 80 - ), patch( 81 - "think.cortex_client.wait_for_agents", 82 - return_value=({}, ["agent-123"]), 79 + with ( 80 + patch("think.cortex_client.cortex_request", return_value="agent-123"), 81 + patch( 82 + "think.cortex_client.wait_for_agents", 83 + return_value=({}, ["agent-123"]), 84 + ), 83 85 ): 84 86 result = _invoke_engage("coder", "--wait", input_text="fix the bug\n") 85 87 ··· 113 115 with patch( 114 116 "think.cortex_client.cortex_request", return_value="agent-123" 115 117 ) as mock_cr: 116 - result = _invoke_engage( 117 - "coder", "--facet", "work", input_text="do stuff\n" 118 - ) 118 + result = _invoke_engage("coder", "--facet", "work", input_text="do stuff\n") 119 119 120 120 assert result.exit_code == 0 121 121 mock_cr.assert_called_once_with(
+4 -2
tests/test_entities_hook.py
··· 6 6 from __future__ import annotations 7 7 8 8 import json 9 - from pathlib import Path 10 9 11 10 12 11 def test_entities_post_process_writes_without_segment(tmp_path): ··· 27 26 28 27 entities_path = output_path.parent / "entities.jsonl" 29 28 assert entities_path.exists() 30 - rows = [json.loads(line) for line in entities_path.read_text(encoding="utf-8").splitlines()] 29 + rows = [ 30 + json.loads(line) 31 + for line in entities_path.read_text(encoding="utf-8").splitlines() 32 + ] 31 33 assert rows == [ 32 34 { 33 35 "type": "Person",
+3 -1
tests/test_home_routines.py
··· 189 189 190 190 def test_api_pulse_includes_routines(monkeypatch, home_client): 191 191 """Pulse API includes the routines payload from the context builder.""" 192 - monkeypatch.setattr("apps.home.routes.get_current", lambda: {"capture": {"status": "ok"}}) 192 + monkeypatch.setattr( 193 + "apps.home.routes.get_current", lambda: {"capture": {"status": "ok"}} 194 + ) 193 195 monkeypatch.setattr("apps.home.routes.get_cached_state", lambda: {}) 194 196 monkeypatch.setattr("apps.home.routes._resolve_attention", lambda awareness: None) 195 197 monkeypatch.setattr("apps.home.routes._load_stats", lambda today: {})
+1 -1
tests/test_routines.py
··· 3 3 4 4 """Tests for think.routines — user-defined routines engine.""" 5 5 6 + import importlib.util 6 7 from contextlib import contextmanager 7 8 from datetime import date, datetime, timedelta, timezone 8 - import importlib.util 9 9 from pathlib import Path 10 10 from unittest.mock import patch 11 11
+6 -2
tests/test_sense_splitter.py
··· 134 134 assert (agents_dir / "density.json").exists() 135 135 assert (agents_dir / "sense.json").exists() 136 136 assert (agents_dir / "activity.md").read_text(encoding="utf-8") == "" 137 - assert json.loads((agents_dir / "facets.json").read_text(encoding="utf-8")) == [] 137 + assert ( 138 + json.loads((agents_dir / "facets.json").read_text(encoding="utf-8")) == [] 139 + ) 138 140 density = json.loads((agents_dir / "density.json").read_text(encoding="utf-8")) 139 141 assert density["classification"] == "active" 140 142 ··· 156 158 157 159 agents_dir = seg_dir / "agents" 158 160 assert (agents_dir / "activity.md").read_text(encoding="utf-8") == "" 159 - assert json.loads((agents_dir / "facets.json").read_text(encoding="utf-8")) == [] 161 + assert ( 162 + json.loads((agents_dir / "facets.json").read_text(encoding="utf-8")) == [] 163 + ) 160 164 density = json.loads((agents_dir / "density.json").read_text(encoding="utf-8")) 161 165 assert density["classification"] == "active" 162 166 assert not (agents_dir / "speakers.json").exists()
+11 -7
tests/test_service.py
··· 81 81 82 82 config_dir = tmp_path / "config" 83 83 config_dir.mkdir(exist_ok=True) 84 - (config_dir / "journal.json").write_text(json.dumps({ 85 - "env": { 86 - "ANTHROPIC_API_KEY": "sk-test", 87 - "OPENAI_API_KEY": "sk-openai", 88 - "GOOGLE_API_KEY": "gk-test", 89 - } 90 - })) 84 + (config_dir / "journal.json").write_text( 85 + json.dumps( 86 + { 87 + "env": { 88 + "ANTHROPIC_API_KEY": "sk-test", 89 + "OPENAI_API_KEY": "sk-openai", 90 + "GOOGLE_API_KEY": "gk-test", 91 + } 92 + } 93 + ) 94 + ) 91 95 92 96 env = service._collect_env() 93 97 assert "ANTHROPIC_API_KEY" not in env
+7 -1
tests/test_sol_call.py
··· 514 514 def test_partner_update_section_logs_history(self, journal_with_sol): 515 515 runner.invoke( 516 516 app, 517 - ["partner", "--update-section", "work patterns", "--value", "Morning focus"], 517 + [ 518 + "partner", 519 + "--update-section", 520 + "work patterns", 521 + "--value", 522 + "Morning focus", 523 + ], 518 524 ) 519 525 history = journal_with_sol / "sol" / "history.jsonl" 520 526 assert history.exists()
+1 -3
tests/test_supervisor.py
··· 641 641 start_mock.assert_not_called() 642 642 643 643 644 - def test_supervisor_singleton_lock_blocked_with_health( 645 - tmp_path, monkeypatch, capsys 646 - ): 644 + def test_supervisor_singleton_lock_blocked_with_health(tmp_path, monkeypatch, capsys): 647 645 import fcntl 648 646 649 647 mod = importlib.reload(importlib.import_module("think.supervisor"))
+8 -2
tests/test_validate_key.py
··· 124 124 def test_update_config_saves_key_validation(settings_client): 125 125 client, journal = settings_client 126 126 127 - with patch("think.providers.validate_key", return_value={"valid": False, "error": "bad key"}): 127 + with patch( 128 + "think.providers.validate_key", 129 + return_value={"valid": False, "error": "bad key"}, 130 + ): 128 131 response = client.put( 129 132 "/app/settings/api/config", 130 133 json={"section": "env", "data": {"GOOGLE_API_KEY": "bad-key"}}, ··· 193 196 config_path.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8") 194 197 195 198 def fake_validate(provider: str, api_key: str) -> dict: 196 - return {"valid": provider == "google", "error": "" if provider == "google" else "bad key"} 199 + return { 200 + "valid": provider == "google", 201 + "error": "" if provider == "google" else "bad key", 202 + } 197 203 198 204 with patch("think.providers.validate_key", side_effect=fake_validate): 199 205 response = client.post("/app/settings/api/validate-keys")
+1 -3
think/activity_state_machine.py
··· 24 24 start_time, _end_time = segment_parse(segment_key) 25 25 if start_time is None: 26 26 return None 27 - return ( 28 - start_time.hour * 3600 + start_time.minute * 60 + start_time.second 29 - ) 27 + return start_time.hour * 3600 + start_time.minute * 60 + start_time.second 30 28 31 29 def _parse_segment_end_seconds(self, segment_key: str) -> int | None: 32 30 _start_time, end_time = segment_parse(segment_key)
+12 -5
think/dream.py
··· 17 17 import sys 18 18 import threading 19 19 import time 20 - from datetime import date, datetime, timedelta, timezone 20 + from datetime import date, datetime, timedelta 21 21 from pathlib import Path 22 22 23 23 from think.activities import get_activity_output_path, load_activity_records 24 + from think.activity_state_machine import ActivityStateMachine 24 25 from think.callosum import CallosumConnection 25 26 from think.cluster import cluster_segments 26 27 from think.cortex_client import cortex_request, wait_for_agents ··· 29 30 get_enabled_facets, 30 31 load_segment_facets, 31 32 ) 32 - from think.activity_state_machine import ActivityStateMachine 33 33 from think.muse import get_muse_configs, get_output_path 34 34 from think.runner import run_task 35 35 from think.sense_splitter import write_idle_stubs, write_sense_outputs ··· 434 434 if is_generate 435 435 else f"Running scheduled task for {iso_date(day)}: {day_input_summary(day)}." 436 436 ) 437 - return _cortex_request_with_retry(prompt=prompt, name=name, config=request_config) 437 + return _cortex_request_with_retry( 438 + prompt=prompt, name=name, config=request_config 439 + ) 438 440 439 441 sense_config = _cfg("sense") 440 442 if sense_config is None: ··· 1849 1851 sense_cfg.get("output", "json"), 1850 1852 stream=stream, 1851 1853 ) 1852 - print(f" {step}. sense (gen/{sense_cfg.get('output', 'json')}){status} — mandatory") 1854 + print( 1855 + f" {step}. sense (gen/{sense_cfg.get('output', 'json')}){status} — mandatory" 1856 + ) 1853 1857 step += 1 1854 1858 1855 1859 for name, label in [ 1856 1860 ("entities", "always for non-idle"), 1857 1861 ("screen", "if recommend.screen_record"), 1858 - ("speaker_attribution", "if recommend.speaker_attribution + audio embeddings"), 1862 + ( 1863 + "speaker_attribution", 1864 + "if recommend.speaker_attribution + audio embeddings", 1865 + ), 1859 1866 ("observation", "if onboarding=observing"), 1860 1867 ("firstday_checkin", "if onboarding=complete"), 1861 1868 ("pulse", "if recommend.pulse_update"),
+3 -1
think/providers/google.py
··· 86 86 raise ValueError("GOOGLE_API_KEY not found in environment") 87 87 client = genai.Client( 88 88 api_key=api_key, 89 - http_options=types.HttpOptions(retry_options=types.HttpRetryOptions(attempts=8)), 89 + http_options=types.HttpOptions( 90 + retry_options=types.HttpRetryOptions(attempts=8) 91 + ), 90 92 ) 91 93 return client 92 94
+4 -1
think/service.py
··· 26 26 import subprocess 27 27 import sys 28 28 from pathlib import Path 29 + 29 30 from think.utils import get_journal, get_journal_info 30 31 31 32 SERVICE_LABEL = "org.solpbc.solstone" ··· 90 91 return plistlib.dumps(plist) 91 92 92 93 93 - def _generate_systemd_unit(env: dict[str, str], port: int = DEFAULT_SERVICE_PORT) -> str: 94 + def _generate_systemd_unit( 95 + env: dict[str, str], port: int = DEFAULT_SERVICE_PORT 96 + ) -> str: 94 97 """Generate a systemd user unit for the solstone supervisor.""" 95 98 sol = _sol_bin() 96 99 env_lines = "\n".join(f"Environment={k}={v}" for k, v in sorted(env.items()))
+1 -3
think/tools/routines.py
··· 400 400 suggestions = meta.get("suggestions", {}) 401 401 402 402 if template not in suggestions: 403 - typer.echo( 404 - f"Error: no suggestion state for template '{template}'.", err=True 405 - ) 403 + typer.echo(f"Error: no suggestion state for template '{template}'.", err=True) 406 404 raise typer.Exit(code=1) 407 405 408 406 from datetime import date