forked from Rockachopa/Timmy-time-dashboard
Major:
- Extract all inline <style> blocks from 22 Jinja2 templates into
static/css/mission-control.css — single cacheable stylesheet
- Add tox lint check that fails on inline <style> in templates
Minor:
1. Connection status indicator in topbar (green/amber/red dot) reflecting
WebSocket + Ollama reachability, with auto-reconnect
2. Jinja2 {% macro panel(title) %} in macros.html — eliminates repeated
.card.mc-panel markup; index.html converted as example
3. SVG favicon (purple T + orange dot)
4. 30-second TTL cache on _check_ollama() to avoid blocking the event loop
on every health poll (asyncio.to_thread was already in place)
5. Toast notification system (McToast.show) for transient status messages —
wired into connection status for Ollama/WebSocket state changes
Enforcement:
- CLAUDE.md updated with conventions 11-14 (no inline CSS, use panel macro,
use toasts, never block the event loop)
- tox lint + pre-push environments now fail on inline <style> blocks
https://claude.ai/code/session_014FQ785MQdyJQ4BAXrRSo9w
Co-authored-by: Claude <noreply@anthropic.com>
184 lines
6.4 KiB
Markdown
184 lines
6.4 KiB
Markdown
# CLAUDE.md — AI Assistant Guide for Timmy Time
|
|
|
|
**Tech stack:** Python 3.11+ · FastAPI · Jinja2 + HTMX · SQLite · Agno ·
|
|
Ollama · pydantic-settings · WebSockets · Docker
|
|
|
|
For agent roster and conventions, see [`AGENTS.md`](AGENTS.md).
|
|
|
|
---
|
|
|
|
## Architecture Patterns
|
|
|
|
### Config access
|
|
|
|
```python
|
|
from config import settings
|
|
url = settings.ollama_url # never use os.environ.get() directly in app code
|
|
```
|
|
|
|
### Singletons
|
|
|
|
```python
|
|
from dashboard.store import message_log
|
|
from infrastructure.notifications.push import notifier
|
|
from infrastructure.ws_manager.handler import ws_manager
|
|
```
|
|
|
|
### HTMX response pattern
|
|
|
|
```python
|
|
return templates.TemplateResponse(
|
|
"partials/chat_message.html",
|
|
{"request": request, "role": "user", "content": message}
|
|
)
|
|
```
|
|
|
|
### Graceful degradation
|
|
|
|
Optional services (Ollama, Redis, AirLLM) degrade gracefully — log the error,
|
|
return a fallback, never crash.
|
|
|
|
### Route registration
|
|
|
|
New routes: `src/dashboard/routes/<name>.py` → register in `src/dashboard/app.py`.
|
|
|
|
---
|
|
|
|
## Development Environments (tox)
|
|
|
|
**tox is the single source of truth for all Python environments.**
|
|
Never run `poetry run` directly — always go through tox. All environment
|
|
config (deps, markers, flags) lives in `tox.ini`. The Makefile and CI
|
|
both delegate to tox.
|
|
|
|
### Quick reference
|
|
|
|
```bash
|
|
tox -e unit # Fast unit tests (default pre-commit gate)
|
|
tox -e ci # Full CI suite with coverage + JUnit XML
|
|
tox -e lint # black --check + isort --check + bandit
|
|
tox -e format # Auto-format (black + isort)
|
|
tox -e dev # Start dashboard with auto-reload
|
|
```
|
|
|
|
### All tox environments
|
|
|
|
| Environment | Purpose |
|
|
|---|---|
|
|
| `lint` | Check formatting + imports + security |
|
|
| `format` | Auto-format code |
|
|
| `typecheck` | mypy static analysis |
|
|
| `unit` | Fast unit tests, parallel |
|
|
| `integration` | Integration tests, parallel |
|
|
| `functional` | Functional tests, sequential |
|
|
| `e2e` | End-to-end tests |
|
|
| `fast` | unit + integration combined |
|
|
| `ollama` | Live LLM tests (requires Ollama) |
|
|
| `ci` | Coverage + JUnit XML (mirrors GitHub Actions) |
|
|
| `coverage` | Coverage terminal + XML |
|
|
| `coverage-html` | Coverage HTML report |
|
|
| `pre-push` | Lint + full CI suite (mirrors GitHub Actions exactly) |
|
|
| `dev` | uvicorn with auto-reload |
|
|
| `all` | All tests, parallel |
|
|
|
|
### Testing notes
|
|
|
|
- **Stubs in conftest:** `agno`, `airllm`, `pyttsx3`, `telegram`, `discord`
|
|
stubbed via `sys.modules.setdefault()` — tests run without those packages
|
|
- **Test mode:** `TIMMY_TEST_MODE=1` set automatically in conftest
|
|
- **FastAPI testing:** Use the `client` fixture
|
|
- **Async:** `asyncio_mode = "auto"` — async tests detected automatically
|
|
- **Coverage threshold:** 73% (`fail_under` in `pyproject.toml`)
|
|
|
|
---
|
|
|
|
## Key Conventions
|
|
|
|
1. **Tests must stay green.** Run `tox -e unit` before committing. Run `tox -e pre-push` before pushing (mirrors CI exactly).
|
|
2. **No cloud AI dependencies.** All inference on localhost.
|
|
3. **Keep the root directory clean.** No new top-level files without purpose.
|
|
4. **Follow existing patterns** — singletons, graceful degradation, pydantic config.
|
|
5. **Security defaults:** Never hard-code secrets.
|
|
6. **XSS prevention:** Never use `innerHTML` with untrusted content.
|
|
7. **Keep routes thin** — business logic lives in the module, not the route.
|
|
8. **Prefer editing existing files** over creating new ones.
|
|
9. **Use `from config import settings`** for all env-var access.
|
|
10. **Use tox for everything.** Never run `poetry run` directly — use `tox -e <env>`.
|
|
11. **No inline CSS in templates.** All styles go in `static/style.css` (base theme) or `static/css/mission-control.css` (page-specific). `{% block extra_styles %}` must stay empty. If you need new styles, append them to the appropriate CSS file.
|
|
12. **Use the panel macro** for repeated `.card.mc-panel` markup: `{% from "macros.html" import panel %}` / `{% call panel("TITLE") %}...{% endcall %}`. See `macros.html` for kwargs (id, hx_get, etc.).
|
|
13. **Toast for transient messages.** Use `McToast.show(msg, level)` (info/warn/error) instead of rendering errors inline in the chat log. The toast container lives in `base.html`.
|
|
14. **Never block the event loop.** Wrap synchronous I/O (HTTP calls, file reads) in `asyncio.to_thread()`. Cache health-check results with a TTL when polling external services.
|
|
|
|
---
|
|
|
|
## Frontend Architecture
|
|
|
|
### Stylesheets
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `static/style.css` | Base theme: palette, layout, header, chat, Bootstrap overrides, mobile breakpoints |
|
|
| `static/css/mission-control.css` | Page-specific styles (tasks, briefing, swarm, calm, etc.), toast system, connection indicator |
|
|
|
|
**Rule:** No `<style>` blocks in Jinja2 templates. All CSS lives in the two static files above. The `{% block extra_styles %}` hook exists for emergencies only and must remain empty in committed code.
|
|
|
|
### CSS custom properties
|
|
|
|
Defined in `:root` in `style.css`. Use these — never hard-code colours:
|
|
|
|
```css
|
|
var(--green) var(--amber) var(--red) var(--purple) var(--orange)
|
|
var(--text-bright) var(--text) var(--text-dim)
|
|
var(--bg-deep) var(--bg-panel) var(--bg-card) var(--border)
|
|
```
|
|
|
|
### Jinja2 macros
|
|
|
|
`src/dashboard/templates/macros.html` — reusable components:
|
|
|
|
```jinja2
|
|
{% from "macros.html" import panel %}
|
|
{% call panel("TITLE", hx_get="/endpoint", hx_trigger="every 10s") %}
|
|
<p>Panel body content</p>
|
|
{% endcall %}
|
|
```
|
|
|
|
### Toast notifications (JS)
|
|
|
|
```javascript
|
|
McToast.show('Ollama reconnected', 'info'); // green border
|
|
McToast.show('Connection lost', 'warn'); // amber border
|
|
McToast.show('Request failed', 'error'); // red border
|
|
```
|
|
|
|
---
|
|
|
|
## Security-Sensitive Areas
|
|
|
|
- `src/timmy_serve/` — API server, payment configuration
|
|
- Any file handling secrets or authentication tokens
|
|
|
|
---
|
|
|
|
## Entry Points
|
|
|
|
| Command | Module | Purpose |
|
|
|---------|--------|---------|
|
|
| `timmy` | `src/timmy/cli.py` | Chat, think, status |
|
|
| `timmy-serve` | `src/timmy_serve/cli.py` | API server (port 8402) |
|
|
|
|
---
|
|
|
|
## Module Map (8 packages)
|
|
|
|
| Package | Purpose |
|
|
|---------|---------|
|
|
| `timmy/` | Core agent, personas, agent interface, semantic memory |
|
|
| `dashboard/` | FastAPI web UI, routes, templates |
|
|
| `infrastructure/` | WebSocket, notifications, events, LLM router |
|
|
| `integrations/` | Discord, Telegram, Siri Shortcuts, voice NLU |
|
|
| `spark/` | Event capture and advisory engine |
|
|
| `brain/` | Identity system, memory interface |
|
|
| `timmy_serve/` | API server |
|
|
| `config.py` | Pydantic settings (foundation for all modules) |
|