Part of: docs/SCOPE.md (S2) Depends on: #1 (Epic A)
Objective
A human posts a message into a nest and a crow answers it — the room works as conversation, not pipeline: say, request, claim, deliver, refer with @-addressing, event-driven (no idle loops), replayable over SSE. Mock brain first; live models only after the loop passes tests.
Context a stranger needs
Nest (nests.go:17) is {ID, Name, Crows} with no message log — the store persists to .crows/nests.json. A nest message log is new: append-only per nest, persisted alongside, mirroring NestStore.save()'s atomic write pattern (nests.go:133).
Hub (hub.go) already does per-list_id fan-out with numbered history and Last-Event-ID replay (hub.go:121). Reuse the shape, keyed by nest_id. The existing GET /api/events?list_id= (server.go:191) stays; nests need their own stream route (add ?nest_id= on the same handler or a parallel one — smallest change that keeps contracts-first).
Message kinds and payload fields must be written into EVENTS.md before any Go code (repo hard rule).
Server routes live in Server.Handler() (server.go:43). Bodies decode via decode() with the 64 KiB cap.
The spec's rules (CHATROOM_SPEC section 4): deliver addresses back to the requester; corrections acknowledged once; membership is a boundary. Event-driven + who-may-speak gating (CHATROOM_SPEC.md:50-56) — the trust-gated half is Epic C/D's dispatch; B only needs "addressed crows must respond" with the mock brain.
Personas and Flock.ask (flock.go:132): every model call goes through ask or classify (CLAUDE.md section 9). For B's mock tests, MockBrain (brain.go:223) already exists.
Out of scope for this epic
Complexity routing, expectations, nudges, assistant or COS roles, debate mode, UI changes.
curl posts owner → request → claim → deliver into a test nest; SSE reconnect with Last-Event-ID replays all four in order; with the mock brain all tests in the plan pass under -race; with a live key, a named crow posts an in-character deliver in a nest within 60 seconds of a request.
Part of: docs/SCOPE.md (S2) Depends on: #1 (Epic A)
## Objective
A human posts a message into a nest and a crow answers it — the room works as conversation, not pipeline: `say`, `request`, `claim`, `deliver`, `refer` with @-addressing, event-driven (no idle loops), replayable over SSE. Mock brain first; live models only after the loop passes tests.
## Context a stranger needs
- `Nest` (`nests.go:17`) is `{ID, Name, Crows}` with no message log — the store persists to `.crows/nests.json`. A nest message log is new: append-only per nest, persisted alongside, mirroring `NestStore.save()`'s atomic write pattern (`nests.go:133`).
- `Hub` (`hub.go`) already does per-`list_id` fan-out with numbered history and `Last-Event-ID` replay (`hub.go:121`). Reuse the shape, keyed by `nest_id`. The existing `GET /api/events?list_id=` (`server.go:191`) stays; nests need their own stream route (add `?nest_id=` on the same handler or a parallel one — smallest change that keeps contracts-first).
- Message kinds and payload fields must be written into `EVENTS.md` before any Go code (repo hard rule).
- Server routes live in `Server.Handler()` (`server.go:43`). Bodies decode via `decode()` with the 64 KiB cap.
- The spec's rules (CHATROOM_SPEC section 4): deliver addresses back to the requester; corrections acknowledged once; membership is a boundary. Event-driven + who-may-speak gating (`CHATROOM_SPEC.md:50-56`) — the trust-gated half is Epic C/D's dispatch; B only needs "addressed crows must respond" with the mock brain.
- Personas and `Flock.ask` (`flock.go:132`): every model call goes through `ask` or `classify` (`CLAUDE.md` section 9). For B's mock tests, `MockBrain` (`brain.go:223`) already exists.
## Out of scope for this epic
Complexity routing, expectations, nudges, assistant or COS roles, debate mode, UI changes.
## Plan of record
- [x] #8 — EVENTS.md: nest message-kind contract
- [x] #9 — MessageLog store with persistence and replay
- [x] #10 — POST messages endpoint + event-driven responder trigger
- [x] #11 — @-addressing parse and addressed-crow-must-respond
- [x] #12 — Mock-brain end-to-end conversation test
- [x] #13 — Live models answer as crows in the nest
## Definition of done
`curl` posts owner → request → claim → deliver into a test nest; SSE reconnect with `Last-Event-ID` replays all four in order; with the mock brain all tests in the plan pass under `-race`; with a live key, a named crow posts an in-character `deliver` in a nest within 60 seconds of a `request`.
Sentry decision landed (#6): it becomes the nest watchdog, quarantining crows outside their contract (flag message kind). Epic F gains: a Sentry-watchdog task beside COS spin-up.
Sentry decision landed (#6): it becomes the nest watchdog, quarantining crows outside their contract (`flag` message kind). Epic F gains: a Sentry-watchdog task beside COS spin-up.
curl owner -> request -> (crow claim/deliver) chain exercised against the running server (mock): 201s, records in log.
SSE reconnect with Last-Event-ID replays in order (TestNestConversationEndToEndMock + manual curl).
Mock brain: all 50 tests pass under -race.
Live key: TestLiveCrowDeliversInNest PASS on nvidia/nemotron-3.5-lightning:free (11.5s, responsive deliver, logged non-mock flight). The pinned gemma:free model is currently 429'd upstream, so the test skips there by design rather than lying.
Definition of done walked 2026-10-28:
- curl owner -> request -> (crow claim/deliver) chain exercised against the running server (mock): 201s, records in log.
- SSE reconnect with Last-Event-ID replays in order (TestNestConversationEndToEndMock + manual curl).
- Mock brain: all 50 tests pass under -race.
- Live key: TestLiveCrowDeliversInNest PASS on nvidia/nemotron-3.5-lightning:free (11.5s, responsive deliver, logged non-mock flight). The pinned gemma:free model is currently 429'd upstream, so the test skips there by design rather than lying.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of: docs/SCOPE.md (S2) Depends on: #1 (Epic A)
Objective
A human posts a message into a nest and a crow answers it — the room works as conversation, not pipeline:
say,request,claim,deliver,referwith @-addressing, event-driven (no idle loops), replayable over SSE. Mock brain first; live models only after the loop passes tests.Context a stranger needs
Nest(nests.go:17) is{ID, Name, Crows}with no message log — the store persists to.crows/nests.json. A nest message log is new: append-only per nest, persisted alongside, mirroringNestStore.save()'s atomic write pattern (nests.go:133).Hub(hub.go) already does per-list_idfan-out with numbered history andLast-Event-IDreplay (hub.go:121). Reuse the shape, keyed bynest_id. The existingGET /api/events?list_id=(server.go:191) stays; nests need their own stream route (add?nest_id=on the same handler or a parallel one — smallest change that keeps contracts-first).EVENTS.mdbefore any Go code (repo hard rule).Server.Handler()(server.go:43). Bodies decode viadecode()with the 64 KiB cap.CHATROOM_SPEC.md:50-56) — the trust-gated half is Epic C/D's dispatch; B only needs "addressed crows must respond" with the mock brain.Flock.ask(flock.go:132): every model call goes throughaskorclassify(CLAUDE.mdsection 9). For B's mock tests,MockBrain(brain.go:223) already exists.Out of scope for this epic
Complexity routing, expectations, nudges, assistant or COS roles, debate mode, UI changes.
Plan of record
Definition of done
curlposts owner → request → claim → deliver into a test nest; SSE reconnect withLast-Event-IDreplays all four in order; with the mock brain all tests in the plan pass under-race; with a live key, a named crow posts an in-characterdeliverin a nest within 60 seconds of arequest.Sentry decision landed (#6): it becomes the nest watchdog, quarantining crows outside their contract (
flagmessage kind). Epic F gains: a Sentry-watchdog task beside COS spin-up.Definition of done walked 2026-10-28: