coding guidelines, agents and gemini.md
This commit is contained in:
124
Provider/.agents/rules/coding-guidelines.md
Normal file
124
Provider/.agents/rules/coding-guidelines.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# Calendink Coding Guidelines
|
||||||
|
|
||||||
|
These rules apply to all code in this workspace.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backend — C++ / ESP-IDF
|
||||||
|
|
||||||
|
### Philosophy: C-with-Utilities
|
||||||
|
Write **C-style code** using C++ convenience features. No classes, no methods, no RAII, no exceptions.
|
||||||
|
|
||||||
|
**Use freely:** `template`, `auto`, `constexpr`, `enum class`, type aliases from `types.hpp`
|
||||||
|
**Avoid:** classes, constructors/destructors, `std::` containers, inheritance, virtual functions, RAII wrappers
|
||||||
|
|
||||||
|
`goto` for cleanup/shutdown paths in `app_main` is acceptable.
|
||||||
|
|
||||||
|
### Unity Build
|
||||||
|
All `.cpp` files are `#include`-ed into `main.cpp` as a single translation unit. **Do not register new source files in CMakeLists.txt.**
|
||||||
|
|
||||||
|
- Use `unity.cpp` aggregators per API group (e.g., `api/tasks/unity.cpp`)
|
||||||
|
- Mark all file-scoped symbols with `internal` (defined as `static` in `types.hpp`)
|
||||||
|
- Use `.hpp` for declarations shared across included files only
|
||||||
|
|
||||||
|
### API Handler Pattern
|
||||||
|
```cpp
|
||||||
|
// METHOD /api/path — What it does
|
||||||
|
// Body: { "field": value } (if applicable)
|
||||||
|
|
||||||
|
internal esp_err_t api_foo_post_handler(httpd_req_t *req) {
|
||||||
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||||
|
// 1. Parse request
|
||||||
|
// 2. Call store function
|
||||||
|
// 3. Build cJSON response
|
||||||
|
// Always cJSON_Delete() objects and free() printed strings — no leaks
|
||||||
|
}
|
||||||
|
|
||||||
|
internal const httpd_uri_t api_foo_post_uri = { .uri = "/api/foo", .method = HTTP_POST, .handler = api_foo_post_handler, .user_ctx = NULL };
|
||||||
|
```
|
||||||
|
|
||||||
|
### Store / Handler Separation
|
||||||
|
Data operations in `store.cpp` / `store.hpp`. HTTP parsing in endpoint files. Never mix them.
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
**Always use `ESP_LOGI` / `ESP_LOGW` / `ESP_LOGE`** — never `printf()`.
|
||||||
|
|
||||||
|
Since this is a Unity Build (single translation unit), the log tag must be unique per file to avoid redefinition. Name it after the module, not a generic `TAG`:
|
||||||
|
```cpp
|
||||||
|
// In each file, use a unique local name:
|
||||||
|
internal const char *kTagHttpServer = "HTTP_SERVER";
|
||||||
|
internal const char *kTagMain = "MAIN";
|
||||||
|
internal const char *kTagMDNS = "MDNS";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Type Aliases
|
||||||
|
Use `types.hpp` aliases: `uint8`, `uint16`, `uint32`, `uint64`, `int8`–`int64`, `internal`
|
||||||
|
|
||||||
|
### Seed Data
|
||||||
|
`seed_users()` and `seed_tasks()` must be guarded:
|
||||||
|
```cpp
|
||||||
|
#ifndef NDEBUG
|
||||||
|
seed_users();
|
||||||
|
seed_tasks();
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data Persistence
|
||||||
|
All task/user data is currently **in-RAM only** (intentional — NVS/LittleFS persistence is a future milestone). Do not add persistence without a TDD.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Frontend — Svelte 5 + TailwindCSS v4
|
||||||
|
|
||||||
|
### Styling: Tailwind Only
|
||||||
|
Use TailwindCSS exclusively. **No `<style>` blocks in components.**
|
||||||
|
|
||||||
|
- All design tokens are in `app.css` via `@theme`: `bg-bg-card`, `text-text-primary`, `border-border`, `text-accent`, `text-success`, `text-danger`, etc.
|
||||||
|
- If a utility is missing, add a token to `@theme` — don't add inline CSS
|
||||||
|
|
||||||
|
### Reactivity: Svelte 5 Runes Only
|
||||||
|
| Do ✅ | Don't ❌ |
|
||||||
|
|---|---|
|
||||||
|
| `$state()` | `writable()`, `readable()` |
|
||||||
|
| `$derived()` / `$derived.by()` | `$:` reactive statements |
|
||||||
|
| `$effect()` | `onMount()`, `onDestroy()`, `.subscribe()` |
|
||||||
|
| `$props()` / `$bindable()` | `export let` |
|
||||||
|
|
||||||
|
### `$state()` vs Plain `let`
|
||||||
|
- **`$state()`** — values the template reads, or that changes should cause a re-render
|
||||||
|
- **Plain `let`** — script-only internals (mutex flags, interval handles, etc.) the template never reads
|
||||||
|
|
||||||
|
### `$effect()` for Initialization
|
||||||
|
When an effect has no reactive dependencies and runs once on mount, add a comment:
|
||||||
|
```js
|
||||||
|
// Load initial data on mount
|
||||||
|
$effect(() => { fetchData(); });
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shared Utilities
|
||||||
|
- Date/time helpers, formatters → `lib/utils.js`
|
||||||
|
- Cross-component reactive state → `lib/stores.js`
|
||||||
|
- API calls → `lib/api.js` (always via `trackedFetch()`)
|
||||||
|
|
||||||
|
**Never duplicate functions across components.**
|
||||||
|
|
||||||
|
### Component Structure
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
// 1. Imports
|
||||||
|
// 2. $props()
|
||||||
|
// 3. $state()
|
||||||
|
// 4. $derived()
|
||||||
|
// 5. Functions
|
||||||
|
// 6. $effect()
|
||||||
|
</script>
|
||||||
|
<!-- Template — Tailwind classes only -->
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
- **Don't commit build artifacts**: `dist/`, `bundles/`, `temp_*`, `*.gz` — update `.gitignore` accordingly
|
||||||
|
- **Version** is managed through `version.json`, injected as `__APP_VERSION__` at build time
|
||||||
@@ -10,3 +10,4 @@ Pleaes add the date.
|
|||||||
The TDD should starts with the What, then the Why and finally the how.
|
The TDD should starts with the What, then the Why and finally the how.
|
||||||
Everytime you write a document you can read other tdd in the folder for inspiration.
|
Everytime you write a document you can read other tdd in the folder for inspiration.
|
||||||
When implementation is finished, the user can add to edit the TDD to add more informations (implementation details that are important, benchmarks, any change of plan during development)
|
When implementation is finished, the user can add to edit the TDD to add more informations (implementation details that are important, benchmarks, any change of plan during development)
|
||||||
|
When you add a tdd, please update Gemini.md to add the tdd.
|
||||||
85
Provider/AGENTS.md
Normal file
85
Provider/AGENTS.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
Calendink Provider — ESP32-S3 firmware + Svelte 5 web dashboard.
|
||||||
|
Uses **ESP-IDF** (not Arduino). Serves UI from LittleFS flash partitions over Ethernet/WiFi.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Backend (from project root)
|
||||||
|
idf.py build
|
||||||
|
idf.py flash monitor
|
||||||
|
|
||||||
|
# Frontend (from frontend/)
|
||||||
|
npm run dev # Dev server — calls real ESP32 API (set VITE_API_BASE in .env.development)
|
||||||
|
npm run build # Production build → dist/index.html
|
||||||
|
npm run build:esp32 # Build + gzip → dist/index.html.gz
|
||||||
|
npm run ota:deploy # OTA deploy frontend to device
|
||||||
|
```
|
||||||
|
|
||||||
|
There are no automated tests. Verify by building and inspecting on-device.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
main/ C++ firmware (Unity Build — one translation unit)
|
||||||
|
main/api/<domain>/ HTTP endpoint files, one per verb
|
||||||
|
main/http_server.cpp Server setup, static file serving, scratch buffer pool
|
||||||
|
main/connect.cpp Ethernet + WiFi management
|
||||||
|
frontend/src/ Svelte 5 components + api.js
|
||||||
|
frontend/src/app.css TailwindCSS v4 @theme design tokens
|
||||||
|
tdd/ Technical Design Documents — read before major changes
|
||||||
|
.agents/rules/ Coding guidelines
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backend Rules (C++ / ESP-IDF)
|
||||||
|
|
||||||
|
- **Unity Build**: `main.cpp` `#include`s all `.cpp` files. Do NOT add files to `CMakeLists.txt`.
|
||||||
|
- **C-style only**: no classes, no `std::`, no RAII, no exceptions. `template`, `auto`, `constexpr` are fine.
|
||||||
|
- **`internal`** (= `static`) on all file-scoped symbols — defined in `main/types.hpp`.
|
||||||
|
- **Logging**: use `ESP_LOGI` / `ESP_LOGW` / `ESP_LOGE` only — never `printf()`.
|
||||||
|
- Because of Unity Build, tag variables must have unique names per file: `kTagHttpServer`, `kTagMain`, etc. — never use a shared `TAG`.
|
||||||
|
- **Seed data**: `seed_users()` / `seed_tasks()` must be inside `#ifndef NDEBUG` guards.
|
||||||
|
- **API handler pattern**: set CORS header + response type → parse request → call store function → build cJSON response → `free()` strings, `cJSON_Delete()` objects.
|
||||||
|
- **Data is in-RAM only** (`g_Users[8]`, `g_Tasks[32]`). This is intentional — persistence is a future milestone. Don't add it without a TDD.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Frontend Rules (Svelte 5 + TailwindCSS v4)
|
||||||
|
|
||||||
|
- **Tailwind only** — no `<style>` blocks in components. Design tokens are in `frontend/src/app.css` (`@theme`).
|
||||||
|
- **Svelte 5 runes only** — `$state`, `$derived`, `$effect`, `$props`, `$bindable`. No `export let`, `onMount`, `onDestroy`, `writable`, or `.subscribe()`.
|
||||||
|
- **`$state()`** for values the template reads. **Plain `let`** for script-only handles/flags the template never reads.
|
||||||
|
- **`$effect()` with no reactive deps** runs once on mount — add a comment saying so.
|
||||||
|
- All API calls through `lib/api.js` via `trackedFetch()` — never raw `fetch()`.
|
||||||
|
- Shared utilities (formatters, helpers) in `lib/utils.js`. Never duplicate functions across components.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Design Documents
|
||||||
|
|
||||||
|
Read the relevant TDD before any major architectural change:
|
||||||
|
|
||||||
|
| TDD | Read when |
|
||||||
|
|---|---|
|
||||||
|
| `tdd/backend_architecture.md` | Changing server setup, adding API groups |
|
||||||
|
| `tdd/frontend_technology_choices.md` | Changing build tools or dependencies |
|
||||||
|
| `tdd/todo_list.md` | Changing task/user data model or API contracts |
|
||||||
|
| `tdd/firmware_ota.md` | Touching OTA partition logic |
|
||||||
|
| `tdd/frontend_ota.md` | Touching frontend OTA upload or versioning |
|
||||||
|
| `tdd/concurrent_requests.md` | Changing HTTP server socket/connection config |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Working with the User
|
||||||
|
|
||||||
|
- After finishing a task: explain what changed, what you recommend next, and wait for approval.
|
||||||
|
- Never make changes beyond the agreed scope without asking first.
|
||||||
|
- Write a TDD (see `.agents/rules/how-to-write-tdd.md`) before major architectural changes.
|
||||||
|
- **Keep `AGENTS.md` and `GEMINI.md` up to date.** If a task changes the architecture, adds new rules, introduces new build commands, or modifies the project layout — update both files before closing the task.
|
||||||
105
Provider/GEMINI.md
Normal file
105
Provider/GEMINI.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# Calendink Provider — Agent Context
|
||||||
|
|
||||||
|
This is an **ESP32-S3 IoT device** firmware + web dashboard project.
|
||||||
|
It uses **ESP-IDF** (native, not Arduino) and serves a **Svelte 5 web UI** from flash.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Summary
|
||||||
|
|
||||||
|
Calendink Provider is a connected desk device that serves a local web dashboard over Ethernet/WiFi.
|
||||||
|
The firmware manages network connections, serves a Svelte SPA from LittleFS flash partitions, and exposes a REST API for system control (reboot, OTA, tasks, users).
|
||||||
|
|
||||||
|
### Key Paths
|
||||||
|
|
||||||
|
| Path | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `main/` | C++ firmware (Unity Build) |
|
||||||
|
| `main/api/` | REST API handlers, one file per endpoint |
|
||||||
|
| `main/http_server.cpp` | HTTP server setup, static file serving |
|
||||||
|
| `main/connect.cpp` | Ethernet + WiFi connection management |
|
||||||
|
| `frontend/src/` | Svelte 5 frontend source |
|
||||||
|
| `frontend/src/lib/api.js` | All API calls (always use `trackedFetch`) |
|
||||||
|
| `frontend/src/app.css` | TailwindCSS v4 design tokens (`@theme`) |
|
||||||
|
| `tdd/` | Technical Design Documents (read before major changes) |
|
||||||
|
| `.agents/rules/` | Coding guidelines (always follow) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
- **Unity Build**: `main.cpp` `#include`s all `.cpp` files. Do NOT add files to CMakeLists.txt. Everything is one translation unit.
|
||||||
|
- **API handlers**: Each endpoint is its own `.cpp` file in `main/api/<domain>/`. A `unity.cpp` aggregates them.
|
||||||
|
- **HTTP server**: `esp_http_server` + `cJSON`. CORS is always on (`*`).
|
||||||
|
- **Data storage**: Users and tasks are in static BSS arrays (`g_Users[8]`, `g_Tasks[32]`). In-RAM only, intentionally — persistence is a future feature.
|
||||||
|
- **OTA**: A/B partition scheme — `www_0` / `www_1` for frontend, `ota_0` / `ota_1` for firmware. NVS tracks which slot is active.
|
||||||
|
- **Connections**: Ethernet first, WiFi fallback. Connection state managed with FreeRTOS semaphores.
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
- **Svelte 5** with runes (`$state`, `$derived`, `$effect`, `$props`). No legacy Svelte 4 APIs.
|
||||||
|
- **TailwindCSS v4** (utility classes only — no `<style>` blocks in components).
|
||||||
|
- **Single-file build**: `vite-plugin-singlefile` inlines all JS+CSS into one `index.html`.
|
||||||
|
- **Version**: Tracked in `version.json`, injected as `__APP_VERSION__` at build time.
|
||||||
|
- **Dev mode**: Set `VITE_API_BASE=http://<ESP32_IP>` in `.env.development` — the frontend runs on PC and calls the real ESP32 API.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coding Rules (summary — full rules in `.agents/rules/coding-guidelines.md`)
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- C-style code: no classes, no `std::`, no RAII, no exceptions. Use `template`, `auto`, `constexpr` freely.
|
||||||
|
- Use `internal` (= `static`) for all file-scoped symbols.
|
||||||
|
- Log with `ESP_LOGI/W/E` only — never `printf()`. Name log tags per-module with unique variable names (e.g., `kTagHttpServer`), not a shared `TAG`, to avoid Unity Build redefinition.
|
||||||
|
- Seed data (`seed_users`, `seed_tasks`) must be `#ifndef NDEBUG` guarded.
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- Svelte 5 runes only. No `onMount`, `onDestroy`, `writable`, `.subscribe`.
|
||||||
|
- Tailwind only. No `<style>` blocks.
|
||||||
|
- Shared logic goes in `lib/utils.js`. Never duplicate functions across components.
|
||||||
|
- API calls go through `lib/api.js` via `trackedFetch()` — never raw `fetch()`.
|
||||||
|
- `$state()` for values the template reads. Plain `let` for script-only flags/handles.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Design Documents
|
||||||
|
|
||||||
|
Always read the relevant TDD before making major architectural changes:
|
||||||
|
|
||||||
|
| TDD | When to read |
|
||||||
|
|---|---|
|
||||||
|
| [backend_architecture.md](tdd/backend_architecture.md) | Changing server setup, adding new API groups |
|
||||||
|
| [frontend_technology_choices.md](tdd/frontend_technology_choices.md) | Changing build tools, adding dependencies |
|
||||||
|
| [todo_list.md](tdd/todo_list.md) | Changing task/user data models or API contracts |
|
||||||
|
| [firmware_ota.md](tdd/firmware_ota.md) | Touching OTA partition logic |
|
||||||
|
| [frontend_ota.md](tdd/frontend_ota.md) | Touching frontend OTA upload or versioning |
|
||||||
|
| [concurrent_requests.md](tdd/concurrent_requests.md) | Changing HTTP server socket/connection config |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Work With the User
|
||||||
|
|
||||||
|
- After finishing any task: tell the user what you did, what you think the next step should be, and ask for approval before proceeding.
|
||||||
|
- Never go rogue — propose changes, wait for confirmation.
|
||||||
|
- Write a TDD before major architectural changes. See `.agents/rules/how-to-write-tdd.md`.
|
||||||
|
- **Keep `AGENTS.md` and `GEMINI.md` up to date.** If a task changes the architecture, adds new rules, introduces new build commands, or modifies the project layout — update both files before closing the task.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Backend — from project root
|
||||||
|
idf.py build
|
||||||
|
idf.py flash monitor
|
||||||
|
|
||||||
|
# Frontend — from frontend/
|
||||||
|
npm run dev # Dev server (PC, calls real ESP32 API)
|
||||||
|
npm run build # Production build → dist/index.html
|
||||||
|
npm run build:esp32 # Build + gzip → dist/index.html.gz
|
||||||
|
npm run ota:package # Package as versioned .bin
|
||||||
|
npm run ota:bundle # Package FW + frontend as .bundle
|
||||||
|
npm run ota:deploy # Deploy frontend OTA to device
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user