Files
pastilhas f5d5a75314 AGENTS.md, so both harnesses find the same guidance
opencode discovers AGENTS.md and nothing else; claude code discovers CLAUDE.md.
this repo had neither, so an agent sent to change something here arrived with no
guidance at all under either.

it deliberately does NOT repeat README.md. that file says what the plugin is,
for someone deciding whether to install it. this one answers the other question:
i have to change something in here, what will i break.

the facts in it are read from the repository rather than recalled — the panel
keys from web/panels.ts, the tables from db/schema.ts, the permission keys, the
host binaries and the route claims from manifest.ts. presence is the declaration
everywhere in this system, so the file says what the platform will actually
conclude from these files existing.

CLAUDE.md beside it is a pointer, not a copy: two copies drift and the stale one
is the one somebody reads.
2026-08-27 07:24:07 +00:00

66 lines
3.2 KiB
Markdown

# AGENTS.md
Guidance for a coding agent working on **this plugin's own repository**. `CLAUDE.md` beside it only
points here — the two harnesses discover different filenames and one set of instructions has to reach
both.
**This is not what the plugin is.** `README.md` answers that, for a person deciding whether to install it.
This file answers "I have to change something in here — what will I break?"
## Where you are
A plugin repository, cloned into `~/officer-dev/plugins/caldav`, its own git remote. It is **not** part of
the platform's repository, and `platform/plugins/caldav` is a different thing — that is where this plugin
gets INSTALLED, by the installer cloning it from gitea. Never edit there; the next install overwrites it.
Verify the checkout is well-formed with `bun run plugins:check` from the platform repo.
## What this plugin is, in one paragraph
Calendars and contacts over CalDAV and CardDAV, backed by Radicale spawned on loopback by its own
sidecar. One sidecar, one permission, **two screens** — `/calendar` and `/contacts` — which makes it the
only plugin using `screens` in its manifest.
## What must not change without knowing why
- **`/dav`, `/.well-known/caldav`, `/.well-known/carddav`.** Claimed in `unauthenticatedRootPaths`, served
ABOVE the account gate because phones send HTTP Basic and have nowhere to put a JWT. Reserved names,
claimable only because this is a first-party plugin.
- **`dav_app_passwords`** is not prefixed `caldav_` and the installer warns about it. Deliberate:
installs hold real rows and a naming convention is not worth a data migration.
- **The two screen segments.** They were core routes; bookmarks, dock tiles and persisted layouts all
address them.
- **The panel keys** (`calendar-nav`, `calendar-view`, `contacts-nav`, `contacts-view`). A stored layout
names them.
## Traps that have already cost time
- **`sidecar/radicale.ts` generates `radicale.conf` inside a template literal.** A backtick in a comment
there terminates the string and the file stops parsing. No test imports it, so only `bunx tsgo` catches
this.
- **`createSidecarProxy` mounts a catch-all**, so in `api/router.ts` the plugin's own routes must be
registered BEFORE it or they are forwarded to the sidecar and 404.
- **Request bodies are not parsed** on this plugin's routes — the proxy registers the whole prefix with
`registerProxiedPrefix`. Use `jsonBody()` in `api/app-passwords.ts`, not `ctx.get('body')`.
- **`date -u -d` does not convert local time to UTC.** It parses AND prints as UTC. Every event lands an
hour out and nothing errors. See the skill.
## Verifying
From the platform repo, because that is where the toolchain is:
```bash
bunx tsgo # a red typecheck is not done
bun test # 1 known failure: ModelSelector, unrelated
bun run plugins:check
bunx prettier --write <the files you touched>
```
Changing the sidecar needs `pm2 restart officer-caldav`; changing `api/` or `web/` needs
`pm2 restart officer`.
## Related
- `README.md` — what it is and what it claims, for someone installing it
- `skills/calendar-and-contacts/SKILL.md` — how an agent USES the calendar, as opposed to changing it