All checks were successful
CI / ci (push) Successful in 5m34s
Add a grounded doc set under docs/ plus a root CONTRIBUTING.md: - docs/ARCHITECTURE.md: current code shape (layers, data seam, provider resolution, reminder engine, DI, build/tooling, manifest) - docs/ROADMAP.md: status view (M0/M1 done, M2 in progress, open decisions) - docs/RELEASING.md: tag-driven release flow, CI jobs, F-Droid repo, secrets (was referenced by build.gradle.kts and CHANGELOG but missing) - docs/README.md: docs index and how the docs relate - CONTRIBUTING.md: build/test/lint, layer rules, style, PR conventions Also refresh the stale "M0 — skeleton" status note in README. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
93 lines
4.2 KiB
Markdown
93 lines
4.2 KiB
Markdown
# Contributing to Floret
|
|
|
|
Thanks for your interest in Floret — a Material 3 Expressive task app that's a
|
|
pure front-end over the OpenTasks `TaskContract` provider, with no own database
|
|
or sync stack. Before diving in, skim [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
|
|
(how it's built), [`docs/ROADMAP.md`](docs/ROADMAP.md) (what's next), and
|
|
[`docs/PLAN.md`](docs/PLAN.md) (the design rationale). This file covers the
|
|
practical how.
|
|
|
|
## The one architectural rule
|
|
|
|
Everything above the data layer talks to `TasksRepository` and sees only domain
|
|
types and Flows. **Provider column names, `TaskContract`, `ContentResolver`, and
|
|
the authority string never leak above `data/tasks/`.** This is what keeps
|
|
"Posture B" (bundling the provider later) an additive change instead of a
|
|
rewrite — see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §7. If a change
|
|
would expose provider details to a ViewModel or the UI, it's in the wrong layer.
|
|
|
|
## Prerequisites
|
|
|
|
- JDK 17
|
|
- Android SDK: compileSdk 37, build-tools 36.0.0 (the Gradle wrapper handles AGP/Kotlin)
|
|
- A device or emulator with **OpenTasks** or **tasks.org** installed for
|
|
anything touching the read/write paths (ideally with DAVx5 syncing a CalDAV
|
|
task list, so there's real data). Debug builds fall back to `DemoSeeder` for
|
|
sample data.
|
|
|
|
## Build, test, lint
|
|
|
|
```sh
|
|
./gradlew :app:assembleDebug # build the debug APK
|
|
./gradlew :app:testDebugUnitTest # JVM unit tests (JUnit5 + Truth + Turbine)
|
|
./gradlew lintDebug # Android lint (CI runs this on every push)
|
|
```
|
|
|
|
CI (`.gitea/workflows/ci.yaml`) runs lint → unit tests → debug build on every
|
|
push, so run these locally before opening a PR. Keep CI green.
|
|
|
|
## Where to put code
|
|
|
|
| Layer | Lives in | Rule of thumb |
|
|
|---|---|---|
|
|
| Pure logic (models, filtering, sorting, form validation, date maths) | `domain/` | No Android imports — must be JVM-unit-testable. |
|
|
| Provider access | `data/tasks/` | The only place that knows about the provider. New provider work goes through `TasksDataSource`. |
|
|
| Reminders, prefs, DI, demo data | `data/reminders/`, `data/prefs/`, `data/di/`, `data/demo/` | |
|
|
| Screens | `ui/<area>/` | One ViewModel + immutable `UiState` per area; Compose for the screen. |
|
|
|
|
## Code style & conventions
|
|
|
|
- **Kotlin**, 4-space indent, LF line endings, final newline, no trailing
|
|
whitespace — all enforced by `.editorconfig` (2-space for yaml/toml/json/md).
|
|
Match the surrounding code.
|
|
- **Material 3 Expressive** for all UI: use `MaterialExpressiveTheme`, the
|
|
colour-scheme tokens (never hardcoded colours), and canonical M3 components
|
|
(e.g. `ListItem` for rows). Consult the `material-3` skill before designing a
|
|
new screen or component.
|
|
- Prefer the domain layer for anything testable; keep `AndroidTasksDataSource`
|
|
the only Android-coupled data implementation so the rest stays JVM-testable.
|
|
|
|
## Tests
|
|
|
|
- New domain logic (mappers, filters, sorting, forms, value mapping) **must**
|
|
come with JVM unit tests under `app/src/test/`. The data source is the
|
|
JVM-testable seam — mock or fake it rather than reaching for instrumentation.
|
|
- Add an instrumented test only when a path genuinely needs a real
|
|
`ContentResolver`.
|
|
|
|
## Commits & PRs
|
|
|
|
- Write focused commits with clear messages (the existing history uses short,
|
|
scoped subjects like `UI: ...` / `M1 ...`).
|
|
- Update [`CHANGELOG.md`](CHANGELOG.md) under `[Unreleased]` for any
|
|
user-visible change — its sections feed the release notes and F-Droid "What's
|
|
New" (see [`docs/RELEASING.md`](docs/RELEASING.md)).
|
|
- If your change shifts the architecture or completes a milestone, update
|
|
[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) / [`docs/ROADMAP.md`](docs/ROADMAP.md)
|
|
in the same PR.
|
|
- Don't bump `versionName` / `versionCode` by hand — the git tag drives those at
|
|
release time.
|
|
|
|
## Scope
|
|
|
|
Floret stays true to its thesis: a front-end over **open** task backends
|
|
(CalDAV / iCalendar / DecSync via the OpenTasks provider). Proprietary backends
|
|
(Google Tasks, Microsoft To Do) are out of scope by design — they'd mean owning
|
|
a sync stack. v1 targets the OpenTasks contract (OpenTasks + tasks.org); jtx's
|
|
richer contract is a possible later addition.
|
|
|
|
## License
|
|
|
|
By contributing you agree your contributions are licensed under the project's
|
|
[MIT License](LICENSE).
|