Cut the README to a getting-started guide; retire SPECS.md and TODO.md

The README had grown to 413 lines and explained as much as it instructed:
someone trying to get calcalist running read past the architecture, the
scheduling-inertness rule and the reasoning behind retarget before reaching
anything they needed to type.

Most of the excess was duplication of SPECS.md, which is now retired along with
TODO.md since the roadmap is finished. That inverted the usual answer — the
rationale could not simply move to the design document, because there would not
be one. Checking what would actually be orphaned: the architecture rationale is
already in the module doc comments, beside the code it governs and where it
cannot drift; the M0-M2 record is history and git keeps it. Two things had no
home: the working agreement that has shaped every commit, and two decisions
that cost real design work to decline and would otherwise be re-proposed from
first principles. Both are now in CLAUDE.md, which is read at the start of every
session rather than filed and forgotten.

What the README keeps is the whole setup path, because none of it exists
anywhere else now: every configuration field, the Google OAuth walkthrough in
full, routing, and the systemd units. What it gains is a short section on what
the tool does to your calendars — deletion propagating to the source is not
something to discover by accident. What it loses is the design commentary.

Also moves `discover` out of the command list and into the CalDAV endpoint
section, since getting the url field right is its entire purpose.

Verified rather than eyeballed: the worked example was extracted and run through
doctor and status, the command table diffed against --help, and every internal
anchor resolved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
randogoth 2026-09-10 16:38:53 +03:00
parent ef6482ed62
commit 4854844a72
4 changed files with 187 additions and 448 deletions

74
CLAUDE.md Normal file
View file

@ -0,0 +1,74 @@
# calcalist
Aggregates events between CalDAV, Google Calendar and iCal feeds. `README.md` is
the user-facing guide; the design rationale lives in the module doc comments,
beside the code it governs.
These conventions were `SPECS.md`'s, which has been retired now the roadmap is
finished. Git history holds it, and `TODO.md`, if the record is ever wanted.
## Development
Use devbox for dependency management and scripts. Use jj for version control
(colocated with git).
- `devbox run fmt` — format.
- `devbox run check` — format check, clippy with warnings denied, and tests.
This is the gate; jj has no commit step to hang a hook off, since the working
copy is itself a commit.
- `devbox run test` — tests only.
Keep `/target` in `.gitignore`: jj snapshots the working copy on every command,
with no staging step.
The integration tests in `tests/` need `radicale` and `pimsync`, both of which
devbox provides. Outside that shell they report what is missing and pass.
## Coding style
- Simple, readable, idiomatic.
- Explicit types for public APIs and important fields.
- Prefer immutable data structures.
- No global mutable state.
- No speculative features or dependencies.
- Keep functions short and single-purpose; extract helpers to avoid nesting.
- File and module naming: `snake_case.rs`. Types and traits: `PascalCase`.
Functions, variables and fields: `snake_case`. Constants:
`SCREAMING_SNAKE_CASE`.
- Run `devbox run check` before describing a change.
- Comment only when intent is not obvious from the code.
- Prefer composition and traits over deep type hierarchies.
## Decisions already taken
Settled after real design work. Reopen only with new information, not from
first principles.
**No configuration web interface.** Designed in full, then dropped. Its audience
would be people who find TOML hard — but every user must first create a Google
Cloud project, configure a consent screen and put a secret in a keyring, which
is a far higher bar than editing the config. Anyone who clears it can edit the
file; anyone who cannot never reaches the file. `doctor`, `status` and
`discover` cover what the interface was actually for.
**Bring-your-own OAuth client, not a shipped verified one.** Verification for
the Calendar scope needs a domain you own — a `github.io` address is rejected —
and Calendar API quota is per Cloud project, with charges announced for
exceeding it. A shipped client would pool every user's syncing into the
publisher's project, and their bill. Shipping an *unverified* shared client is
worse still: the 100-new-user cap is permanent for the project's lifetime.
**pimsync cannot reach Google, and never will.** It has no REST storage, and its
config exposes only HTTP Basic auth, which Google's CalDAV endpoint rejected in
March 2025. The Google leg is calcalist's own in every design.
**The config file is never machine-rewritten.** It is the portable,
hand-editable artefact. Anything that writes it must preserve comments,
ordering and omitted defaults — `toml::to_string` on the `Serialize` derive
does none of those things.
## Known gap
A failing `pimsync sync` stops the whole CalDAV leg. Unlike the Google side this
cannot be narrowed: pimsync is one process covering every pair, and a failure
does not say which pair it belongs to.