diff --git a/.opencode/agents/code-editor/SKILL.md b/.opencode/agents/code-editor/SKILL.md
new file mode 100644
index 0000000..bf8d1c9
--- /dev/null
+++ b/.opencode/agents/code-editor/SKILL.md
@@ -0,0 +1,77 @@
+---
+name: code-editor
+description: "Code Editor — scrittura e modifica codice supabase-pinger"
+allowed-tools:
+ - Read
+ - Write
+ - Edit
+ - Glob
+ - Grep
+ - Bash
+---
+
+
+Gestisce scrittura e modifica del codice per il progetto supabase-pinger.
+
+
+
+## File modificabili
+- app.py — FastAPI + logic
+- tests/test_api.py — Test file
+- AGENTS.md — Istruzioni
+
+## Aggiunte possibili
+- Nuovi endpoint API
+- Nuovi test
+- Nuove feature
+
+
+
+1. Leggi contesto current (explorer)
+2. Identifica modification point
+3. Usa Edit tool per modifiche
+4. Verifica con test
+
+
+
+## Aggiungi endpoint API
+Edit in app.py dopo api_status():
+```python
+@app.get("/api/endpoint")
+def new_endpoint():
+ return {...}
+```
+
+## Aggiungi test
+Edit in tests/test_api.py:
+```python
+def test_new_feature():
+ ...
+```
+
+## Modifica configurazione
+Edit in load_config() in app.py
+
+
+
+# Run server
+python app.py
+
+# Run tests
+pytest -q
+
+# Verifica syntax
+python -m py_compile app.py
+
+
+
+- Backup prima di editare
+- Test dopo modifiche
+- Verifica non broken
+
+
+
+- Scrivere nuovo codice
+- Modificare esistente
+- Implementare feature
+
\ No newline at end of file
diff --git a/.opencode/agents/code-explorer/SKILL.md b/.opencode/agents/code-explorer/SKILL.md
new file mode 100644
index 0000000..eaf3700
--- /dev/null
+++ b/.opencode/agents/code-explorer/SKILL.md
@@ -0,0 +1,71 @@
+---
+name: code-explorer
+description: "Code Explorer — ricerca file, pattern, architettura nel progetto supabase-pinger"
+allowed-tools:
+ - Read
+ - Glob
+ - Grep
+ - Task
+---
+
+
+Ricerca file, pattern e analizza l'architettura del progetto supabase-pinger.
+
+
+
+File principali:
+- app.py (421 lines) — FastAPI + ping logic
+- tests/test_api.py — 3 test functions
+- requirements.txt — Dependencies
+
+Componenti chiave:
+- create_app() — FastAPI factory
+- Settings — Config dataclass
+- RRDStore — Circular buffer
+- run_ping() — Keep-alive
+- collector_loop() — Daemon thread
+
+
+
+# Find Python files
+Glob: **/*.py
+
+# Find all config
+Glob: *.md, *.yml, *.txt, *.example
+
+# Search patterns
+Grep: def |class |import
+
+# Find functions
+Grep: "def " app.py
+Grep: "class " app.py
+
+
+
+Prima explora:
+1. app.py — entry point
+2. tests/test_api.py — test structure
+3. AGENTS.md — instructions
+4. requirements.txt — deps
+
+
+
+## Risultati
+### Files trovati
+- path/file.py (N lines)
+
+### Pattern matching
+- line N: code pattern
+
+### Architettura
+- Entry: app.py:create_app()
+- Config: app.py:Settings
+- Storage: app.py:RRDStore
+- Ping: app.py:run_ping()
+
+
+
+- Trovare file specifici
+- Cercare pattern
+- Comprendere architettura
+
\ No newline at end of file
diff --git a/.opencode/agents/code-reviewer/SKILL.md b/.opencode/agents/code-reviewer/SKILL.md
new file mode 100644
index 0000000..efaf95f
--- /dev/null
+++ b/.opencode/agents/code-reviewer/SKILL.md
@@ -0,0 +1,86 @@
+---
+name: code-reviewer
+description: "Code Reviewer — bug, security, quality per supabase-pinger"
+allowed-tools:
+ - Read
+ - Write
+ - Glob
+ - Grep
+ - Bash
+ - Task
+---
+
+
+Revisiona il codice per bug, security vulnerabilities e quality issues.
+
+
+
+## Area di Review
+- Bug detection
+- Security (SQL, auth)
+- Code quality
+- Error handling
+- Performance
+- Resource cleanup
+
+
+
+| Level | Description |
+|-------|-----------|
+| CRITICAL | Security, data loss |
+| HIGH | Crash, breakage |
+| MEDIUM | Quality, perf |
+| LOW | Style |
+
+
+
+## Core Files
+- app.py (421 lines)
+- tests/test_api.py
+
+## Check For
+### SQL/DB
+- psycopg2 usage — parametrize queries
+- conn.close() in finally
+- connect_timeout
+
+### Error Handling
+- try/except blocks
+- Exception types
+- Graceful failures
+
+### Security
+- No secrets in logs
+- No hardcoded creds
+- Input validation
+
+
+
+# Run tests
+pytest -q
+
+# Syntax check
+python -m py_compile app.py
+
+# Import check
+python -c "from app import *"
+
+
+
+## Findings
+| File | Line | Issue | Severity |
+|------|------|-------|----------|
+| app.py | N | issue | HIGH |
+
+## Summary
+- CRITICAL: N
+- HIGH: N
+- MEDIUM: N
+- LOW: N
+
+
+
+- Dopo modifiche
+- Prima di commit
+- Richiesta review
+
\ No newline at end of file
diff --git a/.opencode/agents/master-orchestrator/SKILL.md b/.opencode/agents/master-orchestrator/SKILL.md
new file mode 100644
index 0000000..9eb56bc
--- /dev/null
+++ b/.opencode/agents/master-orchestrator/SKILL.md
@@ -0,0 +1,82 @@
+---
+name: master-orchestrator
+description: "Master Orchestrator supabase-pinger — analizza, pianifica, cerca skill, coordina sub-agenti"
+allowed-tools:
+ - Read
+ - Write
+ - Glob
+ - Grep
+ - Bash
+ - Task
+ - AskUserQuestion
+ - skill
+---
+
+
+Brain center del sistema multi-agente. Analizza richieste complesse, pianifica attività, cerca skill via mcp universal-skills-manager, assegna a sub-agenti esecutori e coordina il lavoro.
+
+
+
+- **Analisi**: Comprende la richiesta dell'utente
+- **Pianificazione**: Breakdown in step eseguibili
+- **Skill Research**: Trova skill appropriate via mcp
+- **Assegnazione**: Invia a sub-agenti
+- **Coordinamento**: Gestisce il workflow completo
+
+
+
+## Phase 1: Analisi Input
+1. Parsea la richiesta utente
+2. Identifica task type (explore, write, review, test, plan)
+3. Determina complexity level
+
+## Phase 2: Skill Research (via mcp)
+1. Carica universal-skills-manager
+2. Cerca skill per task type
+3. Seleziona skill appropriate
+
+## Phase 3: Pianificazione
+1. Breakdown task in step
+2. Definisci dependencies
+3. Assegna a sub-agenti
+
+## Phase 4: Esecuzione
+1. Spawn sub-agenti con skill
+2. Coordina parallel/sequential
+3. Aggrega risultati
+
+## Phase 5: Reporting
+1. Sintesi risultati
+2. Next actions raccomandate
+
+
+
+## MCP Universal Skills Manager
+Carica skill: `/skill universal-skills-manager`
+
+Cerca skill con:
+- Task type = exploration → cerca "code exploration"
+- Task type = write → cerca "code execution"
+- Task type = review → cerca "code review"
+
+Seleziona basato su:
+- compatibility (OpenCode)
+- description relevance
+
+
+
+| Task Type | Sub-Agent | Skill |
+|----------|----------|-------|
+| Explore | code-explorer | gsd-explore |
+| Write | code-editor | gsd-fast |
+| Review | code-reviewer | gsd-code-review |
+| Test | test-runner | gsd-tester |
+| Plan | task-planner | gsd-plan-phase |
+
+
+
+- Richieste complesse multi-step
+- Need skill research via mcp
+- Coordinamento multi-agente
+- Task ambiguity
+
\ No newline at end of file
diff --git a/.opencode/agents/skill-researcher/SKILL.md b/.opencode/agents/skill-researcher/SKILL.md
new file mode 100644
index 0000000..0a676fa
--- /dev/null
+++ b/.opencode/agents/skill-researcher/SKILL.md
@@ -0,0 +1,69 @@
+---
+name: skill-researcher
+description: "Skill Researcher — cerca skill via mcp universal-skills-manager"
+allowed-tools:
+ - Read
+ - Bash
+ - skill
+ - AskUserQuestion
+---
+
+
+Cerca skill appropriate via mcp universal-skills-manager per eseguire task specifici.
+
+
+
+Carica skill universale:
+```bash
+/skill universal-skills-manager
+```
+
+Cerca con i tool disponibili:
+- Search SkillsMP (richiede API key)
+- Search SkillHub (no key)
+- Search ClawHub (no key, semantic)
+
+
+
+## Step 1: Select Source
+Se SkillsMP key disponibile → AI semantic search
+Altrimenti → SkillHub o ClawHub
+
+## Step 2: Execute Search
+Cerca per task type:
+- "code exploration" → gsd-explore, code search
+- "code execution" → gsd-fast, code write
+- "code review" → gsd-code-review, bug detection
+- "testing" → test execution
+
+## Step 3: Analyze Results
+- Mostra top 5 risultati
+- Verifica compatibilità OpenCode
+- Considera stars/quality
+
+## Step 4: Selection
+Proponi skill migliore all'utente
+
+
+
+# Cerca skill exploration
+curl -X GET "https://clawhub.ai/api/v1/search?q=code+exploration&limit=5" \
+ -H "User-Agent: supabase-pinger-agents"
+
+# Cerca skill execution
+curl -X GET "https://clawhub.ai/api/v1/search?q=code+execution&limit=5" \
+ -H "User-Agent: supabase-pinger-agents"
+
+
+
+
+
+- Quando servono skill esterne
+- Prima di assegnare task
+- Ricerca best practices
+
\ No newline at end of file
diff --git a/.opencode/agents/task-planner/SKILL.md b/.opencode/agents/task-planner/SKILL.md
new file mode 100644
index 0000000..3f5d4ff
--- /dev/null
+++ b/.opencode/agents/task-planner/SKILL.md
@@ -0,0 +1,62 @@
+---
+name: task-planner
+description: "Task Planner — breakdown task in step eseguibili"
+allowed-tools:
+ - Read
+ - Write
+ - Task
+ - AskUserQuestion
+---
+
+
+Analizza task complessi e li scompone in step eseguibili Assign a sub-agenti appropriati.
+
+
+
+## Goal-Backward Planning
+1. Definisci goal finale
+2. Identifica step necessari
+3. Ordina per dependencies
+4. Assegna a sub-agents
+
+
+
+## Task Types
+| Type | Sub-agents needed |
+|------|---------------|
+| Explore | explorer |
+| Write | editor |
+| Write+Test | editor, tester |
+| Review | reviewer |
+| Full Feature | planner → editor → reviewer → tester |
+
+## Complexity Levels
+- **Triviale**: 1 step, 1 agent
+- **Normale**: 2-3 steps, parallelizable
+- **Complesso**: 4+ steps, sequenziali
+
+
+
+## Input: "Aggiungi endpoint /api/health"
+Output:
+1. [explorer] Trova struttura API attuale
+2. [editor] Aggiungi endpoint in app.py
+3. [reviewer] Verifica implementazione
+4. [tester] Esegui test
+
+
+
+## Plan
+| Step | Agent | Action | Dependencies |
+|------|-------|--------|-------------|
+| 1 | explorer | Trova API | None |
+| 2 | editor | Aggiungi endpoint | Step 1 |
+| 3 | reviewer | Review code | Step 2 |
+| 4 | tester | Run tests | Step 2 |
+
+
+
+- Task multi-step
+- Pianificazione nuove feature
+- Coordinamento complesso
+
\ No newline at end of file
diff --git a/.opencode/agents/test-runner/SKILL.md b/.opencode/agents/test-runner/SKILL.md
new file mode 100644
index 0000000..eb89eae
--- /dev/null
+++ b/.opencode/agents/test-runner/SKILL.md
@@ -0,0 +1,80 @@
+---
+name: test-runner
+description: "Test Runner — esegue test e verifica per supabase-pinger"
+allowed-tools:
+ - Read
+ - Write
+ - Bash
+ - Glob
+---
+
+
+Esegue test e verifica l'implementazione del progetto supabase-pinger.
+
+
+
+Framework: pytest
+Test file: tests/test_api.py (3 test functions)
+Config: tests/conftest.py
+
+
+
+| Test | Funzione |
+|------|----------|
+| test_swagger_and_openapi_available | Verifica /docs, /openapi.json |
+| test_history_api_window_and_ring_buffer | Test buffer circolare |
+| test_status_api_when_no_samples | Test stato iniziale |
+
+
+
+## Run all tests
+pytest -q
+
+## Run verbose
+pytest -v
+
+## Run specific
+pytest tests/test_api.py::test_name -v
+
+## Run with coverage
+pytest --cov=app
+
+
+
+## Configurazione test (in conftest.py)
+config_override in create_app()
+start_collector=False
+
+## No DB richiesto
+SQLite in temp directories
+
+
+
+# Verify imports
+python -c "from app import create_app, app, Settings"
+
+# Syntax check
+python -m py_compile app.py
+
+# Docker build
+docker build -t supabase-pinger .
+
+
+
+## Test Results
+```
+pytest -q
+... 3 passed
+```
+
+## Verification
+- Syntax: OK
+- Imports: OK
+- Tests: N/N passed
+
+
+
+- Dopo codice modificato
+- Prima di commit
+- Verifica funzionalità
+
\ No newline at end of file
diff --git a/.opencode/agents/ui-designer/SKILL.md b/.opencode/agents/ui-designer/SKILL.md
new file mode 100644
index 0000000..2c4271c
--- /dev/null
+++ b/.opencode/agents/ui-designer/SKILL.md
@@ -0,0 +1,99 @@
+---
+name: ui-designer
+description: "UI Designer — design system, componenti, UI-SPEC per supabase-pinger"
+allowed-tools:
+ - Read
+ - Write
+ - Edit
+ - Glob
+ - Bash
+---
+
+
+Crea design system e componenti UI coerenti per il progetto supabase-pinger.
+
+
+
+## Supabase Pinger Brand
+- Mission: Monitoraggio database
+- Visual identity: Dark, technical, monitoring
+
+## Color Palette
+```
+Primary: #3ecf8e (green)
+Danger: #ff6b6b (red)
+Background: #101418
+Surface: #17202a
+Text: #edf2f7
+Muted: #9fb3c8
+```
+
+## Typography
+- Font: Segoe UI, system-ui
+- Hierarchy: H1, H2, body, meta
+
+## Spacing
+- Base unit: 4px
+- Common: 8px, 16px, 24px
+
+
+
+## Core Components
+1. **StatusBadge** — UP/DOWN/N/A states
+2. **LatencyChart** — Chart.js line chart
+3. **MetricPanel** — Stats display
+4. **TimelineGraph** — SmokePing style
+
+## Component Specs
+```html
+
+UP|DOWN
+
+
+
+```
+
+
+
+## Tailwind Integration
+Carica skill: tailwindcss-development
+
+Genera componenti con utility classes:
+- bg-*, text-*, p-*, m-*
+- flex, grid layouts
+- responsive prefixes
+
+## CSS Variables
+```css
+:root {
+ --primary: #3ecf8e;
+ --danger: #ff6b6b;
+ --bg: #101418;
+ --surface: #17202a;
+}
+```
+
+
+
+## Output Files
+- .planning/ui/UI-SPEC.md
+- app.py (dashboard HTML)
+- CSS inline o file
+
+## UI-SPEC.md Structure
+1. Concept & Vision
+2. Design Language
+3. Layout & Structure
+4. Features & Interactions
+5. Component Inventory
+6. Technical Approach
+
+
+
+- Creare nuove UI
+- Design system setup
+- Component development
+
\ No newline at end of file
diff --git a/.opencode/agents/ui-expert/SKILL.md b/.opencode/agents/ui-expert/SKILL.md
new file mode 100644
index 0000000..130042a
--- /dev/null
+++ b/.opencode/agents/ui-expert/SKILL.md
@@ -0,0 +1,65 @@
+---
+name: ui-expert
+description: "UI/UX Expert — orchestratore team design supabase-pinger"
+allowed-tools:
+ - Read
+ - Write
+ - Task
+ - AskUserQuestion
+---
+
+
+Orchestratore del team UX/UI. Coordina gli specialisti per creare interfacce user-friendly e design system coerenti.
+
+
+
+| Sub-Agent | Specializzazione |
+|----------|---------------|
+| ui-explorer | Analisi UI esistenti, competitor |
+| ui-designer | Design system, componenti |
+| ui-reviewer | Audit 6-pillar UI quality |
+| ui-tester | Testing UI con Playwright |
+
+
+
+## Phase 1: Context Gathering
+1. ui-explorer → analizza UI attuale
+2. Identifica pain points
+
+## Phase 2: Design
+1. ui-designer → crea design system
+2. Genera UI-SPEC.md
+3. Implementa componenti
+
+## Phase 3: Review
+1. ui-reviewer → 6-pillar audit
+2. Identifica issues
+
+## Phase 4: Testing
+1. ui-tester → Playwright tests
+2. Verifica responsiveness
+
+
+<6_pillars>
+1. **Visual Design** — Colors, typography, spacing
+2. **Accessibility** — WCAG compliance
+3. **Responsiveness** — Mobile/desktop
+4. **Performance** — Load time, interactions
+5. **UX Flow** — User journey clarity
+6. **Consistency** — Design system adherence
+6_pillars>
+
+
+Skill disponibili:
+- tailwind-design-system
+- tailwindcss-development
+- gsd-ui-phase
+- gsd-ui-review
+
+
+
+- Nuove feature UI
+- Redesign dashboard
+- Design system creation
+- UX audit
+
\ No newline at end of file
diff --git a/.opencode/agents/ui-explorer/SKILL.md b/.opencode/agents/ui-explorer/SKILL.md
new file mode 100644
index 0000000..719bc2c
--- /dev/null
+++ b/.opencode/agents/ui-explorer/SKILL.md
@@ -0,0 +1,84 @@
+---
+name: ui-explorer
+description: "UI Explorer — analizza interfacce esistenti, competitor, pattern"
+allowed-tools:
+ - Read
+ - Glob
+ - Grep
+ - Bash
+ - playwright_browser_snapshot
+---
+
+
+Analizza le interfacce esistenti del progetto e identifica pattern e competitor di riferimento.
+
+
+
+## File UI nel progetto
+- app.py → _build_dashboard_html() (riga 245-340)
+- HTML inline nel codice Python
+
+## Pattern da cercare
+- HTML templates
+- CSS classes
+- JavaScript (Chart.js)
+- Responsive design
+
+
+
+## HTML Analysis
+- Semantic structure
+- Accessibility (a11y)
+- SEO structure
+
+## CSS Analysis
+- Color palette
+- Typography
+- Spacing system
+- Component patterns
+
+## JS Analysis
+- Chart.js usage
+- Data fetching
+- Event handlers
+
+
+
+Dashboard attuale supabase-pinger:
+- SmokePing-style visualization
+- Chart.js per grafici latenza
+- Dark theme con gradient
+- Badge status (UP/DOWN)
+
+
+
+## SmokePing References
+- latency monitoring
+- RRD-style graphs
+- status indicators
+
+## Similar dashboards
+- Grafana
+- Datadog
+- CloudWatch
+
+
+
+## UI Analysis
+### Current State
+- Files: ...
+- Patterns: ...
+- Tech stack: ...
+
+### Pain Points
+- List issues found
+
+### Recommendations
+- Improvement suggestions
+
+
+
+- Prima di redesign
+- Analisi competitor
+- Identificare pattern
+
\ No newline at end of file
diff --git a/.opencode/agents/ui-reviewer/SKILL.md b/.opencode/agents/ui-reviewer/SKILL.md
new file mode 100644
index 0000000..83f3faf
--- /dev/null
+++ b/.opencode/agents/ui-reviewer/SKILL.md
@@ -0,0 +1,109 @@
+---
+name: ui-reviewer
+description: "UI Reviewer — audit 6-pillar visual qualità per supabase-pinger"
+allowed-tools:
+ - Read
+ - Write
+ - Glob
+ - Bash
+ - playwright_browser_snapshot
+---
+
+
+Audit visivo 6-pillar per verificare la qualità UI del progetto supabase-pinger.
+
+
+<6_pillars_audit>
+## 1. Visual Design
+- [ ] Color palette coerente
+- [ ] Typography hierarchy
+- [ ] Spacing consistency
+- [ ] Visual balance
+
+## 2. Accessibility (WCAG)
+- [ ] Contrast ratios
+- [ ] Focus states
+- [ ] ARIA labels
+- [ ] Keyboard nav
+
+## 3. Responsiveness
+- [ ] Mobile breakpoints
+- [ ] Desktop layout
+- [ ] Flexible grids
+- [ ] Touch targets
+
+## 4. Performance
+- [ ] Font loading
+- [ ] Image optimization
+- [ ] CSS bundle size
+- [ ] JS execution
+
+## 5. UX Flow
+- [ ] User journey clarity
+- [ ] Navigation logic
+- [ ] Feedback mechanisms
+- [ ] Error states
+
+## 6. Consistency
+- [ ] Design system adherence
+- [ ] Component patterns
+- [ ] Interaction patterns
+- [ ] Language/style
+6_pillars_audit>
+
+
+| Pillar | Score | Max |
+|--------|-------|-----|
+| Visual Design | /10 | 10 |
+| Accessibility | /10 | 10 |
+| Responsiveness | /10 | 10 |
+| Performance | /10 | 10 |
+| UX Flow | /10 | 10 |
+| Consistency | /10 | 10 |
+| **TOTAL** | /60 | 60 |
+
+Pass threshold: 48/60 (80%)
+
+
+
+## Files to Review
+- app.py → _build_dashboard_html()
+- Inline CSS styles
+- Chart.js integration
+
+## Focus Areas
+- Dark theme consistency
+- Status badges
+- Chart visualization
+- Mobile experience
+
+
+
+## UI-REVIEW.md
+### Scores
+| Pillar | Score |
+|--------|-------|
+| Visual | X/10 |
+| A11y | X/10 |
+| Responsive | X/10 |
+| Perf | X/10 |
+| UX | X/10 |
+| Consistent | X/10 |
+| **Total** | X/60 |
+
+### Findings
+- BLOCK: Critical issues
+- FLAG: Warnings
+- PASS: Good practices
+
+
+
+Usa gsd-ui-review per audit automatico
+Carica skill: tailwind-design-system
+
+
+
+- Dopo implementazione UI
+- Prima di deploy
+- Post redesign
+
\ No newline at end of file
diff --git a/.opencode/agents/ui-tester/SKILL.md b/.opencode/agents/ui-tester/SKILL.md
new file mode 100644
index 0000000..ed26a85
--- /dev/null
+++ b/.opencode/agents/ui-tester/SKILL.md
@@ -0,0 +1,113 @@
+---
+name: ui-tester
+description: "UI Tester — testing UI con Playwright per supabase-pinger"
+allowed-tools:
+ - Read
+ - Write
+ - Bash
+ - playwright_browser_navigate
+ - playwright_browser_snapshot
+ - playwright_browser_take_screenshot
+ - playwright_browser_click
+ - playwright_browser_type
+---
+
+
+Testa le interfacce UI del progetto supabase-pinger usando Playwright.
+
+
+
+| Tool | Uso |
+|------|-----|
+| playwright_browser_navigate | Apri URL |
+| playwright_browser_snapshot | Analizza page structure |
+| playwright_browser_take_screenshot | Screenshot visual |
+| playwright_browser_click | Interazioni |
+| playwright_browser_type | Form input |
+
+
+
+## Dashboard Tests
+1. **Load test**
+ - Navigate to /
+ - Verify title
+ - Check for errors
+
+2. **Status badge test**
+ - Check statusBadge element
+ - Verify UP/DOWN/N/A states
+
+3. **Chart test**
+ - Verify Chart.js canvas
+ - Check data loading
+
+4. **Responsive test**
+ - Desktop (1920x1080)
+ - Tablet (768x1024)
+ - Mobile (375x667)
+
+## API Tests
+5. **API endpoint test**
+ - GET /api/status
+ - GET /api/history
+ - Verify JSON response
+
+## Swagger Tests
+6. **Docs accessibility**
+ - GET /docs
+ - Verify Swagger UI loads
+
+
+
+## Breakpoints
+- Mobile: 375px (iPhone SE)
+- Tablet: 768px (iPad)
+- Desktop: 1920px (Full HD)
+
+## Responsive checks
+- Layout shifts
+- Font sizes
+- Touch targets
+- Scroll behavior
+
+
+
+## Run dashboard test
+playwright_browser_navigate: http://localhost:8080
+
+## Screenshot
+playwright_browser_take_screenshot
+
+## Analyze structure
+playwright_browser_snapshot
+
+## Run server for testing
+python app.py
+# Oppure
+docker run -p 8080:8080 supabase-pinger
+
+
+
+## Results Format
+```
+Dashboard Load: PASS/FAIL
+Status Badge: PASS/FAIL
+Chart Visible: PASS/FAIL
+Mobile Layout: PASS/FAIL
+Tablet Layout: PASS/FAIL
+Desktop Layout: PASS/FAIL
+API /status: PASS/FAIL
+API /history: PASS/FAIL
+```
+
+## Screenshots
+- dashboard-desktop.png
+- dashboard-mobile.png
+- dashboard-tablet.png
+
+
+
+- Dopo modifiche UI
+- Test responsive
+- Verifica visual regression
+
\ No newline at end of file
diff --git a/.opencode/agents/work-coordinator/SKILL.md b/.opencode/agents/work-coordinator/SKILL.md
new file mode 100644
index 0000000..218900d
--- /dev/null
+++ b/.opencode/agents/work-coordinator/SKILL.md
@@ -0,0 +1,67 @@
+---
+name: work-coordinator
+description: "Work Coordinator — assegnazione e coordinamento sub-agenti"
+allowed-tools:
+ - Read
+ - Write
+ - Task
+ - AskUserQuestion
+---
+
+
+Assegna task a sub-agenti esecutori e coordina l'esecuzione parallela e sequenziale.
+
+
+| Mode | Description | Use Case |
+|------|-------------|---------|
+| Sequential | Agent B dopo A | Dependencies |
+| Parallel | A + B insieme | Indipendenti |
+| Wave | A → wait → B → wait → C | Iterative |
+
+
+
+| Step | Agent | Task |
+|------|-------|------|
+| 1 | code-explorer | Trova file/modifiche |
+| 2 | code-editor | Scrivi/modifica |
+| 3 | code-reviewer | Audit |
+| 4 | test-runner | Verifica |
+
+
+
+## Sequential
+Step 1 → completato → Step 2 → completato → Step 3
+
+## Parallel
+Step 1 → Step 2 → Step 3 (tutti insieme)
+Wait for all complete → Report
+
+## Wave
+Wave 1: [A, B] → wait → Wave 2: [C] → wait → Wave 3: [D]
+
+
+
+## Assign to sub-agent
+```bash
+Task(description="...", subagent_type="explorer|editor|reviewer|tester")
+```
+
+## Parallel execution
+Spawn multiple Task calls in parallel
+
+## Wait for completion
+B wait for A completion = task_id passed
+
+
+
+1. Collect output from each sub-agent
+2. Merge in unified report
+3. Identify blockers
+4. Propose next actions
+
+
+
+- Assegnare task a sub-agent
+- Coordinamento workflow
+- Aggregazione risultati
+
\ No newline at end of file
diff --git a/.opencode/skills/supabase-pinger-dev/SKILL.md b/.opencode/skills/supabase-pinger-dev/SKILL.md
new file mode 100644
index 0000000..2ff75a8
--- /dev/null
+++ b/.opencode/skills/supabase-pinger-dev/SKILL.md
@@ -0,0 +1,74 @@
+---
+name: supabase-pinger-dev
+description: "Supabase Pinger — manage Supabase keep-alive service"
+allowed-tools:
+ - Read
+ - Write
+ - Edit
+ - Bash
+ - Glob
+ - Grep
+---
+
+
+Development skill for supabase-pinger project. Provides project-specific commands and context.
+
+
+
+supabase-pinger/
+├── app.py # FastAPI app + ping logic
+├── tests/
+│ ├── conftest.py # Test config
+│ └── test_api.py # API tests
+├── AGENTS.md # Agent instructions
+├── requirements.txt # Python deps
+├── Dockerfile
+└── docker-compose.yml
+
+
+
+# Run server (requires valid .env)
+python app.py
+
+# Run tests
+pytest -q
+
+# Docker build
+docker build -t supabase-pinger .
+
+# Docker run
+docker run -d --env-file .env -p 8080:8080 --restart unless-stopped supabase-pinger
+
+
+
+- GET / # Dashboard (SmokePing-style)
+- GET /api/status # Latest sample
+- GET /api/history # History (hours param)
+- GET /docs # Swagger UI
+- GET /openapi.json # OpenAPI schema
+
+
+
+- create_app() # Main factory
+- Settings # Config dataclass
+- RRDStore # Circular buffer storage
+- run_ping() # Execute keep-alive
+- collector_loop() # Daemon thread
+
+
+
+- SUPABASE_DB_HOST
+- SUPABASE_DB_PORT
+- SUPABASE_DB_NAME
+- SUPABASE_DB_USER
+- SUPABASE_DB_PASSWORD
+- PING_INTERVAL_MINUTES
+- PING_QUERY
+- WEB_HOST
+- WEB_PORT
+
+
+
+- Any work on supabase-pinger project
+- Development, testing, or deployment
+
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..077a2d0
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,41 @@
+# AGENTS.md
+
+## Quick Commands
+```bash
+pytest -q # Run all tests
+python app.py # Start server (requires valid .env)
+```
+
+## Testing
+- Tests use `config_override` in `create_app()` to mock settings and skip the collector thread (`start_collector=False`).
+- No database connection required for tests—SQLite uses temp directories.
+- Test files: `tests/test_api.py` with 3 test functions.
+
+## Required Env Vars
+| Variable | Purpose |
+|----------|---------|
+| `SUPABASE_DB_HOST` | Connection pooler hostname |
+| `SUPABASE_DB_PORT` | Pooler port (typically 6543) |
+| `SUPABASE_DB_NAME` | Database name |
+| `SUPABASE_DB_USER` | User in format `postgres.` |
+| `SUPABASE_DB_PASSWORD` | Password |
+
+## App Architecture
+- **Entry**: `app.py` exports `create_app()` and `app` (FastAPI instance).
+- **Config**: `load_config()` validates required vars, returns `Settings` dataclass.
+- **Storage**: `RRDStore` class manages SQLite circular buffer (auto-prunes based on `max_samples`).
+- **Ping**: `run_ping()` executes keep-alive query, returns `(success, latency_ms, error_message)`.
+- **Collector**: `collector_loop()` runs in daemon thread, interval from `PING_INTERVAL_MINUTES`.
+
+## API Endpoints
+- `GET /` — Dashboard (SmokePing-style)
+- `GET /api/status` — Latest sample
+- `GET /api/history?hours=48` — Sample history (max 48h)
+- `GET /docs` — Swagger UI
+- `GET /openapi.json` — OpenAPI schema
+
+## Docker
+```bash
+docker build -t supabase-pinger .
+docker run -d --env-file .env -p 8080:8080 --restart unless-stopped supabase-pinger
+```
\ No newline at end of file
diff --git a/app.py b/app.py
index d03097b..78bca29 100644
--- a/app.py
+++ b/app.py
@@ -288,6 +288,11 @@ def _build_dashboard_html() -> str:
const badge = document.getElementById('statusBadge');
const meta = document.getElementById('meta');
const ctx = document.getElementById('latencyChart').getContext('2d');
+
+ // Buffer locale per campioni - mantiene solo i dati nel grafico
+ let samples = [];
+ const MAX_VISIBLE_SAMPLES = 100; // Limite visualizzazione per performance
+
const chart = new Chart(ctx, {
type: 'line',
data: { labels: [], datasets: [
@@ -303,37 +308,74 @@ def _build_dashboard_html() -> str:
}
});
- async function load() {
- const [statusRes, historyRes] = await Promise.all([
- fetch('/api/status'),
- fetch('/api/history?hours=48')
- ]);
- const status = await statusRes.json();
+ async function loadHistory() {
+ // Carica history iniziale una sola volta
+ const historyRes = await fetch('/api/history?hours=48');
const history = await historyRes.json();
-
- if (status.success === true) {
- badge.textContent = 'UP';
- badge.className = 'badge ok';
- } else if (status.success === false) {
- badge.textContent = 'DOWN';
- badge.className = 'badge ko';
- } else {
- badge.textContent = 'N/A';
- badge.className = 'badge';
- }
-
- meta.textContent = `Campioni 48h: ${history.count} | Ultimo campione: ${status.timestamp ? new Date(status.timestamp * 1000).toLocaleString() : 'n/a'}`;
-
- chart.data.labels = history.samples.map(s => new Date(s.timestamp * 1000).toLocaleTimeString());
- chart.data.datasets[0].data = history.samples.map(s => s.latency_ms);
- chart.data.datasets[1].data = history.samples.map(s => s.success ? 0 : 1);
- chart.update();
+ samples = history.samples || [];
+ updateChart();
}
- load().catch((err) => {
- meta.textContent = `Errore caricamento dashboard: ${err}`;
+ function updateChart() {
+ // Limita i campioni visibili per performance
+ const visibleSamples = samples.slice(-MAX_VISIBLE_SAMPLES);
+
+ chart.data.labels = visibleSamples.map(s => {
+ const d = new Date(s.timestamp * 1000);
+ return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
+ });
+ chart.data.datasets[0].data = visibleSamples.map(s => s.latency_ms);
+ chart.data.datasets[1].data = visibleSamples.map(s => s.success ? 0 : 1);
+ chart.update('none'); // update senza animazione per performance
+ }
+
+ async function pollStatus() {
+ try {
+ const statusRes = await fetch('/api/status');
+ const status = await statusRes.json();
+
+ // Aggiorna badge
+ if (status.success === true) {
+ badge.textContent = 'UP';
+ badge.className = 'badge ok';
+ } else if (status.success === false) {
+ badge.textContent = 'DOWN';
+ badge.className = 'badge ko';
+ } else {
+ badge.textContent = 'N/A';
+ badge.className = 'badge';
+ }
+
+ // Aggiorna meta con timestamp corrente
+ meta.textContent = 'Ultimo aggiornamento: ' + new Date().toLocaleTimeString() + ' | Campioni: ' + samples.length;
+
+ // Aggiunge nuovo sample se non gia presente
+ if (status.timestamp && !samples.find(s => s.timestamp === status.timestamp)) {
+ samples.push({
+ timestamp: status.timestamp,
+ success: status.success,
+ latency_ms: status.latency_ms,
+ error_message: status.error_message
+ });
+
+ // Rimuove campioni piu vecchi di 48h
+ const cutoff = Math.floor(Date.now() / 1000) - (48 * 3600);
+ samples = samples.filter(s => s.timestamp >= cutoff);
+
+ updateChart();
+ }
+ } catch (err) {
+ meta.textContent = 'Errore: ' + err.message;
+ }
+ }
+
+ // Inizializzazione
+ loadHistory().catch((err) => {
+ meta.textContent = 'Errore caricamento history: ' + err;
});
- setInterval(() => load().catch(() => {}), 30000);
+
+ // Poll ogni 10 secondi per aggiornamenti real-time
+ setInterval(pollStatus, 10000);