Skip to content

Commit 833c167

Browse files
committed
docs: add AGENTS.md and AI contribution guidance
Introduce lean agent guidance and document AI-assisted contributions (human remains responsible, exact model disclosure). Expand Grafana dashboard contributing notes (edge image, Classic export, units, variables, positions sampling).
1 parent 1dc5dce commit 833c167

3 files changed

Lines changed: 170 additions & 8 deletions

File tree

AGENTS.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# AGENTS.md
2+
3+
Guidance for AI coding agents working on TeslaMate.
4+
5+
Human contributors: see [Development and Contributing](https://docs.teslamate.org/docs/development/) and `CONTRIBUTING`.
6+
7+
## Project map
8+
9+
| Path | Role |
10+
|------|------|
11+
| `lib/`, `test/` | Elixir / Phoenix app |
12+
| `priv/repo/` | Migrations and SQL helpers (`convert_celsius`, `convert_km`, …) |
13+
| `grafana/dashboards/` | Provisioned Grafana dashboards |
14+
| `website/` | Documentation (Docusaurus) |
15+
| `nix/`, `flake.nix` | Dev environment / packaging |
16+
| `.github/workflows/` | CI |
17+
18+
Prefer small, reviewable changes. Do not expand scope unprompted.
19+
20+
## Setup and checks
21+
22+
Use versions from the development docs when you have a local environment:
23+
24+
```bash
25+
mix setup
26+
MIX_ENV=test mix ecto.setup
27+
mix ci
28+
treefmt # or: nix run .#lint
29+
```
30+
31+
Not every contributor has a full local Elixir/Postgres/Grafana stack. **It is fine to rely on GitHub Actions CI** on the PR for format checks, tests, and related workflows. Run what you can locally; fix CI failures the PR introduces before asking for merge.
32+
33+
Run `mix gettext.extract --merge` only if user-facing strings changed and you can run Mix.
34+
35+
## Change rules
36+
37+
- Match neighboring style; no drive-by refactors.
38+
- Smallest diff that solves the stated problem.
39+
- Add or update tests for behavior changes.
40+
- Do not commit secrets, tokens, cookies, or vehicle credentials.
41+
- Do not change dashboard **UIDs** unless explicitly requested.
42+
43+
## Grafana dashboards
44+
45+
Canonical query and dashboard craft (timestamps, `positions`/streaming, `EXPLAIN ANALYZE`, `pg_stat_statements`) lives in the [Development and Contributing](https://docs.teslamate.org/docs/development/) docs under **Making Changes to Grafana Dashboards** and **Best Practices**. Follow that. Short rules for agents:
46+
47+
- Use `teslamate/grafana:edge` for local edits. Export as code with **Model: Classic** (not **V2 Resource**); keep the JSON as exported.
48+
- Copy variable/link patterns from a similar existing dashboard (e.g. Overview, Efficiency).
49+
- Common variables: `car_id`, `base_url`, and when relevant `length_unit`, `temp_unit`, `preferred_range`.
50+
- Header links: TeslaMate → `${base_url:raw}` + Dashboards dropdown (tag `tesla`).
51+
- Temperature: `convert_celsius(col, '$temp_unit')` — never hardcode °C-only when settings exist.
52+
- Distance: `convert_km(..., '$length_unit')`.
53+
- Prefer `$__timeFilter` / `$__timeGroup`. If using `DATE_TRUNC`, follow the docs pattern with `TIMEZONE('UTC', …)` and `'$__timezone'`.
54+
- Query `positions` only when needed. If ~15s resolution is enough, prefer `ideal_battery_range_km IS NOT NULL` (and `car_id = $car_id`) to skip dense streaming rows — see docs.
55+
- `positions` is denser while driving than when parked; sample counts are not “time spent.” Prefer time-bucketing for distributions.
56+
- History charts: aggregate where samples exist; use Connect null values **Threshold** (not Always) for long offline gaps.
57+
- Larger UX changes: update screenshots under `website/static/screenshots/` (see docs).
58+
- Keep dashboard domain focus; do not merge unrelated concerns unprompted.
59+
60+
## GitHub
61+
62+
- Do not push, open PRs, merge, or post reviews/comments unless the user explicitly asks.
63+
- PR descriptions: what/why, tradeoffs, how tested; `Closes #…` when applicable.
64+
65+
## AI assistance disclosure
66+
67+
Disclose material AI help on **PR descriptions** and **substantive review comments**.
68+
69+
Use this footer (include the robot icon and the **exact model name**):
70+
71+
```markdown
72+
---
73+
74+
🤖 Assisted by <Exact model name> (<Vendor>) via <Tool> (<what it helped with>).
75+
```
76+
77+
Examples:
78+
79+
```markdown
80+
---
81+
82+
🤖 Assisted by Claude Opus 5 (Anthropic) via Claude Code (implementation, tests).
83+
```
84+
85+
```markdown
86+
---
87+
88+
🤖 Assisted by Grok 4.5 (xAI) via Grok Build (planning, code edits, PR description).
89+
```
90+
91+
Rules:
92+
93+
- Always state the **exact model name** (e.g. `Grok 4.5`, not only “Grok” or “AI”).
94+
- Name vendor, tool, and a short role list.
95+
- Do not paste chain-of-thought or tool logs into the PR.
96+
- The **human** opening the PR or posting the review remains fully responsible for correctness, security, and licensing (AGPL-3.0).
97+
98+
## Security
99+
100+
- Never exfiltrate `.env`, tokens, or database dumps.
101+
- Do not add telemetry or phone-home behavior.
102+
- Treat vehicle location and identity as sensitive.

CONTRIBUTING

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Contributing Guidelines
22

3-
see [Development and Contributing](https://docs.teslamate.org/docs/development/)
3+
See [Development and Contributing](https://docs.teslamate.org/docs/development/).
4+
5+
AI coding agents: see [`AGENTS.md`](./AGENTS.md).

website/docs/development.mdx

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ grafana:
112112
113113
## Making Changes to Grafana Dashboards
114114
115-
To update dashboards you need Grafana running locally. The following _docker-compose.yml_ can be used for this purpose:
115+
Use **`teslamate/grafana:edge`** for local dashboard work. Export JSON as Grafana saves it into `./grafana/dashboards/`.
116116

117117
```yml
118118
services:
119119
grafana:
120-
image: teslamate/grafana:latest
120+
image: teslamate/grafana:edge
121121
environment:
122122
- DATABASE_USER=postgres
123123
- DATABASE_PASS=postgres
@@ -132,18 +132,39 @@ volumes:
132132
grafana-data:
133133
```
134134

135-
_(on Linux use the actual IP address of the host as `DATABASE_HOST`instead of `host.docker.internal`)_
135+
_(on Linux use the actual IP address of the host as `DATABASE_HOST` instead of `host.docker.internal`)_
136136

137-
Then build the image with `make grafana` and run the container via `docker compose up grafana`.
138-
139-
Access the Grafana at [http://localhost:3000](http://localhost:3000) and sign in with the default user `admin` and password `admin`.
137+
```bash
138+
docker compose up grafana
139+
```
140140

141-
Then edit the respective dashboard(s) locally. To export a dashboard hit the 'Save' button and select `Save JSON to file`. The final JSON file belongs in the directory `./grafana/dashboards/`. To apply the changes rebuild the image and start the container.
141+
Open [http://localhost:3000](http://localhost:3000) (`admin` / `admin`), edit the dashboard, then **Export** → **Export as code**. Under **Advanced options**, set **Model** to **Classic** (not **V2 Resource**), then **Download file** into `./grafana/dashboards/`.
142142

143143
When making larger changes to Grafana Dashboards please include updated screenshots (1920x1080 @ x2, Grafana running in Kiosk mode) in `./website/static/screenshots`. Ensure to blur sensitive information.
144144

145145
## Best Practices
146146

147+
### Dashboard variables and units
148+
149+
Most dashboards follow a shared shell. Prefer copying variable and link blocks from a similar existing dashboard (e.g. Overview or Efficiency) rather than inventing new shapes.
150+
151+
Common template variables:
152+
153+
| Variable | Typical source | When |
154+
|----------|----------------|------|
155+
| `car_id` | `cars` | Almost always |
156+
| `base_url` | `settings.base_url` | Header link to TeslaMate |
157+
| `length_unit` | `settings.unit_of_length` | Distance / speed |
158+
| `temp_unit` | `settings.unit_of_temperature` | Temperature |
159+
| `preferred_range` | `settings.preferred_range` | Ideal vs rated range |
160+
161+
Typical header links: **TeslaMate** → `${base_url:raw}`, plus a **Dashboards** dropdown on tag `tesla`.
162+
163+
Use the database helpers so user settings apply:
164+
165+
- Temperature: `convert_celsius(column, '$temp_unit')` — do not hardcode Celsius-only units, axis labels, or thresholds when `temp_unit` exists
166+
- Distance / speed: `convert_km(column, '$length_unit')`
167+
147168
### Queries involving timestamp columns
148169

149170
Datetime values are currently stored in columns of type `timestamp`. [This is NOT recommended](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_timestamp_.28without_time_zone.29_to_store_UTC_times).
@@ -165,6 +186,8 @@ When Streaming API is enabled roughly 1 GB of data is gathered per car and 30 00
165186
- only query positions table when really needed
166187
- if data in 15 second intervals is sufficient consider excluding streaming data by adding `ideal_battery_range_km IS NOT NULL and car_id = $car_id` as WHERE conditions
167188

189+
Logging is much denser while driving than when parked or asleep. **Sample counts are not “time spent.”** For frequency distributions, heatmaps, or percentiles over ambient conditions, time-bucket or otherwise debiased aggregates first; do not treat raw row counts as a fair distribution.
190+
168191
Before opening pull requests please diagnose index usage & query performance by making use of `EXPLAIN ANALYZE`.
169192

170193
### Enable _pg_stat_statements_ to collect query statistics
@@ -227,6 +250,41 @@ Before we can merge your first Pull Request, you must sign our **Fiduciary Licen
227250
- **How?** When you open a PR, our `@cla-assistant` bot will post a comment with a link to sign the agreement using your GitHub account. It only takes a few seconds.
228251
- **More Info:** You can find the full text and further details in our [Legal Repository](https://github.com/teslamate-org/legal).
229252

253+
### 3. AI-assisted contributions
254+
255+
**Use of AI tools is welcome** for planning, implementation, tests, docs, and review drafting.
256+
257+
You remain fully in charge of what you submit or post:
258+
259+
- You must understand the change and be able to explain it.
260+
- You are responsible for correctness, security, performance, and license compliance (AGPL-3.0 / CLA).
261+
- Review comments or replies drafted with AI are still **your** review: read and agree with every request before posting.
262+
- Do not let an agent push, merge, or speak on GitHub on your behalf without your explicit direction and review.
263+
264+
For **material** AI assistance, disclose it at the end of the PR description and of substantive review comments. Include the robot icon and the **exact model name** (not only a product family):
265+
266+
```markdown
267+
---
268+
269+
🤖 Assisted by <Exact model name> (<Vendor>) via <Tool> (<what it helped with>).
270+
```
271+
272+
Examples:
273+
274+
```markdown
275+
---
276+
277+
🤖 Assisted by Claude Opus 5 (Anthropic) via Claude Code (implementation, tests).
278+
```
279+
280+
```markdown
281+
---
282+
283+
🤖 Assisted by Grok 4.5 (xAI) via Grok Build (planning, code edits, PR description).
284+
```
285+
286+
Trivial edits (typos, rebases) need no footer. Agent-oriented project rules (commands, Grafana conventions, scope) live in [`AGENTS.md`](https://github.com/teslamate-org/teslamate/blob/main/AGENTS.md) at the repository root.
287+
230288
## Pre-Merge Checks for Dependency Updates
231289

232290
When reviewing a pull request that updates dependencies, it's crucial to verify that the changes are correct and don't break the Nix-based development environment. After checking out the branch of the PR, run the following commands:

0 commit comments

Comments
 (0)