openscribe/state/DECISIONS.md
Laurence 031074c9a9
Some checks failed
ci / firmware (push) Failing after 2s
ci / server (push) Failing after 45s
scaffold: OpenScribe open-source self-hosted AI voice recorder
Bootstrap of the project (M0). Sets up the monorepo, design docs, hardware BOM,
the open API contract, component skeletons, licensing and CI, following the
Default Workflow SOP.

What changed:
- CLAUDE.md + docs/: copied the Default Workflow so sessions load the SOP.
- state/: PROJECT, ARCHITECTURE, DECISIONS, TODO, NOTES filled in for OpenScribe.
  ARCHITECTURE captures the four-part design (firmware, server, app, case) and the
  three sync paths; DECISIONS records the hardware, AI-stack, storage, app and
  licensing choices; TODO lays out milestones M1-M9.
- hardware/BOM.md: two build options (compact XIAO ESP32-S3 Sense; dev ESP32-S3 +
  I2S mic + SD), wiring/pinout, indicative cost.
- api/openapi.yaml: the completely open API (device + server surfaces), including
  recording list/download/delete and exports (wav/ogg/txt/srt/vtt/md/json).
- firmware/: PlatformIO ESP32-S3 project, two board profiles, pin map, boot scaffold
  with module seams for M1-M4.
- server/: FastAPI skeleton mirroring the OpenAPI, config for self-hosted MinIO,
  faster-whisper and Ollama; stub routes browsable at /docs.
- app/, case/: Flutter app plan; parametric OpenSCAD enclosure.
- Licensing: GPL-3.0 (code), CERN-OHL-S-2.0 (hardware), CC-BY-SA-4.0 (case/docs),
  REUSE-style LICENSES/ with SPDX headers; LICENSING.md explains the split.
- CI: Forgejo Actions workflow builds firmware (both profiles) and lints/imports server.

Why:
- Everything self-hosted and openly licensed per the user's requirements: an open
  API, three sync paths (BLE control, WiFi transfer, independent WiFi upload on
  charge to generic cloud storage), and a full self-hosted transcription+summary stack.

Notes:
- No custom PCB in v1; off-the-shelf modules. Physical verification waits on parts.
- Component code is stubs at M0; features land milestone by milestone, each as its
  own branch/PR per the workflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:21:37 +01:00

4.8 KiB

Decisions

A dated, append only log of decisions and their rationale. Newest at the top. Never rewrite past entries; if a decision is reversed, add a new entry that says so.

2026-07-03 - Licensing: copyleft, multi-part (REUSE-style)

  • Decision: Code (firmware, server, app) under GPL-3.0-only; hardware design under CERN-OHL-S-2.0; case models and documentation under CC-BY-SA-4.0. Licence texts live in LICENSES/; top-level LICENSE is GPL-3.0 for forge detection; LICENSING.md explains the split. Apache-2.0 text kept for a possible future permissive client SDK.
  • Context: User asked for "as open source as possible".
  • Rationale: Strong copyleft keeps derivatives open (the point of the project); CERN and CC-BY-SA are the standard reciprocal licences for hardware and creative/docs.
  • Consequences: Derivatives must stay open. If we later want wide third-party adoption of a client library, that specific component can be relicensed permissive (Apache-2.0).

2026-07-03 - Self-hosted tools throughout

  • Decision: Forge = Forgejo (git.discworld.casa); CI = Forgejo Actions; STT = faster-whisper; summaries = Ollama (local LLM); object storage = MinIO (S3-compatible) or local FS / WebDAV. No required proprietary SaaS anywhere.
  • Context: User: "using selfhosted tools where possible".
  • Rationale: Matches the own-your-data goal and keeps running costs at zero beyond the user's own hardware.
  • Consequences: User must run a server (NAS / mini-PC) for AI features; the device and app work without it for plain recording + transfer.

2026-07-03 - Self-hosted AI stack in scope for v1

  • Decision: Build the full pipeline: record -> transcribe (faster-whisper) -> summarise (Ollama) -> export. AI runs on the server, not the device.
  • Context: User chose "Full self-hosted AI stack" at the scope checkpoint.
  • Rationale: Transcription + summary is Plaud's headline feature; server-side keeps the device cheap and low-power while staying fully self-hosted.
  • Consequences: Larger build; server is required for AI features. Device stays simple.

2026-07-03 - Independent upload target: generic cloud storage

  • Decision: When on charge / hard-powered, the device uploads to configurable generic storage: S3-compatible (default: self-hosted MinIO), with WebDAV/NAS as alternatives.
  • Context: User chose "Generic cloud storage" for the independent WiFi path.
  • Rationale: Decouples device from any bespoke always-on server; standard protocol; self-hostable.
  • Consequences: Server ingests from the store (watch/notify/poll). Object-store credentials live in device NVS and must be scoped/rotatable.

2026-07-03 - Mobile app: Flutter (Android + iOS)

  • Decision: One Flutter codebase targeting both platforms.
  • Context: User chose Flutter (Android + iOS).
  • Rationale: Single codebase, both stores.
  • Consequences: iOS background BLE is restricted, so BLE = control/provisioning only; WiFi handles bulk transfer (already the design).

2026-07-03 - Hardware: ESP32-S3 + I2S MEMS mic + microSD (off-the-shelf, no PCB)

  • Decision: Target ESP32-S3 (PSRAM, WiFi + BLE 5, USB). Mic: I2S MEMS (INMP441 default, ICS-43434 upgrade). Storage: microSD. Power: LiPo + charge IC with charge/VBUS detect. v1 uses modules on a carrier/protoboard; no custom PCB. Full list in hardware/BOM.md.
  • Context: User asked me to spec a BOM to buy; has ESP32 / Pico W / other boards.
  • Rationale: ESP32-S3 does all three radios + audio buffering on one cheap chip; I2S MEMS gives clean digital audio; microSD removes length limits. Pico W and classic ESP32 are viable fallbacks but weaker for audio/PSRAM.
  • Consequences: Bigger enclosure than a commercial Plaud; a custom PCB is a later step.

2026-07-03 - Firmware toolchain: PlatformIO + Arduino-ESP32

  • Decision: Build the firmware with PlatformIO using the Arduino-ESP32 framework.
  • Context: Need approachable, reproducible builds and CI.
  • Rationale: Lower barrier for contributors than raw ESP-IDF; good library support for I2S, SD, BLE, HTTP; PlatformIO gives pinned, CI-friendly builds.
  • Consequences: If we hit Arduino limits (fine-grained power, advanced BLE), we can drop to ESP-IDF per-module or migrate; noted as a possible future change.

2026-07-03 - Project name and default audio format

  • Decision: Name = "OpenScribe" (record + transcribe, open). Default recording format = WAV PCM 16 kHz mono 16-bit; compressed codecs (ADPCM/Opus) are a later optimisation.
  • Context: Project bootstrap.
  • Rationale: Clear, descriptive, unencumbered name; WAV is simple and high quality for speech and trivial to decode everywhere.
  • Consequences: Larger files (~115 MB/hour) make WiFi the primary transfer path; revisit with Opus for battery-mode transfer and storage.