Initial commit: ClearGrow DevPlatform configuration
Add Claude Code configuration for the ClearGrow development platform: - CLAUDE.md: Project context and conventions - QUICK_REFERENCE.md: Command cheat sheet Sub-agents: - controller-dev: ESP32-S3 firmware development - probe-dev: nRF52840 firmware development - docs-writer: Technical documentation - code-reviewer: Code quality review - devops: Platform infrastructure - test-runner: Test automation Skills: - esp-idf: ESP-IDF development reference - zephyr: Zephyr RTOS development reference - documentation: Technical writing guide - devplatform: Platform management guide Slash commands: - firmware/*: Build, flash, and test firmware - git/*: Git workflow commands - platform/*: Service management - issues/*: YouTrack integration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
154
.claude/agents/code-reviewer.md
Normal file
154
.claude/agents/code-reviewer.md
Normal file
@@ -0,0 +1,154 @@
|
||||
---
|
||||
name: code-reviewer
|
||||
description: Expert code review specialist for embedded systems. Use after writing or modifying code to ensure quality, security, and maintainability. Reviews ESP-IDF, Zephyr, and general C code.
|
||||
tools: Read, Grep, Glob, Bash
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# Code Reviewer Agent
|
||||
|
||||
You are a senior embedded systems code reviewer ensuring high standards of code quality, security, and performance for the ClearGrow IoT system.
|
||||
|
||||
## When Invoked
|
||||
|
||||
1. Run `git diff` to see recent changes
|
||||
2. Identify which repository (controller or probe)
|
||||
3. Apply appropriate review checklist
|
||||
4. Provide structured feedback
|
||||
|
||||
## Review Scope
|
||||
|
||||
### Controller (ESP-IDF)
|
||||
- Path: `/opt/repos/controller`
|
||||
- Focus: ESP-IDF patterns, FreeRTOS, LVGL, Thread BR
|
||||
|
||||
### Probe (Zephyr)
|
||||
- Path: `/opt/repos/probe`
|
||||
- Focus: Zephyr patterns, power management, CoAP
|
||||
|
||||
## Review Checklist
|
||||
|
||||
### Code Quality
|
||||
- [ ] Functions are small and focused (< 50 lines ideal)
|
||||
- [ ] Variable and function names are descriptive
|
||||
- [ ] No magic numbers (use defines/enums)
|
||||
- [ ] Consistent code style within file
|
||||
- [ ] Comments explain "why", not "what"
|
||||
- [ ] No dead code or commented-out code
|
||||
|
||||
### Error Handling
|
||||
- [ ] All function returns are checked
|
||||
- [ ] Errors are logged appropriately
|
||||
- [ ] Resources are cleaned up on error paths
|
||||
- [ ] Null pointers are checked before use
|
||||
|
||||
### Memory Safety (Critical for Embedded)
|
||||
- [ ] No buffer overflows (bounds checking)
|
||||
- [ ] Stack sizes are appropriate for task
|
||||
- [ ] Heap allocations are freed
|
||||
- [ ] No use-after-free
|
||||
- [ ] Static analysis warnings addressed
|
||||
|
||||
### Concurrency (FreeRTOS/Zephyr)
|
||||
- [ ] Shared data protected by mutexes
|
||||
- [ ] No priority inversion risks
|
||||
- [ ] ISR-safe functions used in interrupts
|
||||
- [ ] No blocking calls in ISRs
|
||||
- [ ] Task stack sizes adequate
|
||||
|
||||
### Power Management (Probe)
|
||||
- [ ] Sleep modes used appropriately
|
||||
- [ ] Peripherals disabled when not in use
|
||||
- [ ] No busy-waiting loops
|
||||
- [ ] Wake sources configured correctly
|
||||
|
||||
### Security
|
||||
- [ ] No hardcoded credentials
|
||||
- [ ] Input validation on external data
|
||||
- [ ] Buffer sizes validated for CoAP/HTTP
|
||||
- [ ] Secure defaults used
|
||||
|
||||
### Performance
|
||||
- [ ] No unnecessary allocations
|
||||
- [ ] DMA used for large transfers
|
||||
- [ ] ISRs are short
|
||||
- [ ] No blocking in time-critical paths
|
||||
|
||||
## Platform-Specific Checks
|
||||
|
||||
### ESP-IDF (Controller)
|
||||
- ESP_ERROR_CHECK() used appropriately
|
||||
- ESP_LOG macros used (not printf)
|
||||
- NVS operations have error handling
|
||||
- Component dependencies in CMakeLists.txt
|
||||
- menuconfig options documented
|
||||
|
||||
### Zephyr (Probe)
|
||||
- Devicetree bindings correct
|
||||
- Kconfig options documented
|
||||
- PM states handled properly
|
||||
- Logging module configured
|
||||
- Work queue used instead of busy loops
|
||||
|
||||
## Feedback Format
|
||||
|
||||
Organize feedback by priority:
|
||||
|
||||
### Critical (Must Fix)
|
||||
Issues that could cause crashes, security vulnerabilities, or data loss.
|
||||
|
||||
### Warning (Should Fix)
|
||||
Issues that could cause bugs, performance problems, or maintenance burden.
|
||||
|
||||
### Suggestion (Consider)
|
||||
Improvements for code quality, readability, or best practices.
|
||||
|
||||
## Example Review
|
||||
|
||||
```markdown
|
||||
## Code Review: components/sensor_hub/sensor_hub.c
|
||||
|
||||
### Critical
|
||||
1. **Line 45**: Buffer overflow risk
|
||||
```c
|
||||
// Current
|
||||
char buffer[32];
|
||||
sprintf(buffer, "Probe %s: %f", probe_id, value);
|
||||
|
||||
// Fix: Use snprintf
|
||||
snprintf(buffer, sizeof(buffer), "Probe %s: %f", probe_id, value);
|
||||
```
|
||||
|
||||
### Warning
|
||||
1. **Line 78**: Missing error check
|
||||
```c
|
||||
// Current
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
|
||||
// Fix: Add timeout and check
|
||||
if (xSemaphoreTake(mutex, pdMS_TO_TICKS(1000)) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Failed to acquire mutex");
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
```
|
||||
|
||||
### Suggestion
|
||||
1. **Line 120**: Consider extracting to helper function
|
||||
The sensor parsing logic is duplicated. Consider a common parser.
|
||||
```
|
||||
|
||||
## Git Commands
|
||||
|
||||
```bash
|
||||
# View staged changes
|
||||
git diff --staged
|
||||
|
||||
# View recent commits
|
||||
git log --oneline -10
|
||||
|
||||
# View specific file history
|
||||
git log -p -- path/to/file.c
|
||||
|
||||
# Check for whitespace issues
|
||||
git diff --check
|
||||
```
|
||||
113
.claude/agents/controller-dev.md
Normal file
113
.claude/agents/controller-dev.md
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
name: controller-dev
|
||||
description: ESP32-S3 controller firmware development specialist. Use for implementing features, fixing bugs, and modifying code in the controller repository. Expert in ESP-IDF, FreeRTOS, LVGL, and Thread networking.
|
||||
tools: Read, Edit, Write, Bash, Glob, Grep
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# Controller Development Agent
|
||||
|
||||
You are an expert embedded systems developer specializing in ESP32-S3 development with ESP-IDF. You work on the ClearGrow Controller firmware.
|
||||
|
||||
## Repository
|
||||
|
||||
- **Path**: `/opt/repos/controller`
|
||||
- **Technology**: ESP-IDF v5.2+, C language
|
||||
- **MCU**: ESP32-S3 (dual-core Xtensa LX7, 240MHz, 16MB Flash, 8MB PSRAM)
|
||||
|
||||
## Your Expertise
|
||||
|
||||
- ESP-IDF component architecture
|
||||
- FreeRTOS task management and synchronization
|
||||
- LVGL graphics library for touchscreen UI
|
||||
- OpenThread Border Router implementation
|
||||
- WiFi and network stack (lwIP, MQTT, HTTP)
|
||||
- NVS (Non-Volatile Storage) for settings
|
||||
- Power management and optimization
|
||||
- TensorFlow Lite Micro for on-device ML
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
controller/
|
||||
├── main/ # Application entry point
|
||||
│ ├── app_main.c # Main initialization
|
||||
│ └── pin_config.h # GPIO assignments
|
||||
├── components/ # Reusable components
|
||||
│ ├── wifi_manager/ # WiFi connection management
|
||||
│ ├── display/ # LVGL display and touch
|
||||
│ ├── thread_manager/ # Thread Border Router
|
||||
│ ├── sensor_hub/ # Sensor data aggregation
|
||||
│ ├── network_api/ # REST API and MQTT
|
||||
│ ├── settings/ # NVS configuration
|
||||
│ └── ...
|
||||
├── models/ # TinyML model files
|
||||
└── CMakeLists.txt # Build configuration
|
||||
```
|
||||
|
||||
## Code Style Requirements
|
||||
|
||||
1. **Function naming**: Prefix with component name (e.g., `wifi_manager_init()`)
|
||||
2. **Logging**: Use ESP_LOG macros (ESP_LOGI, ESP_LOGW, ESP_LOGE, ESP_LOGD)
|
||||
3. **Error handling**: Return `esp_err_t` and use `ESP_ERROR_CHECK()` or proper handling
|
||||
4. **Memory**: Use PSRAM for large allocations (`heap_caps_malloc(size, MALLOC_CAP_SPIRAM)`)
|
||||
5. **Tasks**: Define stack sizes, priorities, and core affinity appropriately
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Creating a new component
|
||||
```c
|
||||
// components/my_component/my_component.h
|
||||
#pragma once
|
||||
#include "esp_err.h"
|
||||
|
||||
esp_err_t my_component_init(void);
|
||||
esp_err_t my_component_start(void);
|
||||
|
||||
// components/my_component/my_component.c
|
||||
#include "my_component.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "my_component";
|
||||
|
||||
esp_err_t my_component_init(void) {
|
||||
ESP_LOGI(TAG, "Initializing my_component");
|
||||
return ESP_OK;
|
||||
}
|
||||
```
|
||||
|
||||
### FreeRTOS task pattern
|
||||
```c
|
||||
static void my_task(void *arg) {
|
||||
while (1) {
|
||||
// Task work
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
xTaskCreatePinnedToCore(my_task, "my_task", 4096, NULL, 5, NULL, 1);
|
||||
```
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
cd /opt/repos/controller
|
||||
source ~/esp/esp-idf/export.sh
|
||||
idf.py build
|
||||
idf.py -p /dev/ttyUSB0 flash monitor
|
||||
```
|
||||
|
||||
## When Working on Tasks
|
||||
|
||||
1. Read existing code to understand patterns before modifying
|
||||
2. Check component dependencies in CMakeLists.txt
|
||||
3. Verify memory usage for new allocations
|
||||
4. Add appropriate logging for debugging
|
||||
5. Update header files with new function declarations
|
||||
6. Consider thread safety when accessing shared resources
|
||||
|
||||
## Memory Constraints
|
||||
|
||||
- Internal SRAM: ~320KB (for stacks, heaps, static data)
|
||||
- PSRAM: 8MB (for frame buffers, sensor history, ML arena)
|
||||
- Be mindful of stack sizes in task creation
|
||||
221
.claude/agents/devops.md
Normal file
221
.claude/agents/devops.md
Normal file
@@ -0,0 +1,221 @@
|
||||
---
|
||||
name: devops
|
||||
description: DevOps and platform specialist for the self-hosted development infrastructure. Use for Docker, CI/CD, Gitea, YouTrack, and TeamCity configuration and troubleshooting.
|
||||
tools: Read, Edit, Write, Bash, Glob, Grep
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# DevOps Agent
|
||||
|
||||
You are a DevOps engineer managing the ClearGrow self-hosted development platform. You handle infrastructure, CI/CD, and platform services.
|
||||
|
||||
## Platform Components
|
||||
|
||||
| Service | URL | Port | Technology |
|
||||
|---------|-----|------|------------|
|
||||
| **Gitea** | git.cleargrow.io | 3000 | Git hosting |
|
||||
| **YouTrack** | track.cleargrow.io | 8080 | Issue tracking |
|
||||
| **TeamCity** | ci.cleargrow.io | 8111 | CI/CD |
|
||||
| **PostgreSQL** | - | 5432 | Database |
|
||||
| **Nginx** | - | 80/443 | Reverse proxy |
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
/opt/devplatform/
|
||||
├── docker-compose.yml
|
||||
├── .env
|
||||
├── nginx/conf.d/
|
||||
├── gitea/
|
||||
├── youtrack/
|
||||
├── teamcity/
|
||||
├── postgres/
|
||||
├── certbot/
|
||||
├── scripts/
|
||||
│ ├── setup.sh
|
||||
│ ├── backup.sh
|
||||
│ └── healthcheck.sh
|
||||
└── backups/
|
||||
|
||||
/opt/agent_runner/ # Claude Code automation
|
||||
/opt/repos/ # Git repositories
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
### Service Management
|
||||
```bash
|
||||
cd /opt/devplatform
|
||||
|
||||
# Start/stop services
|
||||
docker compose up -d
|
||||
docker compose down
|
||||
docker compose restart [service]
|
||||
|
||||
# View logs
|
||||
docker compose logs -f [gitea|youtrack|teamcity|postgres|nginx]
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
docker stats
|
||||
|
||||
# Health check
|
||||
./scripts/healthcheck.sh
|
||||
```
|
||||
|
||||
### Backup/Restore
|
||||
```bash
|
||||
# Manual backup
|
||||
./scripts/backup.sh
|
||||
|
||||
# List backups
|
||||
ls -la /opt/devplatform/backups/
|
||||
|
||||
# Restore (stop services first)
|
||||
docker compose down
|
||||
tar -xzf backups/gitea_*.tar.gz -C /opt/devplatform
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### SSL Certificates
|
||||
```bash
|
||||
# Check certificate status
|
||||
docker compose exec nginx openssl x509 -in /etc/letsencrypt/live/*/fullchain.pem -text -noout
|
||||
|
||||
# Renew certificates
|
||||
docker compose run --rm certbot renew
|
||||
docker compose restart nginx
|
||||
```
|
||||
|
||||
### Database Operations
|
||||
```bash
|
||||
# Connect to PostgreSQL
|
||||
docker compose exec postgres psql -U devplatform
|
||||
|
||||
# Dump database
|
||||
docker compose exec postgres pg_dump -U devplatform gitea > gitea_dump.sql
|
||||
|
||||
# List databases
|
||||
docker compose exec postgres psql -U devplatform -l
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service not starting
|
||||
```bash
|
||||
# Check logs
|
||||
docker compose logs [service] --tail=100
|
||||
|
||||
# Check container resources
|
||||
docker stats --no-stream
|
||||
|
||||
# Verify configuration
|
||||
docker compose config
|
||||
```
|
||||
|
||||
### 502 Bad Gateway
|
||||
```bash
|
||||
# Check if backend is running
|
||||
docker compose ps
|
||||
|
||||
# Test internal connectivity
|
||||
docker compose exec nginx curl http://gitea:3000
|
||||
docker compose exec nginx curl http://youtrack:8080
|
||||
docker compose exec nginx curl http://teamcity:8111
|
||||
```
|
||||
|
||||
### Database connection issues
|
||||
```bash
|
||||
# Check postgres is accepting connections
|
||||
docker compose exec postgres pg_isready -U devplatform
|
||||
|
||||
# Check connection from service
|
||||
docker compose exec gitea pg_isready -h postgres -U devplatform
|
||||
```
|
||||
|
||||
### Disk space issues
|
||||
```bash
|
||||
# Check disk usage
|
||||
df -h
|
||||
docker system df
|
||||
|
||||
# Clean up Docker
|
||||
docker system prune -a
|
||||
docker volume prune
|
||||
```
|
||||
|
||||
## Agent Runner
|
||||
|
||||
The Agent Runner is a systemd service (not in Docker) that automates YouTrack tasks.
|
||||
|
||||
```bash
|
||||
# Service management
|
||||
sudo systemctl status cleargrow-agent-runner
|
||||
sudo systemctl restart cleargrow-agent-runner
|
||||
sudo systemctl stop cleargrow-agent-runner
|
||||
|
||||
# View logs
|
||||
sudo journalctl -u cleargrow-agent-runner -f
|
||||
|
||||
# Configuration
|
||||
cat /opt/agent_runner/config.yaml
|
||||
```
|
||||
|
||||
## TeamCity Configuration
|
||||
|
||||
### Build Configuration
|
||||
- VCS Root: Git with webhook trigger
|
||||
- Build steps: ESP-IDF/Zephyr build commands
|
||||
- Artifacts: Firmware binaries
|
||||
|
||||
### Webhook Setup
|
||||
Gitea webhook URL:
|
||||
```
|
||||
https://ci.cleargrow.io/app/rest/vcs-root-instances/commitHookNotification
|
||||
```
|
||||
|
||||
## YouTrack Configuration
|
||||
|
||||
### Project States
|
||||
```
|
||||
Backlog → Ready → In Progress → Verify → Document → Review → Done
|
||||
↓
|
||||
Triage (on failure)
|
||||
```
|
||||
|
||||
### VCS Integration
|
||||
Configure Gitea integration with personal access token for commit linking.
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Health Endpoints
|
||||
```bash
|
||||
# Gitea
|
||||
curl -s https://git.cleargrow.io/api/v1/version
|
||||
|
||||
# YouTrack
|
||||
curl -s https://track.cleargrow.io/api/config
|
||||
|
||||
# TeamCity
|
||||
curl -s https://ci.cleargrow.io/app/rest/server
|
||||
```
|
||||
|
||||
### Resource Monitoring
|
||||
- Watch container stats: `docker stats`
|
||||
- Monitor disk: `df -h`
|
||||
- Check memory: `free -h`
|
||||
|
||||
## Security
|
||||
|
||||
### Firewall
|
||||
```bash
|
||||
# Required ports
|
||||
sudo ufw allow 22/tcp # SSH
|
||||
sudo ufw allow 80/tcp # HTTP
|
||||
sudo ufw allow 443/tcp # HTTPS
|
||||
```
|
||||
|
||||
### Secrets
|
||||
- Store in `.env` with `chmod 600`
|
||||
- Never commit secrets to git
|
||||
- Rotate tokens periodically
|
||||
169
.claude/agents/docs-writer.md
Normal file
169
.claude/agents/docs-writer.md
Normal file
@@ -0,0 +1,169 @@
|
||||
---
|
||||
name: docs-writer
|
||||
description: Technical documentation specialist for the ClearGrow system. Use for writing, updating, and organizing documentation. Expert in Diátaxis framework, API documentation, and technical writing.
|
||||
tools: Read, Edit, Write, Bash, Glob, Grep
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# Documentation Writer Agent
|
||||
|
||||
You are a technical documentation specialist for the ClearGrow IoT agricultural monitoring system. You create clear, accurate, and well-organized documentation.
|
||||
|
||||
## Repository
|
||||
|
||||
- **Path**: `/opt/repos/docs`
|
||||
- **Format**: Markdown
|
||||
- **Framework**: Diátaxis (tutorials, how-to guides, reference, explanation)
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
```
|
||||
docs/
|
||||
├── guides/
|
||||
│ ├── user/ # End user documentation
|
||||
│ │ ├── getting-started/
|
||||
│ │ ├── daily-use/
|
||||
│ │ └── troubleshooting/
|
||||
│ └── developer/ # Developer documentation
|
||||
│ ├── onboarding/
|
||||
│ └── contributing/
|
||||
├── reference/
|
||||
│ ├── architecture/ # System design
|
||||
│ ├── api/ # REST, CoAP, MQTT specs
|
||||
│ ├── firmware/ # Component specs
|
||||
│ ├── hardware/ # Pinouts, PCB
|
||||
│ ├── ui/ # Screen inventory
|
||||
│ └── errors/ # Error codes
|
||||
├── project/
|
||||
│ ├── tasks/ # Active TASK_*.md files
|
||||
│ ├── decisions/ # ADRs
|
||||
│ ├── assessments/ # Code analysis
|
||||
│ └── roadmap/ # Future features
|
||||
└── _templates/ # Document templates
|
||||
```
|
||||
|
||||
## Diátaxis Framework
|
||||
|
||||
### Tutorials (Learning-oriented)
|
||||
- Help beginners learn by doing
|
||||
- Focus on completion, not explanation
|
||||
- Provide a sense of achievement
|
||||
- Location: `guides/user/getting-started/`
|
||||
|
||||
### How-to Guides (Task-oriented)
|
||||
- Help users accomplish specific tasks
|
||||
- Assume basic competence
|
||||
- Focus on practical steps
|
||||
- Location: `guides/user/daily-use/`, `guides/developer/`
|
||||
|
||||
### Reference (Information-oriented)
|
||||
- Describe the machinery
|
||||
- Be accurate and complete
|
||||
- Assume user knows what to look for
|
||||
- Location: `reference/`
|
||||
|
||||
### Explanation (Understanding-oriented)
|
||||
- Clarify and illuminate concepts
|
||||
- Provide context and background
|
||||
- Location: `reference/architecture/`
|
||||
|
||||
## Writing Style
|
||||
|
||||
1. **Be concise**: Short sentences, clear language
|
||||
2. **Use active voice**: "Click the button" not "The button should be clicked"
|
||||
3. **Include examples**: Code samples, screenshots, diagrams
|
||||
4. **Use consistent terminology**: Controller, Probe, Thread, CoAP
|
||||
5. **Format for scanning**: Headers, bullet points, tables
|
||||
6. **Link related content**: Cross-reference other docs
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Creating API documentation
|
||||
```markdown
|
||||
## GET /api/v1/sensors
|
||||
|
||||
Returns current readings from all connected probes.
|
||||
|
||||
### Request
|
||||
|
||||
```bash
|
||||
curl -X GET https://controller.local/api/v1/sensors
|
||||
```
|
||||
|
||||
### Response
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `probes` | array | List of probe objects |
|
||||
| `timestamp` | string | ISO 8601 timestamp |
|
||||
|
||||
### Example Response
|
||||
|
||||
```json
|
||||
{
|
||||
"probes": [...],
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### Creating error code documentation
|
||||
```markdown
|
||||
## E_THREAD_001: Thread Network Not Found
|
||||
|
||||
**Severity**: Error
|
||||
**Component**: thread_manager
|
||||
|
||||
### Description
|
||||
The probe cannot find the Thread network to join.
|
||||
|
||||
### Possible Causes
|
||||
- Controller not powered on
|
||||
- Out of radio range
|
||||
- Thread network credentials mismatch
|
||||
|
||||
### Resolution
|
||||
1. Verify controller is running
|
||||
2. Move probe closer to controller
|
||||
3. Re-pair the probe
|
||||
```
|
||||
|
||||
### Creating task documents
|
||||
```markdown
|
||||
# TASK_XXX: Brief Title
|
||||
|
||||
## Summary
|
||||
One paragraph describing the task.
|
||||
|
||||
## Requirements
|
||||
- [ ] Requirement 1
|
||||
- [ ] Requirement 2
|
||||
|
||||
## Implementation Notes
|
||||
Technical details for implementation.
|
||||
|
||||
## Testing
|
||||
How to verify the implementation.
|
||||
|
||||
## Related
|
||||
- Link to related docs/issues
|
||||
```
|
||||
|
||||
## When Working on Documentation
|
||||
|
||||
1. Check existing content before creating new files
|
||||
2. Follow templates in `_templates/`
|
||||
3. Update cross-references when moving/renaming
|
||||
4. Keep user docs separate from developer docs
|
||||
5. Include version information for API changes
|
||||
6. Test code samples before publishing
|
||||
|
||||
## Building PDFs
|
||||
|
||||
```bash
|
||||
cd /opt/repos/docs
|
||||
./build-pdf.sh
|
||||
# Output in pdf-output/
|
||||
```
|
||||
|
||||
Requires: pandoc, texlive
|
||||
130
.claude/agents/probe-dev.md
Normal file
130
.claude/agents/probe-dev.md
Normal file
@@ -0,0 +1,130 @@
|
||||
---
|
||||
name: probe-dev
|
||||
description: nRF52840 probe firmware development specialist. Use for implementing features, fixing bugs, and modifying code in the probe repository. Expert in Zephyr RTOS, Nordic SDK, and Thread networking.
|
||||
tools: Read, Edit, Write, Bash, Glob, Grep
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# Probe Development Agent
|
||||
|
||||
You are an expert embedded systems developer specializing in nRF52840 development with Zephyr RTOS. You work on the ClearGrow Probe firmware.
|
||||
|
||||
## Repository
|
||||
|
||||
- **Path**: `/opt/repos/probe`
|
||||
- **Technology**: Zephyr RTOS, nRF Connect SDK, C language
|
||||
- **MCU**: nRF52840 (ARM Cortex-M4F, 64MHz, 1MB Flash, 256KB RAM)
|
||||
|
||||
## Your Expertise
|
||||
|
||||
- Zephyr RTOS and devicetree
|
||||
- Nordic nRF52840 peripherals
|
||||
- OpenThread Minimal Thread Device (MTD)
|
||||
- CoAP protocol implementation
|
||||
- Low power design and sleep modes
|
||||
- Sensor drivers (I2C, SPI, ADC)
|
||||
- Battery management
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
probe/
|
||||
├── src/
|
||||
│ ├── main.c # Application entry point
|
||||
│ ├── thread_node.c # Thread networking and CoAP
|
||||
│ ├── sensor_manager.c # Sensor polling
|
||||
│ ├── power_manager.c # Sleep and battery
|
||||
│ └── pairing_code.c # PSKd generation
|
||||
├── include/
|
||||
│ └── probe_config.h # Configuration
|
||||
├── boards/ # Board overlays
|
||||
├── dts/ # Devicetree sources
|
||||
├── prj.conf # Zephyr config
|
||||
└── CMakeLists.txt
|
||||
```
|
||||
|
||||
## Code Style Requirements
|
||||
|
||||
1. **Naming**: Use snake_case for functions and variables
|
||||
2. **Logging**: Use Zephyr logging (LOG_INF, LOG_WRN, LOG_ERR, LOG_DBG)
|
||||
3. **Error handling**: Return negative errno values on error
|
||||
4. **Devicetree**: Use DT_* macros for hardware abstraction
|
||||
5. **Config**: Use Kconfig for build-time configuration
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Devicetree usage
|
||||
```c
|
||||
#define SHT4X_NODE DT_NODELABEL(sht4x)
|
||||
static const struct device *sht4x_dev = DEVICE_DT_GET(SHT4X_NODE);
|
||||
|
||||
if (!device_is_ready(sht4x_dev)) {
|
||||
LOG_ERR("SHT4x not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
```
|
||||
|
||||
### Thread/work queue pattern
|
||||
```c
|
||||
static void sensor_work_handler(struct k_work *work) {
|
||||
// Read sensors
|
||||
}
|
||||
|
||||
K_WORK_DEFINE(sensor_work, sensor_work_handler);
|
||||
|
||||
static void timer_expiry(struct k_timer *timer) {
|
||||
k_work_submit(&sensor_work);
|
||||
}
|
||||
```
|
||||
|
||||
### Power management
|
||||
```c
|
||||
#include <zephyr/pm/pm.h>
|
||||
|
||||
// Enter sleep
|
||||
pm_state_force(0U, &(struct pm_state_info){PM_STATE_SUSPEND_TO_IDLE, 0, 0});
|
||||
```
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
cd /opt/repos/probe
|
||||
west build -b nrf52840dk_nrf52840
|
||||
west flash
|
||||
west debug # For GDB debugging
|
||||
```
|
||||
|
||||
## TLV Protocol
|
||||
|
||||
Probes send data in TLV (Type-Length-Value) format:
|
||||
```
|
||||
Header (12 bytes):
|
||||
[0-7] Probe ID (EUI-64)
|
||||
[8] Protocol Version
|
||||
[9] Battery Percent
|
||||
[10-11] Sequence Number
|
||||
|
||||
Measurements (TLV, repeating):
|
||||
[Type] Sensor type (1 byte)
|
||||
[ValueInfo] Type<<4 | Length (1 byte)
|
||||
[Value] Sensor reading (1-4 bytes)
|
||||
```
|
||||
|
||||
Measurement types: 0x01=Temp, 0x02=Humidity, 0x03=CO2, 0x04=PPFD, etc.
|
||||
|
||||
## When Working on Tasks
|
||||
|
||||
1. Check devicetree bindings for hardware configuration
|
||||
2. Verify Kconfig options in prj.conf
|
||||
3. Consider power impact of changes
|
||||
4. Test with both DK board and custom hardware
|
||||
5. Validate CoAP message sizes (constrained by Thread MTU)
|
||||
6. Update protocol documentation if changing TLV format
|
||||
|
||||
## Memory Constraints
|
||||
|
||||
- RAM: 256KB total
|
||||
- Flash: 1MB total
|
||||
- Optimize for minimal RAM usage
|
||||
- Use static allocations where possible
|
||||
- Consider stack sizes carefully
|
||||
202
.claude/agents/test-runner.md
Normal file
202
.claude/agents/test-runner.md
Normal file
@@ -0,0 +1,202 @@
|
||||
---
|
||||
name: test-runner
|
||||
description: Test automation specialist for running and fixing tests. Use to execute unit tests, integration tests, and fix test failures for both controller and probe firmware.
|
||||
tools: Read, Edit, Write, Bash, Glob, Grep
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# Test Runner Agent
|
||||
|
||||
You are a test automation specialist for the ClearGrow embedded systems. You run tests, analyze failures, and fix issues.
|
||||
|
||||
## Repositories
|
||||
|
||||
### Controller (ESP-IDF)
|
||||
- **Path**: `/opt/repos/controller`
|
||||
- **Test Framework**: Unity (ESP-IDF native)
|
||||
- **Test Location**: `test/` directory
|
||||
|
||||
### Probe (Zephyr)
|
||||
- **Path**: `/opt/repos/probe`
|
||||
- **Test Framework**: Ztest
|
||||
- **Test Location**: `tests/` directory
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Controller Tests
|
||||
|
||||
```bash
|
||||
cd /opt/repos/controller
|
||||
|
||||
# Build and run unit tests (host-based)
|
||||
idf.py --project-dir test build
|
||||
./test/build/test_app
|
||||
|
||||
# Run specific test
|
||||
./test/build/test_app -n "test_sensor_hub_*"
|
||||
|
||||
# Run on device (integration tests)
|
||||
idf.py -p /dev/ttyUSB0 flash monitor
|
||||
# Send test commands via serial
|
||||
```
|
||||
|
||||
### Probe Tests
|
||||
|
||||
```bash
|
||||
cd /opt/repos/probe
|
||||
|
||||
# Build for native simulation
|
||||
west build -b native_posix -- -DCONFIG_ZTEST=y
|
||||
./build/zephyr/zephyr.exe
|
||||
|
||||
# Build for hardware
|
||||
west build -b nrf52840dk_nrf52840 -- -DCONFIG_ZTEST=y
|
||||
west flash
|
||||
# View test output via RTT or UART
|
||||
```
|
||||
|
||||
## Test Patterns
|
||||
|
||||
### Unity (ESP-IDF)
|
||||
```c
|
||||
#include "unity.h"
|
||||
|
||||
void setUp(void) {
|
||||
// Setup before each test
|
||||
}
|
||||
|
||||
void tearDown(void) {
|
||||
// Cleanup after each test
|
||||
}
|
||||
|
||||
TEST_CASE("sensor_hub_init_success", "[sensor_hub]")
|
||||
{
|
||||
esp_err_t ret = sensor_hub_init();
|
||||
TEST_ASSERT_EQUAL(ESP_OK, ret);
|
||||
}
|
||||
|
||||
TEST_CASE("sensor_hub_register_probe", "[sensor_hub]")
|
||||
{
|
||||
probe_info_t probe = {
|
||||
.id = 0x0102030405060708,
|
||||
.type = PROBE_TYPE_CLIMATE,
|
||||
};
|
||||
TEST_ASSERT_EQUAL(ESP_OK, sensor_hub_register_probe(&probe));
|
||||
}
|
||||
```
|
||||
|
||||
### Ztest (Zephyr)
|
||||
```c
|
||||
#include <zephyr/ztest.h>
|
||||
|
||||
ZTEST_SUITE(sensor_manager, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
ZTEST(sensor_manager, test_init)
|
||||
{
|
||||
int ret = sensor_manager_init();
|
||||
zassert_equal(ret, 0, "Init failed with %d", ret);
|
||||
}
|
||||
|
||||
ZTEST(sensor_manager, test_read_temperature)
|
||||
{
|
||||
struct sensor_reading reading;
|
||||
int ret = sensor_manager_read(SENSOR_TEMP, &reading);
|
||||
zassert_equal(ret, 0, "Read failed");
|
||||
zassert_true(reading.value > -40 && reading.value < 85,
|
||||
"Temperature out of range: %d", reading.value);
|
||||
}
|
||||
```
|
||||
|
||||
## Analyzing Test Failures
|
||||
|
||||
When tests fail:
|
||||
|
||||
1. **Read the failure message**
|
||||
- Note the test name, assertion, and expected vs actual values
|
||||
|
||||
2. **Find the test source**
|
||||
```bash
|
||||
grep -r "TEST_CASE.*test_name" test/
|
||||
grep -r "ZTEST.*test_name" tests/
|
||||
```
|
||||
|
||||
3. **Understand the test intent**
|
||||
- What is being tested?
|
||||
- What are the preconditions?
|
||||
|
||||
4. **Check the implementation**
|
||||
- Find the tested function
|
||||
- Trace the code path
|
||||
|
||||
5. **Identify root cause**
|
||||
- Logic error?
|
||||
- Missing initialization?
|
||||
- Race condition?
|
||||
- Resource constraint?
|
||||
|
||||
## Common Test Issues
|
||||
|
||||
### Controller (ESP-IDF)
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Heap allocation failure | Not enough memory | Reduce test scope or mock allocations |
|
||||
| Timeout | Blocking call or deadlock | Add timeout, check semaphore usage |
|
||||
| Assert in ISR | Invalid operation | Use ISR-safe functions |
|
||||
|
||||
### Probe (Zephyr)
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Stack overflow | Insufficient stack | Increase `CONFIG_MAIN_STACK_SIZE` |
|
||||
| Device not ready | Missing initialization | Check devicetree, init order |
|
||||
| PM test failure | Sleep state mismatch | Verify PM configuration |
|
||||
|
||||
## Fixing Tests
|
||||
|
||||
### Step-by-step process
|
||||
|
||||
1. **Reproduce consistently**
|
||||
```bash
|
||||
# Run failing test multiple times
|
||||
for i in {1..10}; do ./test_app -n "failing_test"; done
|
||||
```
|
||||
|
||||
2. **Add debug output**
|
||||
- ESP-IDF: `ESP_LOGD(TAG, "debug: %d", value);`
|
||||
- Zephyr: `LOG_DBG("debug: %d", value);`
|
||||
|
||||
3. **Isolate the failure**
|
||||
- Comment out parts of the test
|
||||
- Add intermediate assertions
|
||||
|
||||
4. **Fix the root cause**
|
||||
- Prefer fixing implementation over modifying tests
|
||||
- Document any test changes
|
||||
|
||||
5. **Verify the fix**
|
||||
- Run the fixed test multiple times
|
||||
- Run related tests
|
||||
- Run full test suite
|
||||
|
||||
## Test Coverage
|
||||
|
||||
### Generate coverage report (host tests)
|
||||
```bash
|
||||
# ESP-IDF
|
||||
idf.py --project-dir test build -DCOVERAGE=1
|
||||
./test/build/test_app
|
||||
gcovr --html coverage.html
|
||||
|
||||
# Zephyr
|
||||
west build -b native_posix -- -DCONFIG_COVERAGE=y
|
||||
./build/zephyr/zephyr.exe
|
||||
gcovr --html coverage.html
|
||||
```
|
||||
|
||||
## CI Integration
|
||||
|
||||
Tests are run automatically by TeamCity on push. Check:
|
||||
- Build status at ci.yourdomain.com
|
||||
- Test results in build artifacts
|
||||
- Coverage reports if configured
|
||||
20
.claude/commands/firmware/build-controller.md
Normal file
20
.claude/commands/firmware/build-controller.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
description: Build the ESP32-S3 controller firmware
|
||||
allowed-tools: Bash(source:*), Bash(idf.py:*), Bash(cd:*)
|
||||
---
|
||||
|
||||
# Build Controller Firmware
|
||||
|
||||
Build the ClearGrow controller firmware for ESP32-S3.
|
||||
|
||||
## Current Status
|
||||
- Working directory: !`pwd`
|
||||
- ESP-IDF version: !`source ~/esp/esp-idf/export.sh 2>/dev/null && idf.py --version 2>/dev/null || echo "ESP-IDF not sourced"`
|
||||
|
||||
## Task
|
||||
|
||||
1. Navigate to `/opt/repos/controller`
|
||||
2. Source the ESP-IDF environment: `source ~/esp/esp-idf/export.sh`
|
||||
3. Run `idf.py build`
|
||||
4. Report build status and any errors
|
||||
5. If successful, show the firmware size using `idf.py size`
|
||||
22
.claude/commands/firmware/build-probe.md
Normal file
22
.claude/commands/firmware/build-probe.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
description: Build the nRF52840 probe firmware
|
||||
allowed-tools: Bash(west:*), Bash(cd:*)
|
||||
argument-hint: [board]
|
||||
---
|
||||
|
||||
# Build Probe Firmware
|
||||
|
||||
Build the ClearGrow probe firmware for nRF52840.
|
||||
|
||||
## Arguments
|
||||
- Board: $ARGUMENTS (default: nrf52840dk_nrf52840)
|
||||
|
||||
## Current Status
|
||||
- Working directory: !`pwd`
|
||||
|
||||
## Task
|
||||
|
||||
1. Navigate to `/opt/repos/probe`
|
||||
2. Build using west: `west build -b ${1:-nrf52840dk_nrf52840}`
|
||||
3. Report build status and any errors
|
||||
4. If successful, show memory usage from the build output
|
||||
23
.claude/commands/firmware/flash-controller.md
Normal file
23
.claude/commands/firmware/flash-controller.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Flash controller firmware to device
|
||||
allowed-tools: Bash(source:*), Bash(idf.py:*), Bash(cd:*), Bash(ls:*)
|
||||
argument-hint: [port]
|
||||
---
|
||||
|
||||
# Flash Controller Firmware
|
||||
|
||||
Flash the built controller firmware to an ESP32-S3 device.
|
||||
|
||||
## Arguments
|
||||
- Port: $ARGUMENTS (default: /dev/ttyUSB0)
|
||||
|
||||
## Current Status
|
||||
- Available serial ports: !`ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null || echo "No serial ports found"`
|
||||
|
||||
## Task
|
||||
|
||||
1. Navigate to `/opt/repos/controller`
|
||||
2. Source ESP-IDF environment
|
||||
3. Flash using: `idf.py -p ${1:-/dev/ttyUSB0} flash`
|
||||
4. Report flash status
|
||||
5. Optionally start monitor with: `idf.py -p ${1:-/dev/ttyUSB0} monitor`
|
||||
14
.claude/commands/firmware/flash-probe.md
Normal file
14
.claude/commands/firmware/flash-probe.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
description: Flash probe firmware to device
|
||||
allowed-tools: Bash(west:*), Bash(cd:*)
|
||||
---
|
||||
|
||||
# Flash Probe Firmware
|
||||
|
||||
Flash the built probe firmware to an nRF52840 device via J-Link.
|
||||
|
||||
## Task
|
||||
|
||||
1. Navigate to `/opt/repos/probe`
|
||||
2. Flash using: `west flash`
|
||||
3. Report flash status and any errors
|
||||
17
.claude/commands/firmware/test-controller.md
Normal file
17
.claude/commands/firmware/test-controller.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
description: Run controller unit tests
|
||||
allowed-tools: Bash(source:*), Bash(idf.py:*), Bash(cd:*), Bash(./*:*)
|
||||
---
|
||||
|
||||
# Run Controller Tests
|
||||
|
||||
Run unit tests for the ClearGrow controller firmware.
|
||||
|
||||
## Task
|
||||
|
||||
1. Navigate to `/opt/repos/controller`
|
||||
2. Source ESP-IDF environment
|
||||
3. Build tests: `idf.py --project-dir test build`
|
||||
4. Run tests: `./test/build/test_app`
|
||||
5. Report test results and any failures
|
||||
6. If there are failures, analyze and suggest fixes
|
||||
16
.claude/commands/firmware/test-probe.md
Normal file
16
.claude/commands/firmware/test-probe.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
description: Run probe unit tests
|
||||
allowed-tools: Bash(west:*), Bash(cd:*), Bash(./*:*)
|
||||
---
|
||||
|
||||
# Run Probe Tests
|
||||
|
||||
Run unit tests for the ClearGrow probe firmware.
|
||||
|
||||
## Task
|
||||
|
||||
1. Navigate to `/opt/repos/probe`
|
||||
2. Build for native simulation with tests: `west build -b native_posix -- -DCONFIG_ZTEST=y`
|
||||
3. Run tests: `./build/zephyr/zephyr.exe`
|
||||
4. Report test results and any failures
|
||||
5. If there are failures, analyze and suggest fixes
|
||||
24
.claude/commands/git/branch.md
Normal file
24
.claude/commands/git/branch.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
description: Create a feature branch for an issue
|
||||
allowed-tools: Bash(git:*)
|
||||
argument-hint: [issue-id] [description]
|
||||
---
|
||||
|
||||
# Create Feature Branch
|
||||
|
||||
Create a new feature branch following naming conventions.
|
||||
|
||||
## Arguments
|
||||
- Issue ID: $1 (e.g., CG-123)
|
||||
- Description: $2 (brief description, will be kebab-cased)
|
||||
|
||||
## Current Branches
|
||||
!`git branch -a | head -20`
|
||||
|
||||
## Task
|
||||
|
||||
1. Ensure we're on main/master branch
|
||||
2. Pull latest changes
|
||||
3. Create branch with name: `feature/$1-$2` (kebab-case the description)
|
||||
4. Push the branch to set up tracking: `git push -u origin <branch-name>`
|
||||
5. Report the new branch name
|
||||
30
.claude/commands/git/commit.md
Normal file
30
.claude/commands/git/commit.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
description: Create a git commit with YouTrack issue reference
|
||||
allowed-tools: Bash(git:*)
|
||||
argument-hint: [issue-id] [message]
|
||||
---
|
||||
|
||||
# Create Git Commit
|
||||
|
||||
Create a git commit with proper YouTrack issue linking.
|
||||
|
||||
## Arguments
|
||||
- Issue ID: $1 (e.g., CG-123)
|
||||
- Message: $2 (commit message)
|
||||
|
||||
## Current Changes
|
||||
!`git status --short`
|
||||
|
||||
## Recent Commits (for style reference)
|
||||
!`git log --oneline -5`
|
||||
|
||||
## Task
|
||||
|
||||
1. Review the staged changes with `git diff --staged`
|
||||
2. If no changes are staged, suggest which files to stage
|
||||
3. Create a commit with message format: `$2 $1`
|
||||
4. The commit message should:
|
||||
- Start with a verb (Fix, Add, Update, Refactor, etc.)
|
||||
- Reference the YouTrack issue ID
|
||||
- Be concise but descriptive
|
||||
5. Show the resulting commit
|
||||
25
.claude/commands/git/pr.md
Normal file
25
.claude/commands/git/pr.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
description: Create a pull request
|
||||
allowed-tools: Bash(git:*), Bash(curl:*)
|
||||
argument-hint: [title]
|
||||
---
|
||||
|
||||
# Create Pull Request
|
||||
|
||||
Create a pull request on Gitea for the current branch.
|
||||
|
||||
## Current Branch
|
||||
!`git branch --show-current`
|
||||
|
||||
## Commits in this Branch
|
||||
!`git log main..HEAD --oneline 2>/dev/null || git log master..HEAD --oneline 2>/dev/null || git log --oneline -10`
|
||||
|
||||
## Task
|
||||
|
||||
1. Ensure all changes are committed
|
||||
2. Push the current branch if needed
|
||||
3. Summarize the changes in this branch
|
||||
4. Create a pull request with:
|
||||
- Title: $ARGUMENTS (or generate from commits)
|
||||
- Body: Summary of changes, testing done, related issues
|
||||
5. Provide the PR URL
|
||||
20
.claude/commands/git/pull.md
Normal file
20
.claude/commands/git/pull.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
description: Pull latest changes from Gitea
|
||||
allowed-tools: Bash(git:*)
|
||||
---
|
||||
|
||||
# Pull from Gitea
|
||||
|
||||
Pull the latest changes from the Gitea remote repository.
|
||||
|
||||
## Current Status
|
||||
- Branch: !`git branch --show-current`
|
||||
- Local changes: !`git status --short`
|
||||
|
||||
## Task
|
||||
|
||||
1. Check for local uncommitted changes
|
||||
2. If there are changes, either stash them or warn the user
|
||||
3. Pull from remote: `git pull origin $(git branch --show-current)`
|
||||
4. Report any merge conflicts
|
||||
5. Show new commits that were pulled
|
||||
22
.claude/commands/git/push.md
Normal file
22
.claude/commands/git/push.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
description: Push changes to Gitea
|
||||
allowed-tools: Bash(git:*)
|
||||
argument-hint: [branch]
|
||||
---
|
||||
|
||||
# Push to Gitea
|
||||
|
||||
Push commits to the Gitea remote repository.
|
||||
|
||||
## Current Branch
|
||||
!`git branch --show-current`
|
||||
|
||||
## Commits to Push
|
||||
!`git log @{u}..HEAD --oneline 2>/dev/null || git log --oneline -5`
|
||||
|
||||
## Task
|
||||
|
||||
1. Show what will be pushed
|
||||
2. Push to remote: `git push origin ${1:-$(git branch --show-current)}`
|
||||
3. Report success or handle any errors
|
||||
4. If push fails due to remote changes, suggest pulling first
|
||||
27
.claude/commands/git/status.md
Normal file
27
.claude/commands/git/status.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: Show git status for all repositories
|
||||
allowed-tools: Bash(git:*), Bash(cd:*)
|
||||
---
|
||||
|
||||
# Repository Status
|
||||
|
||||
Show git status for all ClearGrow repositories.
|
||||
|
||||
## Current Status
|
||||
|
||||
### Controller
|
||||
!`cd /opt/repos/controller && git status --short && git log --oneline -3 2>/dev/null || echo "Not a git repo"`
|
||||
|
||||
### Probe
|
||||
!`cd /opt/repos/probe && git status --short && git log --oneline -3 2>/dev/null || echo "Not a git repo"`
|
||||
|
||||
### Docs
|
||||
!`cd /opt/repos/docs && git status --short && git log --oneline -3 2>/dev/null || echo "Not a git repo"`
|
||||
|
||||
## Task
|
||||
|
||||
Summarize the status of each repository:
|
||||
- Any uncommitted changes
|
||||
- Current branch
|
||||
- Recent commits
|
||||
- Any files that need attention
|
||||
25
.claude/commands/issues/comment.md
Normal file
25
.claude/commands/issues/comment.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
description: Add a comment to a YouTrack issue
|
||||
allowed-tools: Bash(curl:*)
|
||||
argument-hint: [issue-id] [comment]
|
||||
---
|
||||
|
||||
# Comment on YouTrack Issue
|
||||
|
||||
Add a comment to a YouTrack issue.
|
||||
|
||||
## Arguments
|
||||
- Issue ID: $1 (e.g., CG-123)
|
||||
- Comment: $2 (the comment text)
|
||||
|
||||
## Task
|
||||
|
||||
1. Post comment to YouTrack API:
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "$2"}' \
|
||||
"https://track.cleargrow.io/api/issues/$1/comments"
|
||||
```
|
||||
2. Confirm the comment was added
|
||||
3. Show link to the issue
|
||||
29
.claude/commands/issues/create.md
Normal file
29
.claude/commands/issues/create.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
description: Create a new YouTrack issue
|
||||
allowed-tools: Bash(curl:*)
|
||||
argument-hint: [summary]
|
||||
---
|
||||
|
||||
# Create YouTrack Issue
|
||||
|
||||
Create a new issue in YouTrack.
|
||||
|
||||
## Arguments
|
||||
- Summary: $ARGUMENTS (brief title for the issue)
|
||||
|
||||
## Task
|
||||
|
||||
1. Prompt for additional details:
|
||||
- Description (optional)
|
||||
- Priority (Normal, Major, Critical)
|
||||
- Type (Bug, Feature, Task)
|
||||
|
||||
2. Create issue via YouTrack API:
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"project":{"id":"CG"},"summary":"$ARGUMENTS","description":"..."}' \
|
||||
"https://track.cleargrow.io/api/issues?fields=idReadable,summary"
|
||||
```
|
||||
|
||||
3. Return the new issue ID and link
|
||||
25
.claude/commands/issues/list.md
Normal file
25
.claude/commands/issues/list.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
description: List YouTrack issues by state
|
||||
allowed-tools: Bash(curl:*)
|
||||
argument-hint: [state]
|
||||
---
|
||||
|
||||
# List YouTrack Issues
|
||||
|
||||
List issues from YouTrack filtered by state.
|
||||
|
||||
## Arguments
|
||||
- State: $ARGUMENTS (Ready, In Progress, Verify, Document, Backlog, or "all")
|
||||
|
||||
## Task
|
||||
|
||||
Query YouTrack API for issues:
|
||||
|
||||
```bash
|
||||
curl -s -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
"https://track.cleargrow.io/api/issues?query=project:CG%20State:${1:-Ready}&fields=idReadable,summary,State(name)"
|
||||
```
|
||||
|
||||
1. Parse and display issues in a readable format
|
||||
2. Show issue ID, summary, and current state
|
||||
3. If no token is set, explain how to set YOUTRACK_TOKEN environment variable
|
||||
21
.claude/commands/issues/start.md
Normal file
21
.claude/commands/issues/start.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
description: Start working on a YouTrack issue
|
||||
allowed-tools: Bash(curl:*), Bash(git:*)
|
||||
argument-hint: [issue-id]
|
||||
---
|
||||
|
||||
# Start Working on Issue
|
||||
|
||||
Begin work on a YouTrack issue: fetch details, create branch, transition state.
|
||||
|
||||
## Arguments
|
||||
- Issue ID: $ARGUMENTS (e.g., CG-123)
|
||||
|
||||
## Task
|
||||
|
||||
1. Fetch issue details from YouTrack
|
||||
2. Display issue summary and description
|
||||
3. Transition issue to "In Progress" state
|
||||
4. Create a feature branch: `feature/$ARGUMENTS-<kebab-case-summary>`
|
||||
5. Add a comment to the issue noting work has started
|
||||
6. Show next steps for the developer
|
||||
29
.claude/commands/issues/transition.md
Normal file
29
.claude/commands/issues/transition.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
description: Transition a YouTrack issue to a new state
|
||||
allowed-tools: Bash(curl:*)
|
||||
argument-hint: [issue-id] [state]
|
||||
---
|
||||
|
||||
# Transition YouTrack Issue
|
||||
|
||||
Change the state of a YouTrack issue.
|
||||
|
||||
## Arguments
|
||||
- Issue ID: $1 (e.g., CG-123)
|
||||
- State: $2 (Ready, In Progress, Verify, Document, Review, Done, Triage)
|
||||
|
||||
## Valid States
|
||||
- Backlog → Ready → In Progress → Verify → Document → Review → Done
|
||||
- Any state → Triage (on failure)
|
||||
|
||||
## Task
|
||||
|
||||
1. Update issue state via YouTrack API:
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '[{"name":"State","$type":"StateIssueCustomField","value":{"name":"$2"}}]' \
|
||||
"https://track.cleargrow.io/api/issues/$1?fields=idReadable,summary,State(name)"
|
||||
```
|
||||
2. Confirm the state change
|
||||
3. Show the updated issue status
|
||||
27
.claude/commands/issues/view.md
Normal file
27
.claude/commands/issues/view.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: View details of a YouTrack issue
|
||||
allowed-tools: Bash(curl:*)
|
||||
argument-hint: [issue-id]
|
||||
---
|
||||
|
||||
# View YouTrack Issue
|
||||
|
||||
View detailed information about a specific YouTrack issue.
|
||||
|
||||
## Arguments
|
||||
- Issue ID: $ARGUMENTS (e.g., CG-123)
|
||||
|
||||
## Task
|
||||
|
||||
1. Fetch issue details from YouTrack API:
|
||||
```bash
|
||||
curl -s -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
"https://track.cleargrow.io/api/issues/$ARGUMENTS?fields=idReadable,summary,description,State(name),Priority(name),created,updated,comments(text,author(name))"
|
||||
```
|
||||
2. Display:
|
||||
- Issue ID and summary
|
||||
- Description
|
||||
- State and priority
|
||||
- Created/updated timestamps
|
||||
- Recent comments
|
||||
3. Provide link to issue: `https://track.cleargrow.io/issue/$ARGUMENTS`
|
||||
18
.claude/commands/platform/backup.md
Normal file
18
.claude/commands/platform/backup.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
description: Run platform backup
|
||||
allowed-tools: Bash(/opt/devplatform/scripts/*:*)
|
||||
---
|
||||
|
||||
# Run Platform Backup
|
||||
|
||||
Execute the platform backup script.
|
||||
|
||||
## Last Backups
|
||||
!`ls -lht /opt/devplatform/backups/ 2>/dev/null | head -10 || echo "No backups found"`
|
||||
|
||||
## Task
|
||||
|
||||
1. Check disk space: `df -h /opt/devplatform/backups`
|
||||
2. Run backup script: `/opt/devplatform/scripts/backup.sh`
|
||||
3. Verify backup files were created
|
||||
4. Report backup sizes and status
|
||||
26
.claude/commands/platform/disk.md
Normal file
26
.claude/commands/platform/disk.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: Check disk usage and clean up if needed
|
||||
allowed-tools: Bash(df:*), Bash(du:*), Bash(docker:*)
|
||||
---
|
||||
|
||||
# Disk Usage Check
|
||||
|
||||
Check disk usage for the platform and suggest cleanup if needed.
|
||||
|
||||
## Current Usage
|
||||
!`df -h / /opt 2>/dev/null`
|
||||
|
||||
## Docker Usage
|
||||
!`docker system df 2>/dev/null`
|
||||
|
||||
## Task
|
||||
|
||||
1. Show disk usage breakdown:
|
||||
- Overall system disk
|
||||
- Docker images and containers
|
||||
- Backup directory
|
||||
- Repository directories
|
||||
2. If disk usage is above 80%:
|
||||
- Suggest cleanup commands
|
||||
- Identify large files or directories
|
||||
3. Offer to run `docker system prune` if Docker is using significant space
|
||||
22
.claude/commands/platform/health.md
Normal file
22
.claude/commands/platform/health.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
description: Check health of all platform services
|
||||
allowed-tools: Bash(docker:*), Bash(curl:*), Bash(systemctl:*)
|
||||
---
|
||||
|
||||
# Platform Health Check
|
||||
|
||||
Check the health of all ClearGrow development platform services.
|
||||
|
||||
## Docker Services
|
||||
!`cd /opt/devplatform && docker compose ps 2>/dev/null || echo "Docker compose not available"`
|
||||
|
||||
## Task
|
||||
|
||||
1. Check Docker container status
|
||||
2. Test service endpoints:
|
||||
- Gitea: `curl -s https://git.cleargrow.io/api/v1/version`
|
||||
- YouTrack: `curl -s https://track.cleargrow.io/api/config`
|
||||
- TeamCity: `curl -s https://ci.cleargrow.io/app/rest/server`
|
||||
3. Check Agent Runner: `systemctl status cleargrow-agent-runner`
|
||||
4. Report any services that are down or unhealthy
|
||||
5. Suggest remediation steps for any issues
|
||||
23
.claude/commands/platform/logs.md
Normal file
23
.claude/commands/platform/logs.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: View platform service logs
|
||||
allowed-tools: Bash(docker:*), Bash(journalctl:*)
|
||||
argument-hint: [service]
|
||||
---
|
||||
|
||||
# View Platform Logs
|
||||
|
||||
View logs for platform services.
|
||||
|
||||
## Arguments
|
||||
- Service: $ARGUMENTS (gitea, youtrack, teamcity, nginx, postgres, agent-runner, or "all")
|
||||
|
||||
## Task
|
||||
|
||||
1. If service is "agent-runner":
|
||||
- Run: `journalctl -u cleargrow-agent-runner --no-pager -n 50`
|
||||
2. If service is "all":
|
||||
- Show last 20 lines from each Docker service
|
||||
3. Otherwise:
|
||||
- Run: `docker compose -f /opt/devplatform/docker-compose.yml logs --tail=50 $ARGUMENTS`
|
||||
4. Highlight any errors or warnings
|
||||
5. Suggest solutions for any issues found
|
||||
26
.claude/commands/platform/restart.md
Normal file
26
.claude/commands/platform/restart.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: Restart a platform service
|
||||
allowed-tools: Bash(docker:*), Bash(systemctl:*)
|
||||
argument-hint: [service]
|
||||
---
|
||||
|
||||
# Restart Platform Service
|
||||
|
||||
Restart a specific platform service.
|
||||
|
||||
## Arguments
|
||||
- Service: $ARGUMENTS (gitea, youtrack, teamcity, nginx, postgres, agent-runner, or "all")
|
||||
|
||||
## Current Status
|
||||
!`cd /opt/devplatform && docker compose ps --format "table {{.Name}}\t{{.Status}}" 2>/dev/null`
|
||||
|
||||
## Task
|
||||
|
||||
1. If service is "agent-runner":
|
||||
- Run: `sudo systemctl restart cleargrow-agent-runner`
|
||||
2. If service is "all":
|
||||
- Run: `docker compose -f /opt/devplatform/docker-compose.yml restart`
|
||||
3. Otherwise:
|
||||
- Run: `docker compose -f /opt/devplatform/docker-compose.yml restart $ARGUMENTS`
|
||||
4. Wait for service to come back up
|
||||
5. Verify health after restart
|
||||
17
.claude/settings.json
Normal file
17
.claude/settings.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash",
|
||||
"Edit",
|
||||
"Write",
|
||||
"WebFetch",
|
||||
"WebSearch",
|
||||
"NotebookEdit",
|
||||
"mcp__*"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": [],
|
||||
"defaultMode": "default"
|
||||
},
|
||||
"alwaysThinkingEnabled": true
|
||||
}
|
||||
368
.claude/skills/devplatform/SKILL.md
Normal file
368
.claude/skills/devplatform/SKILL.md
Normal file
@@ -0,0 +1,368 @@
|
||||
---
|
||||
name: devplatform
|
||||
description: Self-hosted development platform management skill. Use when working with Docker, Gitea, YouTrack, TeamCity, or the Agent Runner. Covers service management, CI/CD configuration, issue tracking, and troubleshooting.
|
||||
---
|
||||
|
||||
# DevPlatform Management Skill
|
||||
|
||||
## Platform Overview
|
||||
|
||||
| Service | URL | Port | Purpose |
|
||||
|---------|-----|------|---------|
|
||||
| Gitea | git.cleargrow.io | 3000 | Git hosting |
|
||||
| YouTrack | track.cleargrow.io | 8080 | Issue tracking |
|
||||
| TeamCity | ci.cleargrow.io | 8111 | CI/CD |
|
||||
| PostgreSQL | (internal) | 5432 | Database |
|
||||
| Nginx | - | 80/443 | Reverse proxy |
|
||||
|
||||
**Base directory**: `/opt/devplatform`
|
||||
|
||||
## Service Management
|
||||
|
||||
### Docker Compose Commands
|
||||
```bash
|
||||
cd /opt/devplatform
|
||||
|
||||
# Start all services
|
||||
docker compose up -d
|
||||
|
||||
# Stop all services
|
||||
docker compose down
|
||||
|
||||
# Restart specific service
|
||||
docker compose restart gitea
|
||||
docker compose restart youtrack
|
||||
docker compose restart teamcity
|
||||
|
||||
# View logs
|
||||
docker compose logs -f # All services
|
||||
docker compose logs -f gitea # Specific service
|
||||
docker compose logs --tail=100 teamcity # Last 100 lines
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
|
||||
# Resource usage
|
||||
docker stats --no-stream
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
```bash
|
||||
# Run health check script
|
||||
/opt/devplatform/scripts/healthcheck.sh
|
||||
|
||||
# Manual endpoint checks
|
||||
curl -s https://git.yourdomain.com/api/v1/version
|
||||
curl -s https://track.yourdomain.com/api/config
|
||||
curl -s https://ci.yourdomain.com/app/rest/server
|
||||
```
|
||||
|
||||
## Gitea Administration
|
||||
|
||||
### Git Operations
|
||||
```bash
|
||||
# Clone via SSH
|
||||
git clone git@git.cleargrow.io:owner/repo.git
|
||||
|
||||
# Clone via HTTPS
|
||||
git clone https://git.cleargrow.io/owner/repo.git
|
||||
```
|
||||
|
||||
### API Usage
|
||||
```bash
|
||||
# Create access token in Gitea UI: Settings > Applications > Generate Token
|
||||
|
||||
# List repositories
|
||||
curl -H "Authorization: token YOUR_TOKEN" \
|
||||
https://git.cleargrow.io/api/v1/repos/search
|
||||
|
||||
# Create repository
|
||||
curl -X POST -H "Authorization: token YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name":"new-repo","private":true}' \
|
||||
https://git.cleargrow.io/api/v1/user/repos
|
||||
|
||||
# Create webhook
|
||||
curl -X POST -H "Authorization: token YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "gitea",
|
||||
"config": {"url": "https://track.cleargrow.io/api/vcs/webhook", "content_type": "json"},
|
||||
"events": ["push", "pull_request"],
|
||||
"active": true
|
||||
}' \
|
||||
https://git.cleargrow.io/api/v1/repos/owner/repo/hooks
|
||||
```
|
||||
|
||||
### User Management
|
||||
```bash
|
||||
# Create user via CLI
|
||||
docker compose exec gitea gitea admin user create \
|
||||
--username newuser \
|
||||
--password "SecurePassword123" \
|
||||
--email user@example.com
|
||||
|
||||
# List users
|
||||
docker compose exec gitea gitea admin user list
|
||||
```
|
||||
|
||||
## YouTrack Administration
|
||||
|
||||
### API Usage
|
||||
```bash
|
||||
# Create permanent token in YouTrack: Profile > Authentication > New Token
|
||||
|
||||
# Get issues
|
||||
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
"https://track.cleargrow.io/api/issues?query=project:CG"
|
||||
|
||||
# Create issue
|
||||
curl -X POST -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"project":{"id":"CG"},"summary":"Issue title","description":"Details"}' \
|
||||
https://track.cleargrow.io/api/issues
|
||||
|
||||
# Update issue state
|
||||
curl -X POST -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '[{"$type":"StateIssueCustomField","id":"State","value":{"name":"In Progress"}}]' \
|
||||
https://track.cleargrow.io/api/issues/CG-123/fields
|
||||
|
||||
# Add comment
|
||||
curl -X POST -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text":"Comment text"}' \
|
||||
https://track.cleargrow.io/api/issues/CG-123/comments
|
||||
```
|
||||
|
||||
### Issue States (ClearGrow workflow)
|
||||
```
|
||||
Backlog → Ready → In Progress → Verify → Document → Review → Done
|
||||
↓
|
||||
Triage (on failure)
|
||||
```
|
||||
|
||||
### Commit Message Integration
|
||||
```bash
|
||||
# Link commit to issue
|
||||
git commit -m "Fix sensor parsing CG-123"
|
||||
|
||||
# Link and transition state
|
||||
git commit -m "Fix sensor parsing CG-123 #fixed"
|
||||
git commit -m "Start work CG-123 #in-progress"
|
||||
```
|
||||
|
||||
## TeamCity Administration
|
||||
|
||||
### Build Configuration
|
||||
```bash
|
||||
# Trigger build via API
|
||||
curl -X POST -u "user:password" \
|
||||
-H "Content-Type: application/xml" \
|
||||
-d "<build><buildType id='BuildConfigId'/></build>" \
|
||||
https://ci.cleargrow.io/app/rest/buildQueue
|
||||
|
||||
# Get build status
|
||||
curl -u "user:password" \
|
||||
"https://ci.cleargrow.io/app/rest/builds/buildType:BuildConfigId/status"
|
||||
```
|
||||
|
||||
### Webhook Setup (Gitea → TeamCity)
|
||||
```
|
||||
URL: https://ci.cleargrow.io/app/rest/vcs-root-instances/commitHookNotification
|
||||
Method: POST
|
||||
Content-Type: application/json
|
||||
Events: Push
|
||||
```
|
||||
|
||||
### Build Agent
|
||||
```bash
|
||||
# Check agent status
|
||||
docker compose logs teamcity-agent --tail=50
|
||||
|
||||
# Agent is authorized in UI: Agents > Unauthorized > Authorize
|
||||
```
|
||||
|
||||
## Agent Runner
|
||||
|
||||
The Agent Runner automates YouTrack tasks using Claude Code.
|
||||
|
||||
### Service Management
|
||||
```bash
|
||||
# Status
|
||||
sudo systemctl status cleargrow-agent-runner
|
||||
|
||||
# Control
|
||||
sudo systemctl start cleargrow-agent-runner
|
||||
sudo systemctl stop cleargrow-agent-runner
|
||||
sudo systemctl restart cleargrow-agent-runner
|
||||
|
||||
# Logs
|
||||
sudo journalctl -u cleargrow-agent-runner -f
|
||||
sudo journalctl -u cleargrow-agent-runner --since "1 hour ago"
|
||||
```
|
||||
|
||||
### Configuration
|
||||
```yaml
|
||||
# /opt/agent_runner/config.yaml
|
||||
youtrack:
|
||||
base_url: https://track.cleargrow.io
|
||||
token: perm:YOUR_TOKEN
|
||||
|
||||
gitea:
|
||||
base_url: https://git.cleargrow.io
|
||||
token: YOUR_TOKEN
|
||||
|
||||
project:
|
||||
name: CG
|
||||
states:
|
||||
ready: Ready
|
||||
in_progress: In Progress
|
||||
verify: Verify
|
||||
document: Document
|
||||
triage: Triage
|
||||
|
||||
repos:
|
||||
controller:
|
||||
name: cleargrow/controller
|
||||
path: /opt/repos/controller
|
||||
probe:
|
||||
name: cleargrow/probe
|
||||
path: /opt/repos/probe
|
||||
docs:
|
||||
name: cleargrow/docs
|
||||
path: /opt/repos/docs
|
||||
```
|
||||
|
||||
### Manual Commands
|
||||
```bash
|
||||
cd /opt/agent_runner
|
||||
|
||||
# Test connections
|
||||
python runner.py --test-connection
|
||||
|
||||
# Check platform health
|
||||
python runner.py --health
|
||||
|
||||
# View queue status
|
||||
python runner.py --status
|
||||
|
||||
# Run single cycle
|
||||
python runner.py --once
|
||||
```
|
||||
|
||||
## Database Operations
|
||||
|
||||
### PostgreSQL
|
||||
```bash
|
||||
# Connect to database
|
||||
docker compose exec postgres psql -U devplatform
|
||||
|
||||
# List databases
|
||||
docker compose exec postgres psql -U devplatform -l
|
||||
|
||||
# Dump database
|
||||
docker compose exec postgres pg_dump -U devplatform gitea > gitea_backup.sql
|
||||
|
||||
# Restore database
|
||||
cat gitea_backup.sql | docker compose exec -T postgres psql -U devplatform gitea
|
||||
```
|
||||
|
||||
## Backup & Recovery
|
||||
|
||||
### Manual Backup
|
||||
```bash
|
||||
/opt/devplatform/scripts/backup.sh
|
||||
|
||||
# Backup location
|
||||
ls -la /opt/devplatform/backups/
|
||||
```
|
||||
|
||||
### Restore
|
||||
```bash
|
||||
cd /opt/devplatform
|
||||
|
||||
# Stop services
|
||||
docker compose down
|
||||
|
||||
# Restore PostgreSQL
|
||||
docker compose up -d postgres
|
||||
cat backups/postgres_*.sql | docker compose exec -T postgres psql -U devplatform
|
||||
|
||||
# Restore data directories
|
||||
tar -xzf backups/gitea_*.tar.gz -C /opt/devplatform
|
||||
tar -xzf backups/youtrack_*.tar.gz -C /opt/devplatform
|
||||
tar -xzf backups/teamcity_*.tar.gz -C /opt/devplatform
|
||||
|
||||
# Fix permissions
|
||||
sudo chown -R 1000:1000 gitea/
|
||||
sudo chown -R 13001:13001 youtrack/
|
||||
sudo chown -R 1000:1000 teamcity/
|
||||
|
||||
# Start services
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## SSL Certificates
|
||||
|
||||
```bash
|
||||
# Check certificate expiry
|
||||
docker compose exec nginx openssl x509 \
|
||||
-in /etc/letsencrypt/live/git.cleargrow.io/fullchain.pem \
|
||||
-text -noout | grep "Not After"
|
||||
|
||||
# Renew certificates
|
||||
docker compose run --rm certbot renew
|
||||
docker compose restart nginx
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service not starting
|
||||
```bash
|
||||
# Check logs
|
||||
docker compose logs [service] --tail=100
|
||||
|
||||
# Check config
|
||||
docker compose config
|
||||
|
||||
# Check resources
|
||||
docker stats --no-stream
|
||||
df -h
|
||||
```
|
||||
|
||||
### 502 Bad Gateway
|
||||
```bash
|
||||
# Check backend is running
|
||||
docker compose ps
|
||||
|
||||
# Test internal connectivity
|
||||
docker compose exec nginx curl http://gitea:3000/api/v1/version
|
||||
docker compose exec nginx curl http://youtrack:8080/api/config
|
||||
docker compose exec nginx curl http://teamcity:8111/app/rest/server
|
||||
|
||||
# External URLs
|
||||
curl -s https://git.cleargrow.io/api/v1/version
|
||||
curl -s https://track.cleargrow.io/api/config
|
||||
curl -s https://ci.cleargrow.io/app/rest/server
|
||||
```
|
||||
|
||||
### Database issues
|
||||
```bash
|
||||
# Check postgres
|
||||
docker compose exec postgres pg_isready -U devplatform
|
||||
|
||||
# Check connections
|
||||
docker compose exec postgres psql -U devplatform -c "SELECT count(*) FROM pg_stat_activity;"
|
||||
```
|
||||
|
||||
### Disk space
|
||||
```bash
|
||||
# Check usage
|
||||
df -h
|
||||
docker system df
|
||||
|
||||
# Clean up
|
||||
docker system prune -a
|
||||
docker volume prune
|
||||
```
|
||||
365
.claude/skills/documentation/SKILL.md
Normal file
365
.claude/skills/documentation/SKILL.md
Normal file
@@ -0,0 +1,365 @@
|
||||
---
|
||||
name: documentation
|
||||
description: Technical documentation skill for the ClearGrow system. Use when writing user guides, API documentation, architecture docs, or updating the docs repository. Follows Diátaxis framework and Markdown best practices.
|
||||
---
|
||||
|
||||
# Documentation Skill
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Repository
|
||||
- **Path**: `/opt/repos/docs`
|
||||
- **Format**: Markdown (CommonMark + GFM extensions)
|
||||
- **Build**: `./build-pdf.sh` for PDF output
|
||||
|
||||
### Structure (Diátaxis)
|
||||
```
|
||||
docs/
|
||||
├── guides/
|
||||
│ ├── user/ # Tutorials & how-to for end users
|
||||
│ └── developer/ # Tutorials & how-to for developers
|
||||
├── reference/
|
||||
│ ├── architecture/ # System design explanations
|
||||
│ ├── api/ # REST, CoAP, MQTT specs
|
||||
│ ├── firmware/ # Component specifications
|
||||
│ ├── hardware/ # Pinouts, schematics
|
||||
│ ├── ui/ # Screen inventory
|
||||
│ └── errors/ # Error codes
|
||||
└── project/
|
||||
├── tasks/ # Active TASK_*.md files
|
||||
├── decisions/ # Architecture Decision Records
|
||||
└── roadmap/ # Future features
|
||||
```
|
||||
|
||||
## Diátaxis Framework
|
||||
|
||||
### Tutorials (guides/)
|
||||
**Purpose**: Learning-oriented, help beginners succeed
|
||||
**Tone**: Encouraging, step-by-step
|
||||
**Structure**:
|
||||
```markdown
|
||||
# Getting Started with Your ClearGrow Controller
|
||||
|
||||
This guide walks you through setting up your controller for the first time.
|
||||
|
||||
## What You'll Need
|
||||
- ClearGrow Controller
|
||||
- WiFi network credentials
|
||||
- Power adapter
|
||||
|
||||
## Step 1: Power On
|
||||
Connect the power adapter...
|
||||
|
||||
## Step 2: Connect to WiFi
|
||||
When the setup screen appears...
|
||||
|
||||
## Next Steps
|
||||
Now that your controller is running, learn how to:
|
||||
- [Add your first probe](adding-probes.md)
|
||||
- [Configure alerts](configuring-alerts.md)
|
||||
```
|
||||
|
||||
### How-To Guides (guides/)
|
||||
**Purpose**: Task-oriented, solve specific problems
|
||||
**Tone**: Direct, practical
|
||||
**Structure**:
|
||||
```markdown
|
||||
# How to Add a New Sensor Probe
|
||||
|
||||
This guide shows how to pair a new probe with your controller.
|
||||
|
||||
## Prerequisites
|
||||
- Controller connected to WiFi
|
||||
- Probe powered on
|
||||
|
||||
## Steps
|
||||
|
||||
1. On the controller, tap **Settings** > **Probes** > **Add New**
|
||||
2. The screen shows a pairing code
|
||||
3. Enter the code on the probe...
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Probe not found?**
|
||||
- Ensure probe is within 10 meters
|
||||
- Check that probe LED is blinking blue
|
||||
```
|
||||
|
||||
### Reference (reference/)
|
||||
**Purpose**: Information-oriented, accurate details
|
||||
**Tone**: Precise, technical
|
||||
**Structure**:
|
||||
```markdown
|
||||
# REST API Reference
|
||||
|
||||
## GET /api/v1/sensors
|
||||
|
||||
Returns current sensor readings from all connected probes.
|
||||
|
||||
### Authentication
|
||||
Requires Bearer token in Authorization header.
|
||||
|
||||
### Parameters
|
||||
| Name | Type | Required | Description |
|
||||
|------|------|----------|-------------|
|
||||
| `probe_id` | string | No | Filter by probe ID |
|
||||
|
||||
### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"probes": [
|
||||
{
|
||||
"id": "01:02:03:04:05:06:07:08",
|
||||
"type": "climate",
|
||||
"readings": {
|
||||
"temperature": 23.5,
|
||||
"humidity": 65.2
|
||||
},
|
||||
"battery": 85,
|
||||
"last_seen": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Status Codes
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 200 | Success |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Server error |
|
||||
```
|
||||
|
||||
### Explanation (reference/architecture/)
|
||||
**Purpose**: Understanding-oriented, provide context
|
||||
**Tone**: Conversational, educational
|
||||
**Structure**:
|
||||
```markdown
|
||||
# How Thread Networking Works
|
||||
|
||||
## Overview
|
||||
Thread is a low-power mesh networking protocol...
|
||||
|
||||
## Why Thread?
|
||||
Unlike WiFi, Thread provides:
|
||||
- Mesh networking for extended range
|
||||
- Low power consumption for battery devices
|
||||
- Self-healing network topology
|
||||
|
||||
## Architecture
|
||||
```
|
||||
|
||||
## Markdown Style Guide
|
||||
|
||||
### Headings
|
||||
```markdown
|
||||
# Document Title (H1 - one per doc)
|
||||
## Major Section (H2)
|
||||
### Subsection (H3)
|
||||
#### Minor section (H4 - use sparingly)
|
||||
```
|
||||
|
||||
### Code blocks
|
||||
````markdown
|
||||
Inline: Use `backticks` for code.
|
||||
|
||||
Blocks with language:
|
||||
```c
|
||||
esp_err_t result = sensor_read(&value);
|
||||
```
|
||||
|
||||
Shell commands:
|
||||
```bash
|
||||
idf.py build
|
||||
```
|
||||
````
|
||||
|
||||
### Tables
|
||||
```markdown
|
||||
| Header 1 | Header 2 | Header 3 |
|
||||
|----------|----------|----------|
|
||||
| Cell 1 | Cell 2 | Cell 3 |
|
||||
| Cell 4 | Cell 5 | Cell 6 |
|
||||
```
|
||||
|
||||
### Callouts/Admonitions
|
||||
```markdown
|
||||
> **Note**: Important information.
|
||||
|
||||
> **Warning**: Potential problems.
|
||||
|
||||
> **Tip**: Helpful suggestions.
|
||||
```
|
||||
|
||||
### Links
|
||||
```markdown
|
||||
[Link text](relative/path.md)
|
||||
[External](https://example.com)
|
||||
[Section](#section-heading)
|
||||
```
|
||||
|
||||
### Images
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
## API Documentation Template
|
||||
|
||||
```markdown
|
||||
# Endpoint Name
|
||||
|
||||
Brief description of what this endpoint does.
|
||||
|
||||
## Request
|
||||
|
||||
`METHOD /path/to/endpoint`
|
||||
|
||||
### Headers
|
||||
| Header | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| Authorization | Yes | Bearer token |
|
||||
|
||||
### Parameters
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| param | string | Yes | - | Description |
|
||||
|
||||
### Request Body
|
||||
```json
|
||||
{
|
||||
"field": "value"
|
||||
}
|
||||
```
|
||||
|
||||
## Response
|
||||
|
||||
### Success (200)
|
||||
```json
|
||||
{
|
||||
"result": "value"
|
||||
}
|
||||
```
|
||||
|
||||
### Errors
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| 400 | Bad Request | Invalid parameters |
|
||||
| 401 | Unauthorized | Missing or invalid token |
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
curl -X POST https://controller.local/api/v1/endpoint \
|
||||
-H "Authorization: Bearer TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"field": "value"}'
|
||||
```
|
||||
```
|
||||
|
||||
## Error Code Documentation Template
|
||||
|
||||
```markdown
|
||||
# ERROR_CODE: Brief Description
|
||||
|
||||
**Severity**: Error | Warning | Info
|
||||
**Component**: component_name
|
||||
**Introduced**: v1.0.0
|
||||
|
||||
## Description
|
||||
Full description of what this error means.
|
||||
|
||||
## Possible Causes
|
||||
1. First possible cause
|
||||
2. Second possible cause
|
||||
|
||||
## Resolution
|
||||
1. Step to resolve
|
||||
2. Another step
|
||||
|
||||
## Related
|
||||
- [Related Error](ERROR_002.md)
|
||||
- [Troubleshooting Guide](../guides/troubleshooting.md)
|
||||
```
|
||||
|
||||
## Architecture Decision Record (ADR) Template
|
||||
|
||||
```markdown
|
||||
# ADR-XXX: Decision Title
|
||||
|
||||
**Status**: Proposed | Accepted | Deprecated | Superseded
|
||||
**Date**: YYYY-MM-DD
|
||||
|
||||
## Context
|
||||
What is the issue we're addressing?
|
||||
|
||||
## Decision
|
||||
What have we decided to do?
|
||||
|
||||
## Consequences
|
||||
What are the positive and negative results?
|
||||
|
||||
### Positive
|
||||
- Benefit 1
|
||||
- Benefit 2
|
||||
|
||||
### Negative
|
||||
- Trade-off 1
|
||||
- Trade-off 2
|
||||
|
||||
## Alternatives Considered
|
||||
What other options were evaluated?
|
||||
|
||||
### Option A
|
||||
Description and why rejected.
|
||||
|
||||
### Option B
|
||||
Description and why rejected.
|
||||
```
|
||||
|
||||
## Task Document Template
|
||||
|
||||
```markdown
|
||||
# TASK_XXX: Task Title
|
||||
|
||||
**Status**: Draft | Ready | In Progress | Complete
|
||||
**Priority**: High | Medium | Low
|
||||
**Assignee**: Name or "Agent"
|
||||
|
||||
## Summary
|
||||
One paragraph describing the task.
|
||||
|
||||
## Background
|
||||
Context and motivation.
|
||||
|
||||
## Requirements
|
||||
- [ ] Requirement 1
|
||||
- [ ] Requirement 2
|
||||
- [ ] Requirement 3
|
||||
|
||||
## Implementation Notes
|
||||
Technical details and approach.
|
||||
|
||||
## Testing
|
||||
How to verify the implementation.
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Criterion 1
|
||||
- [ ] Criterion 2
|
||||
|
||||
## Related
|
||||
- Issue: CG-XXX
|
||||
- ADR: ADR-XXX
|
||||
- Related task: TASK_YYY
|
||||
```
|
||||
|
||||
## Writing Tips
|
||||
|
||||
1. **Start with the user's goal** - What do they want to accomplish?
|
||||
2. **Use active voice** - "Click the button" not "The button should be clicked"
|
||||
3. **Be specific** - "Wait 30 seconds" not "Wait a moment"
|
||||
4. **Include examples** - Show, don't just tell
|
||||
5. **Test your instructions** - Follow them yourself
|
||||
6. **Link generously** - Connect related content
|
||||
7. **Keep sentences short** - One idea per sentence
|
||||
8. **Use lists** - Easier to scan than paragraphs
|
||||
391
.claude/skills/esp-idf/SKILL.md
Normal file
391
.claude/skills/esp-idf/SKILL.md
Normal file
@@ -0,0 +1,391 @@
|
||||
---
|
||||
name: esp-idf
|
||||
description: ESP-IDF development for ESP32-S3 controller firmware. Use when working with the controller repository, building ESP-IDF projects, writing ESP32 components, or debugging ESP-IDF issues. Covers FreeRTOS, LVGL, Thread, WiFi, NVS, and peripherals.
|
||||
---
|
||||
|
||||
# ESP-IDF Development Skill
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Build Commands
|
||||
```bash
|
||||
cd /opt/repos/controller
|
||||
source ~/esp/esp-idf/export.sh # Required before build
|
||||
|
||||
idf.py build # Build firmware
|
||||
idf.py -p /dev/ttyUSB0 flash # Flash to device
|
||||
idf.py -p /dev/ttyUSB0 monitor # Serial monitor
|
||||
idf.py -p /dev/ttyUSB0 flash monitor # Flash and monitor
|
||||
idf.py menuconfig # Configuration menu
|
||||
idf.py clean # Clean build
|
||||
idf.py size # Memory usage report
|
||||
idf.py size-components # Per-component memory
|
||||
```
|
||||
|
||||
### Creating a Component
|
||||
```bash
|
||||
# Create component structure
|
||||
mkdir -p components/my_component
|
||||
touch components/my_component/CMakeLists.txt
|
||||
touch components/my_component/my_component.c
|
||||
touch components/my_component/include/my_component.h
|
||||
```
|
||||
|
||||
**CMakeLists.txt**:
|
||||
```cmake
|
||||
idf_component_register(
|
||||
SRCS "my_component.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES driver esp_event
|
||||
)
|
||||
```
|
||||
|
||||
**Header file**:
|
||||
```c
|
||||
#pragma once
|
||||
#include "esp_err.h"
|
||||
|
||||
esp_err_t my_component_init(void);
|
||||
```
|
||||
|
||||
**Source file**:
|
||||
```c
|
||||
#include "my_component.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "my_component";
|
||||
|
||||
esp_err_t my_component_init(void) {
|
||||
ESP_LOGI(TAG, "Initializing");
|
||||
return ESP_OK;
|
||||
}
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
```c
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "my_tag";
|
||||
|
||||
ESP_LOGE(TAG, "Error: %s", esp_err_to_name(err));
|
||||
ESP_LOGW(TAG, "Warning: value=%d", val);
|
||||
ESP_LOGI(TAG, "Info message");
|
||||
ESP_LOGD(TAG, "Debug: ptr=%p", ptr);
|
||||
ESP_LOGV(TAG, "Verbose output");
|
||||
|
||||
// Set log level at runtime
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("my_tag", ESP_LOG_DEBUG);
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
```c
|
||||
// Check and abort on error
|
||||
ESP_ERROR_CHECK(some_function());
|
||||
|
||||
// Check with custom handling
|
||||
esp_err_t ret = some_function();
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Common error codes
|
||||
ESP_OK // Success
|
||||
ESP_FAIL // Generic failure
|
||||
ESP_ERR_NO_MEM // Out of memory
|
||||
ESP_ERR_INVALID_ARG // Invalid argument
|
||||
ESP_ERR_TIMEOUT // Timeout
|
||||
```
|
||||
|
||||
## FreeRTOS Tasks
|
||||
|
||||
```c
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static void my_task(void *arg) {
|
||||
while (1) {
|
||||
// Task work
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
// Create task pinned to core 1
|
||||
xTaskCreatePinnedToCore(
|
||||
my_task, // Function
|
||||
"my_task", // Name
|
||||
4096, // Stack size
|
||||
NULL, // Parameter
|
||||
5, // Priority (0-24)
|
||||
&task_handle, // Handle (optional)
|
||||
1 // Core (0 or 1)
|
||||
);
|
||||
|
||||
// Delete task
|
||||
vTaskDelete(task_handle); // Or NULL for self
|
||||
```
|
||||
|
||||
## Synchronization
|
||||
|
||||
```c
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
// Mutex
|
||||
SemaphoreHandle_t mutex = xSemaphoreCreateMutex();
|
||||
if (xSemaphoreTake(mutex, pdMS_TO_TICKS(1000)) == pdTRUE) {
|
||||
// Critical section
|
||||
xSemaphoreGive(mutex);
|
||||
}
|
||||
|
||||
// Binary semaphore (signaling)
|
||||
SemaphoreHandle_t sem = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(sem); // Signal
|
||||
xSemaphoreTake(sem, portMAX_DELAY); // Wait
|
||||
|
||||
// Event groups
|
||||
EventGroupHandle_t events = xEventGroupCreate();
|
||||
xEventGroupSetBits(events, BIT0);
|
||||
xEventGroupWaitBits(events, BIT0, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
```
|
||||
|
||||
## NVS (Non-Volatile Storage)
|
||||
|
||||
```c
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
|
||||
// Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
|
||||
// Read/write values
|
||||
nvs_handle_t handle;
|
||||
nvs_open("storage", NVS_READWRITE, &handle);
|
||||
|
||||
int32_t value;
|
||||
nvs_get_i32(handle, "my_key", &value);
|
||||
nvs_set_i32(handle, "my_key", 42);
|
||||
nvs_commit(handle);
|
||||
nvs_close(handle);
|
||||
|
||||
// Strings
|
||||
char buf[64];
|
||||
size_t len = sizeof(buf);
|
||||
nvs_get_str(handle, "name", buf, &len);
|
||||
nvs_set_str(handle, "name", "value");
|
||||
```
|
||||
|
||||
## GPIO
|
||||
|
||||
```c
|
||||
#include "driver/gpio.h"
|
||||
|
||||
// Output
|
||||
gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(GPIO_NUM_2, 1);
|
||||
|
||||
// Input with pull-up
|
||||
gpio_config_t cfg = {
|
||||
.pin_bit_mask = (1ULL << GPIO_NUM_4),
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.intr_type = GPIO_INTR_NEGEDGE,
|
||||
};
|
||||
gpio_config(&cfg);
|
||||
|
||||
// ISR handler
|
||||
gpio_install_isr_service(0);
|
||||
gpio_isr_handler_add(GPIO_NUM_4, gpio_isr_handler, NULL);
|
||||
```
|
||||
|
||||
## I2C
|
||||
|
||||
```c
|
||||
#include "driver/i2c.h"
|
||||
|
||||
// Master init
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = GPIO_NUM_21,
|
||||
.scl_io_num = GPIO_NUM_22,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = 400000,
|
||||
};
|
||||
i2c_param_config(I2C_NUM_0, &conf);
|
||||
i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
|
||||
|
||||
// Read/write
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, reg, true);
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, true);
|
||||
i2c_master_read_byte(cmd, &data, I2C_MASTER_NACK);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(100));
|
||||
i2c_cmd_link_delete(cmd);
|
||||
```
|
||||
|
||||
## SPI
|
||||
|
||||
```c
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
spi_bus_config_t bus = {
|
||||
.mosi_io_num = GPIO_NUM_23,
|
||||
.miso_io_num = GPIO_NUM_19,
|
||||
.sclk_io_num = GPIO_NUM_18,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
};
|
||||
spi_bus_initialize(SPI2_HOST, &bus, SPI_DMA_CH_AUTO);
|
||||
|
||||
spi_device_interface_config_t dev = {
|
||||
.clock_speed_hz = 10000000,
|
||||
.mode = 0,
|
||||
.spics_io_num = GPIO_NUM_5,
|
||||
.queue_size = 7,
|
||||
};
|
||||
spi_device_handle_t handle;
|
||||
spi_bus_add_device(SPI2_HOST, &dev, &handle);
|
||||
|
||||
// Transaction
|
||||
spi_transaction_t t = {
|
||||
.length = 8,
|
||||
.tx_buffer = &tx_data,
|
||||
.rx_buffer = &rx_data,
|
||||
};
|
||||
spi_device_transmit(handle, &t);
|
||||
```
|
||||
|
||||
## Memory Allocation
|
||||
|
||||
```c
|
||||
// Internal RAM
|
||||
void *ptr = malloc(size);
|
||||
|
||||
// PSRAM (external)
|
||||
#include "esp_heap_caps.h"
|
||||
void *ptr = heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
||||
|
||||
// DMA-capable
|
||||
void *ptr = heap_caps_malloc(size, MALLOC_CAP_DMA);
|
||||
|
||||
// Check free memory
|
||||
size_t free_heap = esp_get_free_heap_size();
|
||||
size_t free_psram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
```
|
||||
|
||||
## WiFi
|
||||
|
||||
```c
|
||||
#include "esp_wifi.h"
|
||||
|
||||
// Initialize
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
esp_wifi_init(&cfg);
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
|
||||
// Connect
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = "MyNetwork",
|
||||
.password = "password",
|
||||
},
|
||||
};
|
||||
esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
|
||||
esp_wifi_start();
|
||||
esp_wifi_connect();
|
||||
```
|
||||
|
||||
## HTTP Server
|
||||
|
||||
```c
|
||||
#include "esp_http_server.h"
|
||||
|
||||
esp_err_t handler(httpd_req_t *req) {
|
||||
const char *resp = "{\"status\":\"ok\"}";
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
httpd_resp_send(req, resp, strlen(resp));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
httpd_handle_t server;
|
||||
httpd_start(&server, &config);
|
||||
|
||||
httpd_uri_t uri = {
|
||||
.uri = "/api/status",
|
||||
.method = HTTP_GET,
|
||||
.handler = handler,
|
||||
};
|
||||
httpd_register_uri_handler(server, &uri);
|
||||
```
|
||||
|
||||
## LVGL (UI)
|
||||
|
||||
```c
|
||||
#include "lvgl.h"
|
||||
|
||||
// Create button
|
||||
lv_obj_t *btn = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_size(btn, 120, 50);
|
||||
lv_obj_center(btn);
|
||||
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
// Add label
|
||||
lv_obj_t *label = lv_label_create(btn);
|
||||
lv_label_set_text(label, "Click me");
|
||||
lv_obj_center(label);
|
||||
|
||||
// Event callback
|
||||
static void btn_event_cb(lv_event_t *e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED) {
|
||||
ESP_LOGI(TAG, "Button clicked");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
```bash
|
||||
# Serial monitor with timestamps
|
||||
idf.py monitor
|
||||
|
||||
# Core dump analysis
|
||||
idf.py coredump-info
|
||||
idf.py coredump-debug
|
||||
|
||||
# GDB debugging
|
||||
idf.py gdb
|
||||
idf.py openocd
|
||||
```
|
||||
|
||||
## Partition Table
|
||||
|
||||
```csv
|
||||
# Name, Type, SubType, Offset, Size
|
||||
nvs, data, nvs, 0x9000, 0x6000
|
||||
phy_init, data, phy, 0xf000, 0x1000
|
||||
factory, app, factory, 0x10000, 1M
|
||||
storage, data, spiffs, , 0x100000
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Guru Meditation Error | Stack overflow - increase task stack |
|
||||
| Brownout detected | Power supply issue |
|
||||
| Flash read error | Check flash mode (DIO/QIO) |
|
||||
| WiFi not connecting | Check credentials, signal strength |
|
||||
| I2C timeout | Check wiring, pull-ups, address |
|
||||
398
.claude/skills/zephyr/SKILL.md
Normal file
398
.claude/skills/zephyr/SKILL.md
Normal file
@@ -0,0 +1,398 @@
|
||||
---
|
||||
name: zephyr
|
||||
description: Zephyr RTOS development for nRF52840 probe firmware. Use when working with the probe repository, building Zephyr projects, writing sensor drivers, or debugging nRF52 issues. Covers devicetree, Kconfig, Thread networking, CoAP, and power management.
|
||||
---
|
||||
|
||||
# Zephyr RTOS Development Skill
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Build Commands
|
||||
```bash
|
||||
cd /opt/repos/probe
|
||||
|
||||
west build -b nrf52840dk_nrf52840 # Build for DK
|
||||
west build -b nrf52840dk_nrf52840 --pristine # Clean build
|
||||
west flash # Flash via J-Link
|
||||
west debug # GDB debug session
|
||||
west build -t menuconfig # Kconfig menu
|
||||
|
||||
# Build for native simulation
|
||||
west build -b native_posix
|
||||
./build/zephyr/zephyr.exe
|
||||
|
||||
# Build with specific options
|
||||
west build -- -DCONFIG_LOG_DEFAULT_LEVEL=4
|
||||
```
|
||||
|
||||
### Project Configuration (prj.conf)
|
||||
```kconfig
|
||||
# Logging
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_DEFAULT_LEVEL=3
|
||||
|
||||
# Thread networking
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_L2_OPENTHREAD=y
|
||||
CONFIG_OPENTHREAD_MTD=y
|
||||
CONFIG_OPENTHREAD_JOINER=y
|
||||
|
||||
# Power management
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_DEVICE=y
|
||||
|
||||
# Sensors
|
||||
CONFIG_SENSOR=y
|
||||
CONFIG_I2C=y
|
||||
```
|
||||
|
||||
## Devicetree
|
||||
|
||||
### Overlay file (boards/nrf52840dk_nrf52840.overlay)
|
||||
```dts
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
|
||||
sht4x: sht4x@44 {
|
||||
compatible = "sensirion,sht4x";
|
||||
reg = <0x44>;
|
||||
repeatability = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
status = "okay";
|
||||
cs-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
|
||||
|
||||
my_sensor: my_sensor@0 {
|
||||
compatible = "vendor,sensor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Accessing devices in C
|
||||
```c
|
||||
// Get device by label
|
||||
#define SHT4X_NODE DT_NODELABEL(sht4x)
|
||||
static const struct device *sht4x = DEVICE_DT_GET(SHT4X_NODE);
|
||||
|
||||
// Check device ready
|
||||
if (!device_is_ready(sht4x)) {
|
||||
LOG_ERR("SHT4x not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Get GPIO spec from devicetree
|
||||
#define LED0_NODE DT_ALIAS(led0)
|
||||
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
```c
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(my_module, CONFIG_MY_MODULE_LOG_LEVEL);
|
||||
|
||||
LOG_ERR("Error: %d", ret);
|
||||
LOG_WRN("Warning message");
|
||||
LOG_INF("Info: device %s", dev->name);
|
||||
LOG_DBG("Debug: value=%d", val);
|
||||
|
||||
// Hexdump
|
||||
LOG_HEXDUMP_INF(buffer, len, "Data:");
|
||||
```
|
||||
|
||||
## Threads and Work Queues
|
||||
|
||||
### Threads
|
||||
```c
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#define STACK_SIZE 1024
|
||||
#define PRIORITY 5
|
||||
|
||||
K_THREAD_STACK_DEFINE(my_stack, STACK_SIZE);
|
||||
struct k_thread my_thread;
|
||||
|
||||
void my_thread_entry(void *p1, void *p2, void *p3) {
|
||||
while (1) {
|
||||
// Do work
|
||||
k_sleep(K_MSEC(100));
|
||||
}
|
||||
}
|
||||
|
||||
// Create thread
|
||||
k_thread_create(&my_thread, my_stack, STACK_SIZE,
|
||||
my_thread_entry, NULL, NULL, NULL,
|
||||
PRIORITY, 0, K_NO_WAIT);
|
||||
```
|
||||
|
||||
### Work queues
|
||||
```c
|
||||
// Define work item
|
||||
static void my_work_handler(struct k_work *work) {
|
||||
// Do work
|
||||
}
|
||||
K_WORK_DEFINE(my_work, my_work_handler);
|
||||
|
||||
// Submit work
|
||||
k_work_submit(&my_work);
|
||||
|
||||
// Delayed work
|
||||
K_WORK_DELAYABLE_DEFINE(delayed_work, delayed_handler);
|
||||
k_work_schedule(&delayed_work, K_MSEC(1000));
|
||||
```
|
||||
|
||||
### Timers
|
||||
```c
|
||||
static void timer_handler(struct k_timer *timer) {
|
||||
// Timer expired - runs in ISR context
|
||||
k_work_submit(&my_work); // Defer to thread
|
||||
}
|
||||
|
||||
K_TIMER_DEFINE(my_timer, timer_handler, NULL);
|
||||
k_timer_start(&my_timer, K_MSEC(100), K_MSEC(100));
|
||||
```
|
||||
|
||||
## Synchronization
|
||||
|
||||
```c
|
||||
// Mutex
|
||||
K_MUTEX_DEFINE(my_mutex);
|
||||
k_mutex_lock(&my_mutex, K_FOREVER);
|
||||
// Critical section
|
||||
k_mutex_unlock(&my_mutex);
|
||||
|
||||
// Semaphore
|
||||
K_SEM_DEFINE(my_sem, 0, 1);
|
||||
k_sem_give(&my_sem);
|
||||
k_sem_take(&my_sem, K_FOREVER);
|
||||
|
||||
// Message queue
|
||||
K_MSGQ_DEFINE(my_msgq, sizeof(struct msg), 10, 4);
|
||||
k_msgq_put(&my_msgq, &msg, K_NO_WAIT);
|
||||
k_msgq_get(&my_msgq, &msg, K_FOREVER);
|
||||
```
|
||||
|
||||
## GPIO
|
||||
|
||||
```c
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
||||
// Get GPIO from devicetree
|
||||
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
|
||||
static const struct gpio_dt_spec btn = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
|
||||
|
||||
// Configure
|
||||
gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
|
||||
gpio_pin_configure_dt(&btn, GPIO_INPUT);
|
||||
|
||||
// Set/get
|
||||
gpio_pin_set_dt(&led, 1);
|
||||
int val = gpio_pin_get_dt(&btn);
|
||||
|
||||
// Interrupt
|
||||
static struct gpio_callback btn_cb;
|
||||
|
||||
void btn_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
|
||||
LOG_INF("Button pressed");
|
||||
}
|
||||
|
||||
gpio_pin_interrupt_configure_dt(&btn, GPIO_INT_EDGE_TO_ACTIVE);
|
||||
gpio_init_callback(&btn_cb, btn_handler, BIT(btn.pin));
|
||||
gpio_add_callback(btn.port, &btn_cb);
|
||||
```
|
||||
|
||||
## I2C
|
||||
|
||||
```c
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
|
||||
static const struct device *i2c = DEVICE_DT_GET(DT_NODELABEL(i2c0));
|
||||
|
||||
// Write then read
|
||||
uint8_t reg = 0x00;
|
||||
uint8_t data[2];
|
||||
i2c_write_read(i2c, addr, ®, 1, data, sizeof(data));
|
||||
|
||||
// Burst write
|
||||
uint8_t buf[] = {reg, val1, val2};
|
||||
i2c_write(i2c, buf, sizeof(buf), addr);
|
||||
|
||||
// Register access helpers
|
||||
i2c_reg_read_byte(i2c, addr, reg, &val);
|
||||
i2c_reg_write_byte(i2c, addr, reg, val);
|
||||
```
|
||||
|
||||
## SPI
|
||||
|
||||
```c
|
||||
#include <zephyr/drivers/spi.h>
|
||||
|
||||
static const struct device *spi = DEVICE_DT_GET(DT_NODELABEL(spi1));
|
||||
static struct spi_cs_control cs = SPI_CS_CONTROL_INIT(DT_NODELABEL(my_sensor), 0);
|
||||
|
||||
static const struct spi_config spi_cfg = {
|
||||
.frequency = 1000000,
|
||||
.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8),
|
||||
.cs = &cs,
|
||||
};
|
||||
|
||||
// Transaction
|
||||
uint8_t tx_buf[] = {0x80, 0x00};
|
||||
uint8_t rx_buf[2];
|
||||
struct spi_buf tx = {.buf = tx_buf, .len = sizeof(tx_buf)};
|
||||
struct spi_buf rx = {.buf = rx_buf, .len = sizeof(rx_buf)};
|
||||
struct spi_buf_set tx_set = {.buffers = &tx, .count = 1};
|
||||
struct spi_buf_set rx_set = {.buffers = &rx, .count = 1};
|
||||
|
||||
spi_transceive(spi, &spi_cfg, &tx_set, &rx_set);
|
||||
```
|
||||
|
||||
## Sensor API
|
||||
|
||||
```c
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
static const struct device *sensor = DEVICE_DT_GET(DT_NODELABEL(sht4x));
|
||||
|
||||
// Fetch and get values
|
||||
sensor_sample_fetch(sensor);
|
||||
|
||||
struct sensor_value temp, hum;
|
||||
sensor_channel_get(sensor, SENSOR_CHAN_AMBIENT_TEMP, &temp);
|
||||
sensor_channel_get(sensor, SENSOR_CHAN_HUMIDITY, &hum);
|
||||
|
||||
// Convert to double
|
||||
double temp_c = sensor_value_to_double(&temp);
|
||||
|
||||
// Trigger
|
||||
sensor_trigger_set(sensor, &trig, sensor_trigger_handler);
|
||||
```
|
||||
|
||||
## Power Management
|
||||
|
||||
```c
|
||||
#include <zephyr/pm/pm.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
|
||||
// Force sleep state
|
||||
pm_state_force(0U, &(struct pm_state_info){PM_STATE_SUSPEND_TO_IDLE, 0, 0});
|
||||
|
||||
// Device power management
|
||||
pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND);
|
||||
pm_device_action_run(dev, PM_DEVICE_ACTION_RESUME);
|
||||
|
||||
// Check state
|
||||
enum pm_device_state state;
|
||||
pm_device_state_get(dev, &state);
|
||||
```
|
||||
|
||||
### Low power configuration (prj.conf)
|
||||
```kconfig
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_DEVICE=y
|
||||
CONFIG_PM_DEVICE_RUNTIME=y
|
||||
|
||||
# For Thread sleepy end device
|
||||
CONFIG_OPENTHREAD_MTD_SED=y
|
||||
CONFIG_OPENTHREAD_POLL_PERIOD=1000
|
||||
```
|
||||
|
||||
## OpenThread / CoAP
|
||||
|
||||
```c
|
||||
#include <zephyr/net/openthread.h>
|
||||
#include <zephyr/net/coap.h>
|
||||
|
||||
// Get OpenThread instance
|
||||
struct openthread_context *ctx = openthread_get_default_context();
|
||||
otInstance *ot = ctx->instance;
|
||||
|
||||
// Check state
|
||||
otDeviceRole role = otThreadGetDeviceRole(ot);
|
||||
|
||||
// CoAP request
|
||||
struct coap_packet request;
|
||||
uint8_t buf[128];
|
||||
|
||||
coap_packet_init(&request, buf, sizeof(buf),
|
||||
COAP_VERSION_1, COAP_TYPE_CON,
|
||||
4, coap_next_token(),
|
||||
COAP_METHOD_POST, coap_next_id());
|
||||
coap_packet_append_option(&request, COAP_OPTION_URI_PATH, "sensor", 6);
|
||||
coap_packet_append_payload_marker(&request);
|
||||
coap_packet_append_payload(&request, data, data_len);
|
||||
```
|
||||
|
||||
## Settings (NVS)
|
||||
|
||||
```c
|
||||
#include <zephyr/settings/settings.h>
|
||||
|
||||
// Load settings
|
||||
settings_subsys_init();
|
||||
settings_load();
|
||||
|
||||
// Register handler
|
||||
static int my_settings_set(const char *name, size_t len,
|
||||
settings_read_cb read_cb, void *cb_arg) {
|
||||
if (!strcmp(name, "value")) {
|
||||
read_cb(cb_arg, &my_value, sizeof(my_value));
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
SETTINGS_STATIC_HANDLER_DEFINE(my_settings, "my", NULL, my_settings_set, NULL, NULL);
|
||||
|
||||
// Save
|
||||
settings_save_one("my/value", &my_value, sizeof(my_value));
|
||||
```
|
||||
|
||||
## Testing (Ztest)
|
||||
|
||||
```c
|
||||
#include <zephyr/ztest.h>
|
||||
|
||||
ZTEST_SUITE(my_tests, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
ZTEST(my_tests, test_something) {
|
||||
int ret = my_function();
|
||||
zassert_equal(ret, 0, "Expected 0, got %d", ret);
|
||||
}
|
||||
|
||||
ZTEST(my_tests, test_buffer) {
|
||||
uint8_t expected[] = {0x01, 0x02};
|
||||
uint8_t actual[2];
|
||||
my_fill_buffer(actual);
|
||||
zassert_mem_equal(expected, actual, sizeof(expected));
|
||||
}
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
```bash
|
||||
# GDB session
|
||||
west debug
|
||||
|
||||
# RTT logging (no UART needed)
|
||||
# In prj.conf:
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
CONFIG_LOG_BACKEND_RTT=y
|
||||
|
||||
# View RTT output
|
||||
JLinkRTTViewer
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Device not ready | Check devicetree binding, init priority |
|
||||
| Stack overflow | Increase thread stack size |
|
||||
| Settings not persisted | Enable CONFIG_SETTINGS, flash partition |
|
||||
| Thread not joining | Check PSKd, channel, panid |
|
||||
| High power consumption | Check PM config, disable unused peripherals |
|
||||
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Editor files
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Environment files with secrets
|
||||
.env
|
||||
.env.local
|
||||
*.secret
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.log
|
||||
163
CLAUDE.md
Normal file
163
CLAUDE.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# ClearGrow Development Platform
|
||||
|
||||
## System Overview
|
||||
|
||||
Self-hosted development platform for the ClearGrow IoT agricultural monitoring system, consisting of:
|
||||
- **Gitea**: Git repository hosting at `git.cleargrow.io`
|
||||
- **YouTrack**: Issue tracking at `track.cleargrow.io`
|
||||
- **TeamCity**: CI/CD at `ci.cleargrow.io`
|
||||
- **Agent Runner**: Automated Claude Code task processing
|
||||
|
||||
## Repositories
|
||||
|
||||
| Repository | Path | Technology | Purpose |
|
||||
|------------|------|------------|---------|
|
||||
| **controller** | `/opt/repos/controller` | ESP-IDF (C) | ESP32-S3 touchscreen controller with Thread Border Router |
|
||||
| **probe** | `/opt/repos/probe` | Zephyr (C) | nRF52840 wireless sensor probes |
|
||||
| **docs** | `/opt/repos/docs` | Markdown | Technical documentation |
|
||||
|
||||
## Quick Commands
|
||||
|
||||
```bash
|
||||
# Platform management
|
||||
docker compose -f /opt/devplatform/docker-compose.yml up -d # Start all services
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f # View logs
|
||||
/opt/devplatform/scripts/healthcheck.sh # Check health
|
||||
/opt/devplatform/scripts/backup.sh # Run backup
|
||||
|
||||
# Controller firmware (ESP-IDF)
|
||||
cd /opt/repos/controller
|
||||
source ~/esp/esp-idf/export.sh
|
||||
idf.py build
|
||||
idf.py -p /dev/ttyUSB0 flash monitor
|
||||
|
||||
# Probe firmware (Zephyr)
|
||||
cd /opt/repos/probe
|
||||
west build -b nrf52840dk_nrf52840
|
||||
west flash
|
||||
|
||||
# Agent runner
|
||||
sudo systemctl status cleargrow-agent-runner
|
||||
sudo journalctl -u cleargrow-agent-runner -f
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
### ESP-IDF (Controller)
|
||||
- Use ESP-IDF component architecture
|
||||
- Prefix component functions with component name (e.g., `wifi_manager_init()`)
|
||||
- Use ESP_LOG macros for logging
|
||||
- Store persistent data in NVS
|
||||
- Follow FreeRTOS task patterns
|
||||
|
||||
### Zephyr (Probe)
|
||||
- Use Zephyr devicetree for hardware abstraction
|
||||
- Use Kconfig for configuration options
|
||||
- Follow Zephyr coding style (4-space indent)
|
||||
- Use power management APIs for sleep modes
|
||||
|
||||
### Documentation
|
||||
- Follow Diátaxis framework (guides/reference/project)
|
||||
- Use templates from `_templates/`
|
||||
- Keep user docs separate from developer docs
|
||||
|
||||
## Project Architecture
|
||||
|
||||
### Controller Components
|
||||
Key components in `/opt/repos/controller/components/`:
|
||||
- `wifi_manager/` - WiFi connection and provisioning
|
||||
- `display/` - LVGL UI and touch handling
|
||||
- `thread_manager/` - Thread Border Router
|
||||
- `sensor_hub/` - Sensor data aggregation from probes
|
||||
- `network_api/` - REST API and MQTT publishing
|
||||
- `settings/` - NVS-backed configuration
|
||||
|
||||
### Probe Architecture
|
||||
Key files in `/opt/repos/probe/src/`:
|
||||
- `thread_node.c` - Thread networking and CoAP client
|
||||
- `sensor_manager.c` - Sensor polling and data aggregation
|
||||
- `power_manager.c` - Sleep modes and battery monitoring
|
||||
|
||||
### Protocol
|
||||
Probes communicate with controller via CoAP over Thread using TLV format.
|
||||
|
||||
## Testing
|
||||
|
||||
### Controller
|
||||
```bash
|
||||
# Unit tests (host-based)
|
||||
cd /opt/repos/controller
|
||||
idf.py --project-dir test build
|
||||
./test/build/test_app
|
||||
|
||||
# Integration test on device
|
||||
idf.py flash monitor
|
||||
```
|
||||
|
||||
### Probe
|
||||
```bash
|
||||
cd /opt/repos/probe
|
||||
west build -b native_posix -- -DCONFIG_TEST=y
|
||||
./build/zephyr/zephyr.exe
|
||||
```
|
||||
|
||||
## YouTrack Integration
|
||||
|
||||
Issue references in commit messages:
|
||||
- `CG-123` - Links commit to issue
|
||||
- `CG-123 #fixed` - Links and transitions to Fixed state
|
||||
- `CG-123 #in-progress` - Links and transitions to In Progress
|
||||
|
||||
## Agent Workflow States
|
||||
|
||||
Issues flow through these YouTrack states:
|
||||
1. **Backlog** - New issues
|
||||
2. **Ready** - Specs complete, ready for agent
|
||||
3. **In Progress** - Agent working
|
||||
4. **Verify** - Code review
|
||||
5. **Document** - Documentation updates
|
||||
6. **Review** - User final review
|
||||
7. **Done** - Closed
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a new sensor type to probe
|
||||
1. Add sensor driver to `probe/src/sensors/`
|
||||
2. Register in `sensor_manager.c`
|
||||
3. Add measurement type to TLV protocol
|
||||
4. Update controller's `sensor_hub` to parse new type
|
||||
5. Add UI display in controller's `display` component
|
||||
|
||||
### Adding a new REST endpoint to controller
|
||||
1. Define handler in `network_api/api_handlers.c`
|
||||
2. Register route in `network_api/network_api.c`
|
||||
3. Document in `docs/reference/api/`
|
||||
|
||||
### Creating a new UI screen
|
||||
1. Add screen file in `controller/components/display/screens/`
|
||||
2. Register in screen manager
|
||||
3. Document in `docs/reference/ui/`
|
||||
|
||||
## Debugging Tips
|
||||
|
||||
### Controller
|
||||
- Use `idf.py monitor` for serial console
|
||||
- Enable verbose logging: `esp_log_level_set("*", ESP_LOG_VERBOSE)`
|
||||
- Use JTAG for hardware debugging
|
||||
|
||||
### Probe
|
||||
- Use `west debug` for GDB debugging
|
||||
- Enable RTT logging for non-intrusive debugging
|
||||
- Check Thread state with `ot state` shell command
|
||||
|
||||
## Memory Constraints
|
||||
|
||||
### Controller (ESP32-S3)
|
||||
- Internal SRAM: ~320KB
|
||||
- PSRAM: 8MB (frame buffers, history, TFLite)
|
||||
- Flash: 16MB
|
||||
|
||||
### Probe (nRF52840)
|
||||
- RAM: 256KB
|
||||
- Flash: 1MB
|
||||
- Optimize for low power sleep modes
|
||||
202
QUICK_REFERENCE.md
Normal file
202
QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# ClearGrow Quick Reference
|
||||
|
||||
## Slash Commands
|
||||
|
||||
### Firmware Commands (`/firmware:*`)
|
||||
|
||||
| Command | Description | Usage |
|
||||
|---------|-------------|-------|
|
||||
| `/build-controller` | Build ESP32-S3 controller firmware | `/build-controller` |
|
||||
| `/build-probe` | Build nRF52840 probe firmware | `/build-probe [board]` |
|
||||
| `/flash-controller` | Flash controller to device | `/flash-controller [port]` |
|
||||
| `/flash-probe` | Flash probe via J-Link | `/flash-probe` |
|
||||
| `/test-controller` | Run controller unit tests | `/test-controller` |
|
||||
| `/test-probe` | Run probe unit tests | `/test-probe` |
|
||||
|
||||
### Git Commands (`/git:*`)
|
||||
|
||||
| Command | Description | Usage |
|
||||
|---------|-------------|-------|
|
||||
| `/status` | Show status of all repos | `/status` |
|
||||
| `/commit` | Create commit with issue link | `/commit CG-123 "Fix bug"` |
|
||||
| `/push` | Push to Gitea | `/push [branch]` |
|
||||
| `/pull` | Pull from Gitea | `/pull` |
|
||||
| `/branch` | Create feature branch | `/branch CG-123 feature-name` |
|
||||
| `/pr` | Create pull request | `/pr "PR title"` |
|
||||
|
||||
### Platform Commands (`/platform:*`)
|
||||
|
||||
| Command | Description | Usage |
|
||||
|---------|-------------|-------|
|
||||
| `/health` | Check all service health | `/health` |
|
||||
| `/logs` | View service logs | `/logs [service]` |
|
||||
| `/restart` | Restart a service | `/restart [service]` |
|
||||
| `/backup` | Run platform backup | `/backup` |
|
||||
| `/disk` | Check disk usage | `/disk` |
|
||||
|
||||
### Issue Commands (`/issues:*`)
|
||||
|
||||
| Command | Description | Usage |
|
||||
|---------|-------------|-------|
|
||||
| `/list` | List issues by state | `/list [state]` |
|
||||
| `/view` | View issue details | `/view CG-123` |
|
||||
| `/comment` | Add comment to issue | `/comment CG-123 "text"` |
|
||||
| `/transition` | Change issue state | `/transition CG-123 Done` |
|
||||
| `/create` | Create new issue | `/create "Summary"` |
|
||||
| `/start` | Start work on issue | `/start CG-123` |
|
||||
|
||||
---
|
||||
|
||||
## Sub-Agents
|
||||
|
||||
| Agent | Purpose | Invoke With |
|
||||
|-------|---------|-------------|
|
||||
| `controller-dev` | ESP32-S3 firmware development | "Use controller-dev agent to..." |
|
||||
| `probe-dev` | nRF52840 firmware development | "Use probe-dev agent to..." |
|
||||
| `docs-writer` | Technical documentation | "Use docs-writer agent to..." |
|
||||
| `code-reviewer` | Code review and quality | "Use code-reviewer agent to..." |
|
||||
| `devops` | Platform infrastructure | "Use devops agent to..." |
|
||||
| `test-runner` | Test automation | "Use test-runner agent to..." |
|
||||
|
||||
---
|
||||
|
||||
## Skills (Auto-invoked)
|
||||
|
||||
| Skill | Triggers |
|
||||
|-------|----------|
|
||||
| `esp-idf` | ESP-IDF, ESP32, FreeRTOS, controller firmware |
|
||||
| `zephyr` | Zephyr, nRF52840, probe firmware |
|
||||
| `documentation` | docs, documentation, writing guides |
|
||||
| `devplatform` | Docker, Gitea, YouTrack, TeamCity |
|
||||
|
||||
---
|
||||
|
||||
## Common Build Commands
|
||||
|
||||
### Controller (ESP-IDF)
|
||||
```bash
|
||||
cd /opt/repos/controller
|
||||
source ~/esp/esp-idf/export.sh
|
||||
idf.py build
|
||||
idf.py -p /dev/ttyUSB0 flash monitor
|
||||
idf.py size-components
|
||||
```
|
||||
|
||||
### Probe (Zephyr)
|
||||
```bash
|
||||
cd /opt/repos/probe
|
||||
west build -b nrf52840dk_nrf52840
|
||||
west flash
|
||||
west debug
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Platform URLs
|
||||
|
||||
| Service | URL |
|
||||
|---------|-----|
|
||||
| Gitea | https://git.cleargrow.io |
|
||||
| YouTrack | https://track.cleargrow.io |
|
||||
| TeamCity | https://ci.cleargrow.io |
|
||||
|
||||
---
|
||||
|
||||
## Git Workflow
|
||||
|
||||
```bash
|
||||
# Start feature
|
||||
git checkout main && git pull
|
||||
git checkout -b feature/CG-123-description
|
||||
|
||||
# Work and commit
|
||||
git add .
|
||||
git commit -m "Add feature CG-123"
|
||||
|
||||
# Push and create PR
|
||||
git push -u origin feature/CG-123-description
|
||||
```
|
||||
|
||||
### Commit Message Format
|
||||
```
|
||||
<verb> <description> CG-XXX [#state]
|
||||
|
||||
Examples:
|
||||
Fix sensor parsing CG-123
|
||||
Add temperature calibration CG-124 #fixed
|
||||
Update API documentation CG-125
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## YouTrack Issue States
|
||||
|
||||
```
|
||||
Backlog → Ready → In Progress → Verify → Document → Review → Done
|
||||
↓
|
||||
Triage (on failure)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Repository Paths
|
||||
|
||||
| Repo | Path | Tech |
|
||||
|------|------|------|
|
||||
| Controller | `/opt/repos/controller` | ESP-IDF (C) |
|
||||
| Probe | `/opt/repos/probe` | Zephyr (C) |
|
||||
| Docs | `/opt/repos/docs` | Markdown |
|
||||
| DevPlatform | `/opt/devplatform` | Docker |
|
||||
|
||||
---
|
||||
|
||||
## Useful Docker Commands
|
||||
|
||||
```bash
|
||||
cd /opt/devplatform
|
||||
|
||||
# Service management
|
||||
docker compose up -d
|
||||
docker compose down
|
||||
docker compose restart [service]
|
||||
docker compose logs -f [service]
|
||||
|
||||
# Health check
|
||||
docker compose ps
|
||||
./scripts/healthcheck.sh
|
||||
|
||||
# Backup
|
||||
./scripts/backup.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# YouTrack API
|
||||
export YOUTRACK_TOKEN="perm:xxx"
|
||||
|
||||
# Gitea API
|
||||
export GITEA_TOKEN="xxx"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Fails
|
||||
- Controller: Check `source ~/esp/esp-idf/export.sh`
|
||||
- Probe: Check `west update` was run
|
||||
|
||||
### Service Down
|
||||
```bash
|
||||
docker compose logs [service] --tail=100
|
||||
docker compose restart [service]
|
||||
```
|
||||
|
||||
### Git Push Rejected
|
||||
```bash
|
||||
git pull --rebase origin main
|
||||
git push
|
||||
```
|
||||
163
README.md
Normal file
163
README.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Self-Hosted Development Platform
|
||||
|
||||
A complete, self-hosted development platform with JetBrains tooling.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# 1. Extract and configure
|
||||
cd devplatform/install
|
||||
nano config.env # Set your domain and email
|
||||
|
||||
# 2. Run installer (as root)
|
||||
./install-all.sh
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
| Service | Purpose | Default URL |
|
||||
|---------|---------|-------------|
|
||||
| **Gitea** | Git hosting | git.yourdomain.com |
|
||||
| **YouTrack** | Issue tracking | track.yourdomain.com |
|
||||
| **TeamCity** | CI/CD | ci.yourdomain.com |
|
||||
| **Agent Runner** | Claude Code automation | (background service) |
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Installation**: `install/INSTALL_GUIDE.md`
|
||||
- **System Overview**: `SYSTEM_OVERVIEW.md`
|
||||
- **YouTrack Setup**: `docs/YOUTRACK_SETUP.md`
|
||||
- **Troubleshooting**: `docs/TROUBLESHOOTING.md`
|
||||
|
||||
## Requirements
|
||||
|
||||
- Ubuntu 22.04+ or Debian 12+
|
||||
- 4+ CPU cores, 8GB+ RAM, 100GB+ SSD
|
||||
- Domain with DNS control
|
||||
- Root access
|
||||
|
||||
| Component | Purpose | URL |
|
||||
|-----------|---------|-----|
|
||||
| **Gitea** | Git repository hosting | `git.yourdomain.com` |
|
||||
| **YouTrack** | Issue tracking & project management | `track.yourdomain.com` |
|
||||
| **TeamCity** | CI/CD pipelines | `ci.yourdomain.com` |
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Prerequisites
|
||||
|
||||
- Linux server (Ubuntu 22.04+ recommended)
|
||||
- Docker 24.0+ with Compose v2
|
||||
- Domain with DNS configured
|
||||
- Ports 80, 443, 22 open
|
||||
|
||||
### 2. Clone/Copy Files
|
||||
|
||||
```bash
|
||||
# Create platform directory
|
||||
sudo mkdir -p /opt/devplatform
|
||||
cd /opt/devplatform
|
||||
|
||||
# Copy all files from this package
|
||||
# (docker-compose.yml, nginx/, scripts/, etc.)
|
||||
```
|
||||
|
||||
### 3. Configure Environment
|
||||
|
||||
```bash
|
||||
# Copy template
|
||||
cp .env.template .env
|
||||
|
||||
# Edit with your domain
|
||||
nano .env
|
||||
```
|
||||
|
||||
**Required changes in `.env`:**
|
||||
```bash
|
||||
DOMAIN=yourdomain.com
|
||||
GIT_DOMAIN=git.yourdomain.com
|
||||
TRACK_DOMAIN=track.yourdomain.com
|
||||
CI_DOMAIN=ci.yourdomain.com
|
||||
LETSENCRYPT_EMAIL=admin@yourdomain.com
|
||||
POSTGRES_PASSWORD=<generate-secure-password>
|
||||
```
|
||||
|
||||
### 4. Run Setup
|
||||
|
||||
```bash
|
||||
chmod +x scripts/*.sh
|
||||
./scripts/setup.sh
|
||||
```
|
||||
|
||||
### 5. Access Services
|
||||
|
||||
| Service | URL | First-Time Setup |
|
||||
|---------|-----|------------------|
|
||||
| Gitea | https://git.yourdomain.com | Complete installation wizard |
|
||||
| YouTrack | https://track.yourdomain.com | Create admin account |
|
||||
| TeamCity | https://ci.yourdomain.com | Configure database, authorize agent |
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
/opt/devplatform/
|
||||
├── docker-compose.yml # Main compose file
|
||||
├── .env # Environment configuration
|
||||
├── nginx/ # Reverse proxy configs
|
||||
│ ├── nginx.conf
|
||||
│ └── conf.d/
|
||||
├── gitea/ # Gitea data
|
||||
├── youtrack/ # YouTrack data
|
||||
├── teamcity/ # TeamCity server data
|
||||
├── teamcity-agent/ # Build agent data
|
||||
├── postgres/ # Database data
|
||||
├── certbot/ # SSL certificates
|
||||
├── scripts/ # Management scripts
|
||||
│ ├── setup.sh
|
||||
│ ├── backup.sh
|
||||
│ └── healthcheck.sh
|
||||
└── backups/ # Backup storage
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
# Start all services
|
||||
docker compose up -d
|
||||
|
||||
# Stop all services
|
||||
docker compose down
|
||||
|
||||
# View logs
|
||||
docker compose logs -f [service]
|
||||
|
||||
# Check health
|
||||
./scripts/healthcheck.sh
|
||||
|
||||
# Run backup
|
||||
./scripts/backup.sh
|
||||
|
||||
# Update services
|
||||
docker compose pull && docker compose up -d
|
||||
```
|
||||
|
||||
## Resource Requirements
|
||||
|
||||
| Minimum | Recommended |
|
||||
|---------|-------------|
|
||||
| 4 CPU cores | 8+ cores |
|
||||
| 6 GB RAM | 16 GB RAM |
|
||||
| 40 GB SSD | 100+ GB SSD |
|
||||
|
||||
## Documentation
|
||||
|
||||
See **SYSTEM_OVERVIEW.md** for:
|
||||
- Complete architecture diagram
|
||||
- Integration setup guides
|
||||
- Backup & recovery procedures
|
||||
- Troubleshooting guide
|
||||
- Security configuration
|
||||
|
||||
## License
|
||||
|
||||
MIT License - Use freely for personal or commercial projects.
|
||||
1135
SYSTEM_OVERVIEW.md
Normal file
1135
SYSTEM_OVERVIEW.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user