Skip to content

Commit 06f1dfd

Browse files
committed
Boy Scout Pass 2026-05-09
1 parent 1bed4d6 commit 06f1dfd

5 files changed

Lines changed: 120 additions & 0 deletions

File tree

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,11 @@ Cargo.lock
66
.claude/
77
CLAUDE.md
88
archive/
9+
review-queue/
910
.idea/
11+
12+
# Temporary scratch files — local only
13+
tmp/
14+
15+
# Claude Code project-local memory — personal, not committed
16+
memory/

AGENTS.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# AGENTS.md
2+
3+
> Fast-path operating guide for AI coding agents on this project.
4+
> Prefer repository truth over assumptions — check the files referenced below.
5+
6+
## Project Overview
7+
8+
`battery-monitor` is a Rust library for battery voltage monitoring and power management on ESP32 microcontrollers, targeting the Heltec WiFi LoRa 32 V3 (ESP32-S3) and Adafruit ESP32 Feather V2.
9+
It is designed for low-power firmware loops: read battery state, decide whether to transmit, enter deep sleep, repeat.
10+
11+
## Architecture
12+
13+
Single crate: `crates/battery-monitor/`. Two layers split by the `esp-idf` feature flag.
14+
15+
**Core — always compiled, host-testable (`--no-default-features`):**
16+
- `lib.rs``BatteryMonitor` + `ChargingMonitor` traits, `PowerSource`, `BatteryStatus`, `Noop*` mocks
17+
- `config.rs``BatteryConfig` with board presets (`heltec_v3()`, `adafruit_feather_v2()`) and `evaluate_reading()`
18+
- `sleep.rs``SleepManager` + `WakeCauseSource` traits, `WakeCause`/`WakeSource` enums, `NoopSleepManager`
19+
- `charging.rs``ChargingMonitor` trait, `ChargingState`, `ChargingSource`, `NoopChargingMonitor`
20+
21+
**ESP-IDF implementations — feature `esp-idf` (default):**
22+
- `esp_adc.rs` — ADC1 reading with averaging and voltage divider compensation
23+
- `esp_sleep.rs` — deep sleep with timer and GPIO wake sources; `EspWakeCauseSource` reads wake reason
24+
- `esp_charging.rs` — MCP73831 STAT pin + USB VBUS detect GPIO
25+
26+
Every hardware concern is behind a trait. Every trait has a `Noop*` mock for host-side testing.
27+
Business logic lives in `BatteryConfig::evaluate_reading()` — hardware-independent and fully unit-tested.
28+
29+
## Development Workflow
30+
31+
Requires the Espressif `esp` Rust toolchain (installed via `espup`). Use `just` for all operations:
32+
33+
```shell
34+
just check # check platform-independent code — no ESP toolchain needed
35+
just test # run host-side unit tests — no ESP toolchain needed
36+
just check-all # check everything including ESP-IDF (requires ESP toolchain)
37+
just build-all # full build for the ESP32 target
38+
just verify # non-modifying full verification: fmt-check, deny, check, lint, test
39+
just pre-commit # full verification with auto-formatting (modifies files)
40+
just build-example <name> # build a named example inferred from the idf_{chip}_{name} prefix
41+
just run <name> # build, flash, and open serial monitor
42+
```
43+
44+
Run `just` with no arguments to list all recipes. Host-side tests use `--no-default-features` and require no ESP toolchain. The `esp` toolchain is only needed for `check-all`, `build-all`, `build-example`, and `flash`.
45+
46+
## Key Conventions
47+
48+
**Trait-first:** All hardware reads are behind a trait. Adding a new board means implementing the trait, not changing business logic. See `NoopBatteryMonitor` and `NoopChargingMonitor` for the mock pattern.
49+
50+
**Feature boundary:** Code compilable on the host must not be inside `#[cfg(feature = "esp-idf")]`. This boundary is what makes `just test` work without the ESP toolchain.
51+
52+
**Error handling:** `anyhow::Result` with `.context()` for fallible operations. No `.unwrap()` outside tests. Log with `log::info!`, `log::warn!`, `log::error!`.
53+
54+
**Board presets:** Use `BatteryConfig::heltec_v3()` or `BatteryConfig::adafruit_feather_v2()` — both are calibrated for each board's voltage divider ratio and ADC characteristics. Start from a preset when targeting a new board.
55+
56+
**`is_sufficient` fallback:** `BatteryStatus::is_sufficient()` intentionally returns `true` for `External` and `Unknown` sources — do not block operations when battery state is unclear.
57+
58+
**`EspWakeCauseSource` is a unit struct:** `EspWakeCauseSource.last_wake_cause()` is both a constructor and a method call in one expression. Call it early in `main()`, before peripheral initialisation — the EXT1 status register is hardware-preserved until the next sleep entry.
59+
60+
## Important Files
61+
62+
- `crates/battery-monitor/src/lib.rs` — public API, trait definitions, Noop mocks, usage examples in doc comments
63+
- `crates/battery-monitor/src/config.rs` — board presets and voltage conversion logic
64+
- `docs/key-insights.md` — non-obvious hardware behaviour, build quirks, and resolved gotchas; read before starting any non-trivial task
65+
- `docs/hardware-setup.md` — GPIO wiring tables for Heltec V3 and Feather V2
66+
- `crates/battery-monitor/examples/idf_esp32_battery.rs` — complete Feather V2 example: wake-cause detection, ADC read, charging state, deep sleep

docs/adr/000-template.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# ADR-NNN: Title
2+
3+
## Status
4+
Proposed | Accepted | Deprecated | Superseded by ADR-NNN
5+
6+
## Context
7+
What is the issue or decision that needs to be made?
8+
9+
## Decision
10+
What was decided and why.
11+
12+
## Consequences
13+
What are the positive and negative effects of this decision?
14+
15+
## Alternatives Considered
16+
| Alternative | Pros | Cons | Why Rejected |
17+
|-------------:|------:|:------|:--------------|
18+
| | | | |

docs/features/000-template.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Feature: <Name> v<N>
2+
3+
## Decisions
4+
| Decision | Reason | Rejected Alternative |
5+
|----------|--------|----------------------|
6+
| | | |
7+
8+
## Constraints
9+
- <Hard constraint 1>
10+
- <Hard constraint 2>
11+
12+
## Open Questions
13+
- [ ] <Question awaiting input>
14+
15+
## State
16+
- [ ] Design approved
17+
- [ ] Core implementation
18+
- [ ] Tests passing
19+
- [ ] Documentation updated
20+
21+
## Session Log
22+
- <YYYY-MM-DD> — Feature doc created

docs/project-lore.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Project Lore
2+
3+
This file records non-obvious technical discoveries: facts that caused surprising
4+
failures, took significant time to debug, or would save a future developer 30+
5+
minutes if known upfront.
6+
7+
Refer to `AGENTS.md` and the `/project-lore` skill for recording guidelines.

0 commit comments

Comments
 (0)