From e9f20349a1476ae9915108a2a9fd37421e958711 Mon Sep 17 00:00:00 2001 From: Smokey <150986568+jacisjake@users.noreply.github.com> Date: Tue, 27 Oct 2026 12:43:22 -0600 Subject: [PATCH] EVENTS.md: nests contract Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UQnSw4RRWp8uqpj3nsnnXF --- EVENTS.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/EVENTS.md b/EVENTS.md index 24dca37..a8d8024 100644 --- a/EVENTS.md +++ b/EVENTS.md @@ -38,3 +38,23 @@ Pending approvals that get no answer within 10 minutes count as rejected (`verdi - `requester.pranked` goes to every list of that requester's still flying; if none, only the 429 is sent. - Each SSE message carries an `id:` line, so clients can reconnect with `Last-Event-ID`. Heartbeat comment every 15 seconds. - The server listens on localhost only by default. There is no login yet, and requester names are self-asserted. + +## Nests + +A nest is a room where a team of crows works together. You create a nest and pick its core crows; when a job needs more crows than the core has, the Sentry borrows from the rest of the flock. The Sentry and Elder serve every nest and are never core members. + +- The default nest is `todo`, with an empty core: its crows come from the whole flock, so nothing there is ever "borrowed". +- Crows are picked core-first (rotating within the core), then borrowed from outside it (rotating), still capped by the flock guardrails. +- Nests persist on the server (`.crows/nests.json`). + +| Method | Path | Body | Returns | +|---|---|---|---| +| GET | `/api/nests` | | `{"roster": ["Hugin", ...], "nests": [{"nest_id", "name", "crows": [...]}]}`; roster is the 8 crows (not Sentry or Elder) | +| POST | `/api/nests` | `{"name": "Launch copy", "crows": ["Pepper", "Inky"]}` | 201 with the nest; 400 with `{"message"}` if invalid | +| POST | `/api/lists` | adds optional `"nest_id"` (default `todo`) | 404 with `{"message"}` for an unknown nest | + +Guardrails: name 1–40 characters after trimming; `nest_id` is a slug of the name (lowercase, `a-z0-9-`), unique (409 with `{"message"}` on a clash); `crows` must be roster names, no duplicates, 1–8 of them; at most 20 nests. + +Event changes: +- `list.started` adds `nest_id`. +- `crow.flying` adds `borrowed` (bool): true when the crow is not in the nest's core. Always false for Sentry, Elder, and the `todo` nest.