diff --git a/auth-gate.py b/auth-gate.py index f89357f..c53c40a 100644 --- a/auth-gate.py +++ b/auth-gate.py @@ -1,6 +1,12 @@ #!/usr/bin/env python3 """Tiny auth gate for nginx auth_request. Sets a cookie after successful basic auth.""" -import hashlib, hmac, http.server, time, base64, os, sys +import base64 +import hashlib +import hmac +import http.server +import os +import sys +import time SECRET = os.environ.get("AUTH_GATE_SECRET", "") USER = os.environ.get("AUTH_GATE_USER", "") diff --git a/index_research_docs.py b/index_research_docs.py index 6ab2de7..7a25c95 100644 --- a/index_research_docs.py +++ b/index_research_docs.py @@ -1,5 +1,4 @@ -import os import sys from pathlib import Path @@ -8,6 +7,7 @@ sys.path.insert(0, str(Path(__file__).parent / "src")) from timmy.memory_system import memory_store + def index_research_documents(): research_dir = Path("docs/research") if not research_dir.is_dir(): diff --git a/migrations/env.py b/migrations/env.py index 85bb5b3..8a93957 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -1,9 +1,7 @@ from logging.config import fileConfig -from sqlalchemy import engine_from_config -from sqlalchemy import pool - from alembic import context +from sqlalchemy import engine_from_config, pool # this is the Alembic Config object, which provides # access to the values within the .ini file in use. @@ -19,7 +17,7 @@ if config.config_file_name is not None: # from myapp import mymodel # target_metadata = mymodel.Base.metadata from src.dashboard.models.database import Base -from src.dashboard.models.calm import Task, JournalEntry + target_metadata = Base.metadata # other values from the config, defined by the needs of env.py, diff --git a/migrations/versions/0093c15b4bbf_create_task_and_journal_entry_tables.py b/migrations/versions/0093c15b4bbf_create_task_and_journal_entry_tables.py index 9f89edb..587829a 100644 --- a/migrations/versions/0093c15b4bbf_create_task_and_journal_entry_tables.py +++ b/migrations/versions/0093c15b4bbf_create_task_and_journal_entry_tables.py @@ -5,17 +5,16 @@ Revises: Create Date: 2026-03-02 10:57:55.537090 """ -from typing import Sequence, Union +from collections.abc import Sequence -from alembic import op import sqlalchemy as sa - +from alembic import op # revision identifiers, used by Alembic. revision: str = '0093c15b4bbf' -down_revision: Union[str, Sequence[str], None] = None -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None +down_revision: str | Sequence[str] | None = None +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None def upgrade() -> None: diff --git a/scripts/add_pytest_markers.py b/scripts/add_pytest_markers.py index a15eba6..14bfd95 100644 --- a/scripts/add_pytest_markers.py +++ b/scripts/add_pytest_markers.py @@ -5,7 +5,6 @@ Usage: python scripts/add_pytest_markers.py """ -import re from pathlib import Path @@ -93,7 +92,7 @@ def main(): print(f"โญ๏ธ {rel_path:<50} (already marked)") print(f"\n๐Ÿ“Š Total files marked: {marked_count}") - print(f"\nโœจ Pytest markers configured. Run 'pytest -m unit' to test specific categories.") + print("\nโœจ Pytest markers configured. Run 'pytest -m unit' to test specific categories.") if __name__ == "__main__": diff --git a/scripts/apply_security_fixes.py b/scripts/apply_security_fixes.py index 2f4420c..4262936 100644 --- a/scripts/apply_security_fixes.py +++ b/scripts/apply_security_fixes.py @@ -1,8 +1,7 @@ -import os def fix_l402_proxy(): path = "src/timmy_serve/l402_proxy.py" - with open(path, "r") as f: + with open(path) as f: content = f.read() # 1. Add hmac_secret to Macaroon dataclass @@ -132,7 +131,7 @@ if _MACAROON_SECRET_RAW == _MACAROON_SECRET_DEFAULT or _HMAC_SECRET_RAW == _HMAC def fix_xss(): # Fix chat_message.html path = "src/dashboard/templates/partials/chat_message.html" - with open(path, "r") as f: + with open(path) as f: content = f.read() content = content.replace("{{ user_message }}", "{{ user_message | e }}") content = content.replace("{{ response }}", "{{ response | e }}") @@ -142,7 +141,7 @@ def fix_xss(): # Fix history.html path = "src/dashboard/templates/partials/history.html" - with open(path, "r") as f: + with open(path) as f: content = f.read() content = content.replace("{{ msg.content }}", "{{ msg.content | e }}") with open(path, "w") as f: @@ -150,7 +149,7 @@ def fix_xss(): # Fix briefing.html path = "src/dashboard/templates/briefing.html" - with open(path, "r") as f: + with open(path) as f: content = f.read() content = content.replace("{{ briefing.summary }}", "{{ briefing.summary | e }}") with open(path, "w") as f: @@ -158,7 +157,7 @@ def fix_xss(): # Fix approval_card_single.html path = "src/dashboard/templates/partials/approval_card_single.html" - with open(path, "r") as f: + with open(path) as f: content = f.read() content = content.replace("{{ item.title }}", "{{ item.title | e }}") content = content.replace("{{ item.description }}", "{{ item.description | e }}") @@ -168,7 +167,7 @@ def fix_xss(): # Fix marketplace.html path = "src/dashboard/templates/marketplace.html" - with open(path, "r") as f: + with open(path) as f: content = f.read() content = content.replace("{{ agent.name }}", "{{ agent.name | e }}") content = content.replace("{{ agent.role }}", "{{ agent.role | e }}") diff --git a/scripts/backfill_retro.py b/scripts/backfill_retro.py index dbfb688..47a2aee 100644 --- a/scripts/backfill_retro.py +++ b/scripts/backfill_retro.py @@ -8,8 +8,7 @@ from existing history so the LOOPSTAT panel isn't empty. import json import os import re -import subprocess -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path from urllib.request import Request, urlopen @@ -227,7 +226,7 @@ def generate_summary(entries: list[dict]): stats["avg_duration"] = round(stats["total_duration"] / stats["count"]) summary = { - "updated_at": datetime.now(timezone.utc).isoformat(), + "updated_at": datetime.now(UTC).isoformat(), "window": len(recent), "total_cycles": len(entries), "success_rate": round(len(successes) / len(recent), 2) if recent else 0, diff --git a/scripts/benchmarks/run_suite.py b/scripts/benchmarks/run_suite.py index db0fbfe..a23164e 100644 --- a/scripts/benchmarks/run_suite.py +++ b/scripts/benchmarks/run_suite.py @@ -17,7 +17,7 @@ import importlib.util import json import sys import time -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path import requests @@ -216,7 +216,7 @@ def generate_markdown(all_results: dict, run_date: str) -> str: lines.append(f"- **Result:** {bres.get('detail', bres.get('error', 'n/a'))}") snippet = bres.get("code_snippet", "") if snippet: - lines.append(f"- **Generated code snippet:**") + lines.append("- **Generated code snippet:**") lines.append(" ```python") for ln in snippet.splitlines()[:8]: lines.append(f" {ln}") @@ -287,7 +287,7 @@ def parse_args() -> argparse.Namespace: def main() -> int: args = parse_args() - run_date = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC") + run_date = datetime.now(UTC).strftime("%Y-%m-%d %H:%M UTC") print(f"Model Benchmark Suite โ€” {run_date}") print(f"Testing {len(args.models)} model(s): {', '.join(args.models)}") diff --git a/scripts/cycle_retro.py b/scripts/cycle_retro.py index 87b6273..c3209ee 100644 --- a/scripts/cycle_retro.py +++ b/scripts/cycle_retro.py @@ -46,8 +46,7 @@ import argparse import json import re import subprocess -import sys -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent @@ -91,7 +90,7 @@ def _epoch_tag(now: datetime | None = None) -> tuple[str, dict]: When the date rolls over, the counter resets to 1. """ if now is None: - now = datetime.now(timezone.utc) + now = datetime.now(UTC) iso_cal = now.isocalendar() # (year, week, weekday) week = iso_cal[1] @@ -221,7 +220,7 @@ def update_summary() -> None: for k, v in sorted(by_weekday.items())} summary = { - "updated_at": datetime.now(timezone.utc).isoformat(), + "updated_at": datetime.now(UTC).isoformat(), "current_epoch": current_epoch, "window": len(recent), "measured_cycles": len(measured), @@ -293,7 +292,7 @@ def main() -> None: truly_success = args.success and args.main_green # Generate epoch turnover tag - now = datetime.now(timezone.utc) + now = datetime.now(UTC) epoch_tag, epoch_parts = _epoch_tag(now) entry = { diff --git a/scripts/dev_server.py b/scripts/dev_server.py index 0c8db97..8bcac24 100644 --- a/scripts/dev_server.py +++ b/scripts/dev_server.py @@ -11,7 +11,6 @@ Usage: python scripts/dev_server.py [--port PORT] """ import argparse -import datetime import os import socket import subprocess @@ -81,8 +80,8 @@ def _ollama_url() -> str: def _smoke_ollama(url: str) -> str: """Quick connectivity check against Ollama.""" - import urllib.request import urllib.error + import urllib.request try: req = urllib.request.Request(url, method="GET") @@ -101,14 +100,14 @@ def _print_banner(port: int) -> None: hr = "โ”€" * 62 print(flush=True) print(f" {hr}") - print(f" โ”ƒ Timmy Time โ€” Development Server") + print(" โ”ƒ Timmy Time โ€” Development Server") print(f" {hr}") print() print(f" Dashboard: http://localhost:{port}") print(f" API docs: http://localhost:{port}/docs") print(f" Health: http://localhost:{port}/health") print() - print(f" โ”€โ”€ Status โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€") + print(" โ”€โ”€ Status โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€") print(f" Backend: {ollama_url} [{ollama_status}]") print(f" Version: {version}") print(f" Git commit: {git}") diff --git a/scripts/export_trajectories.py b/scripts/export_trajectories.py index 8cdb98f..b3a9df0 100644 --- a/scripts/export_trajectories.py +++ b/scripts/export_trajectories.py @@ -319,9 +319,9 @@ def main(argv: list[str] | None = None) -> int: print(f"Exported {count} training examples to: {args.output}") print() print("Next steps:") - print(f" mkdir -p ~/timmy-lora-training") + print(" mkdir -p ~/timmy-lora-training") print(f" cp {args.output} ~/timmy-lora-training/train.jsonl") - print(f" python scripts/lora_finetune.py --data ~/timmy-lora-training") + print(" python scripts/lora_finetune.py --data ~/timmy-lora-training") else: print("No training examples exported.") return 1 diff --git a/scripts/loop_introspect.py b/scripts/loop_introspect.py index 2af9c7a..46b94c0 100644 --- a/scripts/loop_introspect.py +++ b/scripts/loop_introspect.py @@ -18,9 +18,8 @@ Called by: deep_triage.sh (before the LLM triage), timmy-loop.sh (every 50 cycle from __future__ import annotations import json -import sys from collections import defaultdict -from datetime import datetime, timezone, timedelta +from datetime import UTC, datetime, timedelta from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent @@ -52,7 +51,7 @@ def parse_ts(ts_str: str) -> datetime | None: try: dt = datetime.fromisoformat(ts_str.replace("Z", "+00:00")) if dt.tzinfo is None: - dt = dt.replace(tzinfo=timezone.utc) + dt = dt.replace(tzinfo=UTC) return dt except (ValueError, TypeError): return None @@ -60,7 +59,7 @@ def parse_ts(ts_str: str) -> datetime | None: def window(entries: list[dict], days: int) -> list[dict]: """Filter entries to the last N days.""" - cutoff = datetime.now(timezone.utc) - timedelta(days=days) + cutoff = datetime.now(UTC) - timedelta(days=days) result = [] for e in entries: ts = parse_ts(e.get("timestamp", "")) @@ -344,7 +343,7 @@ def main() -> None: recommendations = generate_recommendations(trends, types, repeats, outliers, triage_eff) insights = { - "generated_at": datetime.now(timezone.utc).isoformat(), + "generated_at": datetime.now(UTC).isoformat(), "total_cycles_analyzed": len(cycles), "trends": trends, "by_type": types, @@ -371,7 +370,7 @@ def main() -> None: header += f" ยท current epoch: {latest_epoch}" print(header) - print(f"\n TRENDS (7d vs previous 7d):") + print("\n TRENDS (7d vs previous 7d):") r7 = trends["recent_7d"] p7 = trends["previous_7d"] print(f" Cycles: {r7['count']:>3d} (was {p7['count']})") @@ -383,14 +382,14 @@ def main() -> None: print(f" PRs merged: {r7['prs_merged']:>3d} (was {p7['prs_merged']})") print(f" Lines net: {r7['lines_net']:>+5d}") - print(f"\n BY TYPE:") + print("\n BY TYPE:") for t, info in sorted(types.items(), key=lambda x: -x[1]["count"]): print(f" {t:12s} n={info['count']:>2d} " f"ok={info['success_rate']*100:>3.0f}% " f"avg={info['avg_duration']//60}m{info['avg_duration']%60:02d}s") if repeats: - print(f"\n REPEAT FAILURES:") + print("\n REPEAT FAILURES:") for rf in repeats[:3]: print(f" #{rf['issue']} failed {rf['failure_count']}x") diff --git a/scripts/lora_finetune.py b/scripts/lora_finetune.py index 049b111..f1b9362 100644 --- a/scripts/lora_finetune.py +++ b/scripts/lora_finetune.py @@ -360,7 +360,7 @@ def main(argv: list[str] | None = None) -> int: return rc # Default: train - print(f"Starting LoRA fine-tuning") + print("Starting LoRA fine-tuning") print(f" Model: {model_path}") print(f" Data: {args.data}") print(f" Adapter path: {args.adapter_path}") diff --git a/scripts/pre_commit_checks.py b/scripts/pre_commit_checks.py index 05f21cd..79034b7 100755 --- a/scripts/pre_commit_checks.py +++ b/scripts/pre_commit_checks.py @@ -9,11 +9,10 @@ This script runs before commits to catch issues early: - Syntax errors in test files """ -import sys -import subprocess -from pathlib import Path import ast -import re +import subprocess +import sys +from pathlib import Path def check_imports(): @@ -70,7 +69,7 @@ def check_test_syntax(): for test_file in tests_dir.rglob("test_*.py"): try: - with open(test_file, "r") as f: + with open(test_file) as f: ast.parse(f.read()) print(f"โœ“ {test_file.relative_to(tests_dir.parent)} has valid syntax") except SyntaxError as e: @@ -86,7 +85,7 @@ def check_platform_specific_tests(): # Check for hardcoded /Users/ paths in tests tests_dir = Path("tests").resolve() for test_file in tests_dir.rglob("test_*.py"): - with open(test_file, "r") as f: + with open(test_file) as f: content = f.read() if 'startswith("/Users/")' in content: issues.append( @@ -110,7 +109,7 @@ def check_docker_availability(): if docker_test_files: for test_file in docker_test_files: - with open(test_file, "r") as f: + with open(test_file) as f: content = f.read() has_skipif = "@pytest.mark.skipif" in content or "pytestmark = pytest.mark.skipif" in content if not has_skipif and "docker" in content.lower(): diff --git a/scripts/test_gabs_connectivity.py b/scripts/test_gabs_connectivity.py index cad3f84..b3e442b 100644 --- a/scripts/test_gabs_connectivity.py +++ b/scripts/test_gabs_connectivity.py @@ -83,8 +83,8 @@ def test_tcp_connection(host: str, port: int, timeout: float) -> tuple[bool, soc return True, sock except OSError as exc: print(f" โœ— Connection failed: {exc}") - print(f" Checklist:") - print(f" - Is Bannerlord running with GABS mod enabled?") + print(" Checklist:") + print(" - Is Bannerlord running with GABS mod enabled?") print(f" - Is port {port} open in Windows Firewall?") print(f" - Is the VM IP correct? (got: {host})") return False, None @@ -92,7 +92,7 @@ def test_tcp_connection(host: str, port: int, timeout: float) -> tuple[bool, soc def test_ping(sock: socket.socket) -> bool: """PASS: JSON-RPC ping returns a 2.0 response.""" - print(f"\n[2/4] JSON-RPC ping") + print("\n[2/4] JSON-RPC ping") try: t0 = time.monotonic() resp = _rpc(sock, "ping", req_id=1) @@ -109,7 +109,7 @@ def test_ping(sock: socket.socket) -> bool: def test_game_state(sock: socket.socket) -> bool: """PASS: get_game_state returns a result (game must be in a campaign).""" - print(f"\n[3/4] get_game_state call") + print("\n[3/4] get_game_state call") try: t0 = time.monotonic() resp = _rpc(sock, "get_game_state", req_id=2) @@ -120,7 +120,7 @@ def test_game_state(sock: socket.socket) -> bool: if code == -32601: # Method not found โ€” GABS version may not expose this method print(f" ~ Method not available ({elapsed_ms:.1f} ms): {msg}") - print(f" This is acceptable if game is not yet in a campaign.") + print(" This is acceptable if game is not yet in a campaign.") return True print(f" โœ— RPC error ({elapsed_ms:.1f} ms) [{code}]: {msg}") return False @@ -191,7 +191,7 @@ def main() -> int: args = parser.parse_args() print("=" * 60) - print(f"GABS Connectivity Test Suite") + print("GABS Connectivity Test Suite") print(f"Target: {args.host}:{args.port}") print(f"Timeout: {args.timeout}s") print("=" * 60) diff --git a/scripts/test_hermes4.py b/scripts/test_hermes4.py index 7c881ca..fcf67cd 100644 --- a/scripts/test_hermes4.py +++ b/scripts/test_hermes4.py @@ -150,7 +150,7 @@ def test_model_available(model: str) -> bool: def test_basic_response(model: str) -> bool: """PASS: model responds coherently to a simple prompt.""" - print(f"\n[2/5] Basic response test") + print("\n[2/5] Basic response test") messages = [ {"role": "user", "content": "Reply with exactly: HERMES_OK"}, ] @@ -188,7 +188,7 @@ def test_memory_usage() -> bool: def test_tool_calling(model: str) -> bool: """PASS: model produces a tool_calls response (not raw text) for a tool-use prompt.""" - print(f"\n[4/5] Tool-calling test") + print("\n[4/5] Tool-calling test") messages = [ { "role": "user", @@ -236,7 +236,7 @@ def test_tool_calling(model: str) -> bool: def test_timmy_persona(model: str) -> bool: """PASS: model accepts a Timmy persona system prompt and responds in-character.""" - print(f"\n[5/5] Timmy-persona smoke test") + print("\n[5/5] Timmy-persona smoke test") messages = [ { "role": "system", diff --git a/scripts/test_timmy_skills.py b/scripts/test_timmy_skills.py index 70b2f6c..e8e58f6 100644 --- a/scripts/test_timmy_skills.py +++ b/scripts/test_timmy_skills.py @@ -26,7 +26,7 @@ import argparse import json import sys import time -from dataclasses import dataclass, field +from dataclasses import dataclass from typing import Any try: diff --git a/scripts/triage_score.py b/scripts/triage_score.py index e2ffdba..13457e2 100644 --- a/scripts/triage_score.py +++ b/scripts/triage_score.py @@ -16,7 +16,7 @@ import json import os import re import sys -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path # โ”€โ”€ Config โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ @@ -277,7 +277,7 @@ def update_quarantine(scored: list[dict]) -> list[dict]: """Auto-quarantine issues that have failed >= 2 times. Returns filtered list.""" failures = load_cycle_failures() quarantine = load_quarantine() - now = datetime.now(timezone.utc).isoformat() + now = datetime.now(UTC).isoformat() filtered = [] for item in scored: @@ -366,7 +366,7 @@ def run_triage() -> list[dict]: backup_data = QUEUE_BACKUP_FILE.read_text() json.loads(backup_data) # Validate backup QUEUE_FILE.write_text(backup_data) - print(f"[triage] Restored queue.json from backup") + print("[triage] Restored queue.json from backup") except (json.JSONDecodeError, OSError) as restore_exc: print(f"[triage] ERROR: Backup restore failed: {restore_exc}", file=sys.stderr) # Write empty list as last resort @@ -377,7 +377,7 @@ def run_triage() -> list[dict]: # Write retro entry retro_entry = { - "timestamp": datetime.now(timezone.utc).isoformat(), + "timestamp": datetime.now(UTC).isoformat(), "total_open": len(all_issues), "scored": len(scored), "ready": len(ready), diff --git a/src/dashboard/app.py b/src/dashboard/app.py index bf26dd6..205b2e0 100644 --- a/src/dashboard/app.py +++ b/src/dashboard/app.py @@ -35,9 +35,9 @@ from dashboard.routes.chat_api_v1 import router as chat_api_v1_router from dashboard.routes.daily_run import router as daily_run_router from dashboard.routes.db_explorer import router as db_explorer_router from dashboard.routes.discord import router as discord_router +from dashboard.routes.energy import router as energy_router from dashboard.routes.experiments import router as experiments_router from dashboard.routes.grok import router as grok_router -from dashboard.routes.energy import router as energy_router from dashboard.routes.health import router as health_router from dashboard.routes.hermes import router as hermes_router from dashboard.routes.loop_qa import router as loop_qa_router @@ -48,6 +48,7 @@ from dashboard.routes.models import router as models_router from dashboard.routes.nexus import router as nexus_router from dashboard.routes.quests import router as quests_router from dashboard.routes.scorecards import router as scorecards_router +from dashboard.routes.self_correction import router as self_correction_router from dashboard.routes.sovereignty_metrics import router as sovereignty_metrics_router from dashboard.routes.sovereignty_ws import router as sovereignty_ws_router from dashboard.routes.spark import router as spark_router @@ -55,7 +56,6 @@ from dashboard.routes.system import router as system_router from dashboard.routes.tasks import router as tasks_router from dashboard.routes.telegram import router as telegram_router from dashboard.routes.thinking import router as thinking_router -from dashboard.routes.self_correction import router as self_correction_router from dashboard.routes.three_strike import router as three_strike_router from dashboard.routes.tools import router as tools_router from dashboard.routes.tower import router as tower_router diff --git a/src/infrastructure/energy/monitor.py b/src/infrastructure/energy/monitor.py index a43ce4a..c2cc97f 100644 --- a/src/infrastructure/energy/monitor.py +++ b/src/infrastructure/energy/monitor.py @@ -19,7 +19,6 @@ Refs: #1009 """ import asyncio -import json import logging import subprocess import time diff --git a/src/infrastructure/models/__init__.py b/src/infrastructure/models/__init__.py index b0b6403..3fbb72e 100644 --- a/src/infrastructure/models/__init__.py +++ b/src/infrastructure/models/__init__.py @@ -24,8 +24,8 @@ from infrastructure.models.registry import ( model_registry, ) from infrastructure.models.router import ( - TierLabel, TieredModelRouter, + TierLabel, classify_tier, get_tiered_router, ) diff --git a/src/infrastructure/models/router.py b/src/infrastructure/models/router.py index 1d05a9d..aee86fd 100644 --- a/src/infrastructure/models/router.py +++ b/src/infrastructure/models/router.py @@ -27,7 +27,6 @@ References: - Issue #882 โ€” Model Tiering Router: Local 8B / Hermes 70B / Cloud API Cascade """ -import asyncio import logging import re import time diff --git a/src/infrastructure/self_correction.py b/src/infrastructure/self_correction.py index e716673..2cfa391 100644 --- a/src/infrastructure/self_correction.py +++ b/src/infrastructure/self_correction.py @@ -20,13 +20,11 @@ Usage:: from __future__ import annotations -import json import logging import sqlite3 import uuid from collections.abc import Generator from contextlib import closing, contextmanager -from datetime import UTC, datetime from pathlib import Path logger = logging.getLogger(__name__) diff --git a/src/timmy/sovereignty/session_report.py b/src/timmy/sovereignty/session_report.py index d034e48..43854c9 100644 --- a/src/timmy/sovereignty/session_report.py +++ b/src/timmy/sovereignty/session_report.py @@ -21,7 +21,6 @@ import base64 import json import logging from datetime import UTC, datetime -from pathlib import Path from typing import Any import httpx diff --git a/src/timmy/thinking/__init__.py b/src/timmy/thinking/__init__.py index 1f2ad80..66d9990 100644 --- a/src/timmy/thinking/__init__.py +++ b/src/timmy/thinking/__init__.py @@ -22,21 +22,20 @@ import sqlite3 from datetime import datetime from pathlib import Path -from timmy.thinking._db import Thought, _get_conn -from timmy.thinking.engine import ThinkingEngine -from timmy.thinking.seeds import ( - SEED_TYPES, - _SENSITIVE_PATTERNS, - _META_OBSERVATION_PHRASES, - _THINK_TAG_RE, - _THINKING_PROMPT, -) - # Re-export HOT_MEMORY_PATH and SOUL_PATH so existing patch targets continue to work. # Tests that patch "timmy.thinking.HOT_MEMORY_PATH" or "timmy.thinking.SOUL_PATH" # should instead patch "timmy.thinking._snapshot.HOT_MEMORY_PATH" etc., but these # re-exports are kept for any code that reads them from the top-level namespace. from timmy.memory_system import HOT_MEMORY_PATH, SOUL_PATH # noqa: F401 +from timmy.thinking._db import Thought, _get_conn +from timmy.thinking.engine import ThinkingEngine +from timmy.thinking.seeds import ( + _META_OBSERVATION_PHRASES, + _SENSITIVE_PATTERNS, + _THINK_TAG_RE, + _THINKING_PROMPT, + SEED_TYPES, +) logger = logging.getLogger(__name__) diff --git a/src/timmy/thinking/_distillation.py b/src/timmy/thinking/_distillation.py index 4adbf07..07c719f 100644 --- a/src/timmy/thinking/_distillation.py +++ b/src/timmy/thinking/_distillation.py @@ -4,7 +4,6 @@ import logging from pathlib import Path from config import settings - from timmy.thinking.seeds import _META_OBSERVATION_PHRASES, _SENSITIVE_PATTERNS logger = logging.getLogger(__name__) diff --git a/src/timmy/thinking/_seeds_mixin.py b/src/timmy/thinking/_seeds_mixin.py index 14aa6c5..76ea74d 100644 --- a/src/timmy/thinking/_seeds_mixin.py +++ b/src/timmy/thinking/_seeds_mixin.py @@ -5,11 +5,11 @@ import random from datetime import UTC, datetime from timmy.thinking.seeds import ( - SEED_TYPES, _CREATIVE_SEEDS, _EXISTENTIAL_SEEDS, _OBSERVATION_SEEDS, _SOVEREIGNTY_SEEDS, + SEED_TYPES, ) logger = logging.getLogger(__name__) diff --git a/src/timmy/thinking/_snapshot.py b/src/timmy/thinking/_snapshot.py index 77d32c4..471312c 100644 --- a/src/timmy/thinking/_snapshot.py +++ b/src/timmy/thinking/_snapshot.py @@ -1,7 +1,7 @@ """System snapshot and memory context mixin for the thinking engine.""" import logging -from datetime import UTC, datetime +from datetime import datetime from timmy.memory_system import HOT_MEMORY_PATH, SOUL_PATH diff --git a/src/timmy/thinking/engine.py b/src/timmy/thinking/engine.py index bbc3256..f616da4 100644 --- a/src/timmy/thinking/engine.py +++ b/src/timmy/thinking/engine.py @@ -7,8 +7,7 @@ from difflib import SequenceMatcher from pathlib import Path from config import settings - -from timmy.thinking._db import Thought, _DEFAULT_DB, _get_conn, _row_to_thought +from timmy.thinking._db import _DEFAULT_DB, Thought, _get_conn, _row_to_thought from timmy.thinking._distillation import _DistillationMixin from timmy.thinking._issue_filing import _IssueFilingMixin from timmy.thinking._seeds_mixin import _SeedsMixin diff --git a/tests/infrastructure/test_graceful_degradation.py b/tests/infrastructure/test_graceful_degradation.py index bc50887..3ff509a 100644 --- a/tests/infrastructure/test_graceful_degradation.py +++ b/tests/infrastructure/test_graceful_degradation.py @@ -27,7 +27,6 @@ from infrastructure.router.cascade import ( ProviderStatus, ) - # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- diff --git a/tests/infrastructure/test_tiered_model_router.py b/tests/infrastructure/test_tiered_model_router.py index 1cd5c03..e29e73f 100644 --- a/tests/infrastructure/test_tiered_model_router.py +++ b/tests/infrastructure/test_tiered_model_router.py @@ -10,13 +10,13 @@ Covers: - "Plan the optimal path to become Hortator" โ†’ LOCAL_HEAVY """ -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest from infrastructure.models.router import ( - TierLabel, TieredModelRouter, + TierLabel, _is_low_quality, classify_tier, get_tiered_router, diff --git a/tests/timmy/test_backlog_triage.py b/tests/timmy/test_backlog_triage.py index 4bc1a79..7ca5690 100644 --- a/tests/timmy/test_backlog_triage.py +++ b/tests/timmy/test_backlog_triage.py @@ -5,7 +5,6 @@ from __future__ import annotations from datetime import UTC, datetime, timedelta from unittest.mock import AsyncMock, MagicMock, patch -import httpx import pytest from timmy.backlog_triage import ( @@ -28,7 +27,6 @@ from timmy.backlog_triage import ( score_issue, ) - # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- diff --git a/tests/timmy/test_kimi_delegation.py b/tests/timmy/test_kimi_delegation.py index 998dfd3..5fd438d 100644 --- a/tests/timmy/test_kimi_delegation.py +++ b/tests/timmy/test_kimi_delegation.py @@ -4,7 +4,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest - # --------------------------------------------------------------------------- # exceeds_local_capacity # --------------------------------------------------------------------------- diff --git a/tests/timmy/test_quest_system.py b/tests/timmy/test_quest_system.py index 3dc7168..6050009 100644 --- a/tests/timmy/test_quest_system.py +++ b/tests/timmy/test_quest_system.py @@ -34,7 +34,6 @@ from timmy.quest_system import ( update_quest_progress, ) - # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- diff --git a/tests/timmy/test_research_tools.py b/tests/timmy/test_research_tools.py index 057b60b..4075b0c 100644 --- a/tests/timmy/test_research_tools.py +++ b/tests/timmy/test_research_tools.py @@ -15,7 +15,6 @@ if "serpapi" not in sys.modules: from timmy.research_tools import get_llm_client, google_web_search # noqa: E402 - # --------------------------------------------------------------------------- # google_web_search # --------------------------------------------------------------------------- diff --git a/tests/timmy/test_session_report.py b/tests/timmy/test_session_report.py index 54f2b73..795d042 100644 --- a/tests/timmy/test_session_report.py +++ b/tests/timmy/test_session_report.py @@ -6,8 +6,7 @@ Refs: #957 (Session Sovereignty Report Generator) import base64 import json import time -from datetime import UTC, datetime -from pathlib import Path +from datetime import UTC from unittest.mock import MagicMock, patch import pytest @@ -18,14 +17,12 @@ from timmy.sovereignty.session_report import ( _format_duration, _gather_session_data, _gather_sovereignty_data, - _render_markdown, commit_report, generate_and_commit_report, generate_report, mark_session_start, ) - # --------------------------------------------------------------------------- # _format_duration # --------------------------------------------------------------------------- diff --git a/tests/timmy/test_tools_search.py b/tests/timmy/test_tools_search.py index dec00f2..602be83 100644 --- a/tests/timmy/test_tools_search.py +++ b/tests/timmy/test_tools_search.py @@ -7,11 +7,8 @@ from __future__ import annotations from unittest.mock import MagicMock, patch -import pytest - from timmy.tools.search import _extract_crawl_content, scrape_url, web_search - # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- diff --git a/tests/timmy_automations/test_orchestrator.py b/tests/timmy_automations/test_orchestrator.py index 7355bd9..deba092 100644 --- a/tests/timmy_automations/test_orchestrator.py +++ b/tests/timmy_automations/test_orchestrator.py @@ -12,9 +12,7 @@ import argparse import json import sys from pathlib import Path -from unittest.mock import MagicMock, patch - -import pytest +from unittest.mock import patch # Add timmy_automations to path for imports _TA_PATH = Path(__file__).resolve().parent.parent.parent / "timmy_automations" / "daily_run" diff --git a/tests/unit/test_airllm_backend.py b/tests/unit/test_airllm_backend.py index 94c1cf8..2b54896 100644 --- a/tests/unit/test_airllm_backend.py +++ b/tests/unit/test_airllm_backend.py @@ -7,7 +7,6 @@ falls back to the Ollama backend without crashing. Refs #1284 """ -import sys from unittest.mock import MagicMock, patch import pytest diff --git a/tests/unit/test_energy_monitor.py b/tests/unit/test_energy_monitor.py index 20858c4..c7a7063 100644 --- a/tests/unit/test_energy_monitor.py +++ b/tests/unit/test_energy_monitor.py @@ -11,11 +11,9 @@ from unittest.mock import MagicMock, patch import pytest from infrastructure.energy.monitor import ( + _DEFAULT_MODEL_SIZE_GB, EnergyBudgetMonitor, InferenceSample, - _DEFAULT_MODEL_SIZE_GB, - _EFFICIENCY_SCORE_CEILING, - _WATTS_PER_GB_HEURISTIC, ) diff --git a/tests/unit/test_self_correction.py b/tests/unit/test_self_correction.py index 98c6a8f..6f941b8 100644 --- a/tests/unit/test_self_correction.py +++ b/tests/unit/test_self_correction.py @@ -1,9 +1,5 @@ """Unit tests for infrastructure.self_correction.""" -import os -import tempfile -from pathlib import Path -from unittest.mock import patch import pytest diff --git a/timmy-benchmark/run_benchmark.py b/timmy-benchmark/run_benchmark.py index 4c8636a..0a28463 100644 --- a/timmy-benchmark/run_benchmark.py +++ b/timmy-benchmark/run_benchmark.py @@ -13,10 +13,9 @@ Usage: import argparse import dataclasses import json -import os import sys import time -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path try: @@ -28,12 +27,14 @@ except ImportError: # Add parent dir to path so levels can be imported sys.path.insert(0, str(Path(__file__).parent)) -from levels import level_0_coin_flip -from levels import level_1_tic_tac_toe -from levels import level_2_resource_mgmt -from levels import level_3_battle_tactics -from levels import level_4_trade_route -from levels import level_5_mini_campaign +from levels import ( + level_0_coin_flip, + level_1_tic_tac_toe, + level_2_resource_mgmt, + level_3_battle_tactics, + level_4_trade_route, + level_5_mini_campaign, +) ALL_LEVELS = [ level_0_coin_flip, @@ -86,7 +87,7 @@ def run_benchmark( levels_to_run = list(range(len(ALL_LEVELS))) print(f"\n{'=' * 60}") - print(f" Timmy Cognitive Benchmark โ€” Project Bannerlord M0") + print(" Timmy Cognitive Benchmark โ€” Project Bannerlord M0") print(f"{'=' * 60}") print(f" Model: {model}") print(f" Levels: {levels_to_run}") @@ -100,7 +101,7 @@ def run_benchmark( "model": model, "skipped": True, "reason": f"Model '{model}' not available", - "timestamp": datetime.now(timezone.utc).isoformat(), + "timestamp": datetime.now(UTC).isoformat(), } else: print(f" ERROR: Model '{model}' not found in Ollama.", file=sys.stderr) @@ -110,7 +111,7 @@ def run_benchmark( results = { "model": model, - "timestamp": datetime.now(timezone.utc).isoformat(), + "timestamp": datetime.now(UTC).isoformat(), "skipped": False, "levels": {}, "summary": {}, diff --git a/timmy_automations/daily_run/golden_path.py b/timmy_automations/daily_run/golden_path.py index 183e45f..de20234 100644 --- a/timmy_automations/daily_run/golden_path.py +++ b/timmy_automations/daily_run/golden_path.py @@ -21,11 +21,10 @@ import json import os import sys from dataclasses import dataclass, field -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path -from typing import Any -from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError +from urllib.request import Request, urlopen # โ”€โ”€ Configuration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ @@ -260,7 +259,7 @@ def score_issue_for_path(issue: dict) -> int: if updated_at: try: updated = datetime.fromisoformat(updated_at.replace("Z", "+00:00")) - days_old = (datetime.now(timezone.utc) - updated).days + days_old = (datetime.now(UTC) - updated).days if days_old < 7: score += 2 elif days_old < 30: @@ -388,7 +387,7 @@ def build_golden_path( 4. One more micro-fix or docs (closure) """ path = GoldenPath( - generated_at=datetime.now(timezone.utc).isoformat(), + generated_at=datetime.now(UTC).isoformat(), target_minutes=target_minutes, ) @@ -478,7 +477,7 @@ def generate_golden_path( if not client.is_available(): # Return empty path with error indication return GoldenPath( - generated_at=datetime.now(timezone.utc).isoformat(), + generated_at=datetime.now(UTC).isoformat(), target_minutes=target_minutes, items=[], ) diff --git a/timmy_automations/daily_run/health_snapshot.py b/timmy_automations/daily_run/health_snapshot.py index 216dcf7..f1abe3c 100755 --- a/timmy_automations/daily_run/health_snapshot.py +++ b/timmy_automations/daily_run/health_snapshot.py @@ -17,11 +17,11 @@ import json import os import sys from dataclasses import dataclass, field -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta from pathlib import Path from typing import Any -from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError +from urllib.request import Request, urlopen # โ”€โ”€ Configuration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ @@ -327,7 +327,7 @@ def check_critical_issues(client: GiteaClient, config: dict) -> IssueSignal: issues=all_critical[:10], # Limit stored issues ) - except (HTTPError, URLError) as exc: + except (HTTPError, URLError): return IssueSignal( count=0, p0_count=0, @@ -419,7 +419,7 @@ def check_token_economy(config: dict) -> TokenEconomySignal: try: # Read last 24 hours of transactions - since = datetime.now(timezone.utc) - timedelta(hours=24) + since = datetime.now(UTC) - timedelta(hours=24) recent_mint = 0 recent_burn = 0 @@ -511,7 +511,7 @@ def generate_snapshot(config: dict, token: str | None) -> HealthSnapshot: overall = calculate_overall_status(ci, issues, flakiness) return HealthSnapshot( - timestamp=datetime.now(timezone.utc).isoformat(), + timestamp=datetime.now(UTC).isoformat(), overall_status=overall, ci=ci, issues=issues, diff --git a/timmy_automations/daily_run/orchestrator.py b/timmy_automations/daily_run/orchestrator.py index b454b87..e055c6e 100755 --- a/timmy_automations/daily_run/orchestrator.py +++ b/timmy_automations/daily_run/orchestrator.py @@ -19,11 +19,11 @@ import argparse import json import os import sys -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta from pathlib import Path from typing import Any -from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError +from urllib.request import Request, urlopen # โ”€โ”€ Token Economy Integration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # Import token rules helpers for tracking Daily Run rewards @@ -31,12 +31,11 @@ from urllib.error import HTTPError, URLError sys.path.insert( 0, str(Path(__file__).resolve().parent.parent) ) -from utils.token_rules import TokenRules, compute_token_reward - # Health snapshot lives in the same package from health_snapshot import generate_snapshot as _generate_health_snapshot from health_snapshot import get_token as _hs_get_token from health_snapshot import load_config as _hs_load_config +from utils.token_rules import TokenRules, compute_token_reward # โ”€โ”€ Configuration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ @@ -284,7 +283,7 @@ def generate_agenda(issues: list[dict], config: dict) -> dict: items.append(item) return { - "generated_at": datetime.now(timezone.utc).isoformat(), + "generated_at": datetime.now(UTC).isoformat(), "time_budget_minutes": agenda_time, "item_count": len(items), "items": items, @@ -322,7 +321,7 @@ def print_agenda(agenda: dict) -> None: def fetch_recent_activity(client: GiteaClient, config: dict) -> dict: """Fetch recent issues and PRs from the lookback window.""" lookback_hours = config.get("lookback_hours", 24) - since = datetime.now(timezone.utc) - timedelta(hours=lookback_hours) + since = datetime.now(UTC) - timedelta(hours=lookback_hours) since_str = since.isoformat() activity = { @@ -399,7 +398,7 @@ def load_cycle_data() -> dict: continue # Get entries from last 24 hours - since = datetime.now(timezone.utc) - timedelta(hours=24) + since = datetime.now(UTC) - timedelta(hours=24) recent = [ e for e in entries if e.get("timestamp") and datetime.fromisoformat(e["timestamp"].replace("Z", "+00:00")) >= since @@ -426,7 +425,7 @@ def load_cycle_data() -> dict: def generate_day_summary(activity: dict, cycles: dict) -> dict: """Generate a day summary from activity data.""" return { - "generated_at": datetime.now(timezone.utc).isoformat(), + "generated_at": datetime.now(UTC).isoformat(), "lookback_hours": 24, "issues_touched": len(activity.get("issues_touched", [])), "issues_closed": len(activity.get("issues_closed", [])), diff --git a/timmy_automations/daily_run/weekly_narrative.py b/timmy_automations/daily_run/weekly_narrative.py index 6fa818c..79eae63 100644 --- a/timmy_automations/daily_run/weekly_narrative.py +++ b/timmy_automations/daily_run/weekly_narrative.py @@ -25,7 +25,6 @@ import sys from collections import Counter from datetime import UTC, datetime, timedelta from pathlib import Path -from typing import Any from urllib.error import HTTPError, URLError from urllib.request import Request, urlopen diff --git a/timmy_automations/retrain/lora_trainer.py b/timmy_automations/retrain/lora_trainer.py index 85c0a3f..3948d53 100644 --- a/timmy_automations/retrain/lora_trainer.py +++ b/timmy_automations/retrain/lora_trainer.py @@ -12,7 +12,6 @@ Refs: #1105 from __future__ import annotations -import json import logging import os import shutil