feat: experiment log append/read utilities and rich viewer

This commit is contained in:
2026-04-04 14:31:45 +02:00
parent 02d44d30be
commit 8fdbd81a05
3 changed files with 133 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
"""Append-only experiment log utilities."""
import json
import os
from datetime import datetime, timezone
LOG_PATH = os.path.expanduser('~/.claude/autoresearch/log.jsonl')
def append_entry(entry: dict, path: str = LOG_PATH) -> None:
entry = dict(entry) # don't mutate caller's dict
entry.setdefault('ts', datetime.now(timezone.utc).isoformat())
os.makedirs(os.path.dirname(os.path.abspath(path)), exist_ok=True)
with open(path, 'a') as f:
f.write(json.dumps(entry) + '\n')
def read_entries(path: str = LOG_PATH) -> list:
if not os.path.exists(path):
return []
entries = []
with open(path) as f:
for line in f:
line = line.strip()
if not line:
continue
try:
entries.append(json.loads(line))
except json.JSONDecodeError:
pass
return entries
+59
View File
@@ -0,0 +1,59 @@
"""Live log viewer for overview pane. Run: python3 bin/log_view.py [--follow]"""
import sys
import time
import os
sys.path.insert(0, os.path.dirname(__file__))
from log_append import read_entries
from rich.console import Console
from rich.table import Table
from rich import box
LOG_PATH = os.path.expanduser('~/.claude/autoresearch/log.jsonl')
console = Console()
def render_table(entries):
table = Table(box=box.SIMPLE, show_header=True, header_style="bold #DA251C")
table.add_column("Time", style="dim", width=8)
table.add_column("Project", width=14)
table.add_column("Exp", width=6)
table.add_column("Description", width=42)
table.add_column("Δ", width=8, justify="right")
table.add_column("", width=2)
for e in entries[-40:]:
ts = (e.get('ts') or '')[11:16] # HH:MM from ISO8601
before = e.get('metric_before')
after = e.get('metric_after')
if before is not None and after is not None:
delta = f"{after - before:+.3f}"
delta_style = "green" if after < before else "red"
else:
delta, delta_style = "n/a", "dim"
kept = "" if e.get('kept') else ""
kept_style = "green" if e.get('kept') else "red"
table.add_row(
ts,
(e.get('project') or '?')[:14],
str(e.get('exp') or '?'),
(e.get('description') or '')[:42],
f"[{delta_style}]{delta}[/{delta_style}]",
f"[{kept_style}]{kept}[/{kept_style}]",
)
return table
if __name__ == '__main__':
follow = '--follow' in sys.argv
while True:
entries = read_entries()
console.clear()
console.print(
f"[bold #DA251C]autoresearch[/bold #DA251C] — {len(entries)} experiments",
justify="center"
)
console.print(render_table(entries))
if not follow:
break
time.sleep(5)