D4: ask_owner kind + fail-safe resolution #41

Closed
opened 2026-10-28 13:42:51 +00:00 by jacisjake · 0 comments
jacisjake commented 2026-10-28 13:42:51 +00:00 (Migrated from github.com)

Epic: #36. Depends on: #38

Goal

ask_owner becomes a real message kind (already in CHATROOM_SPEC section 4; add to EVENTS.md kind table first): a decision only the owner can make. It carries an exact approval_phrase; resolution happens only on the owner's reply matching that phrase (fail safe: anything else, including silence/timeout, is not a yes). Quill uses it when asked to decide something it must not decide alone.

Acceptance criteria — falsifiable tests

  1. TestAskOwnerPostedAndSurfaced (askowner_test.go) — Given a nest, when a crow (or the harness) posts kind: "ask_owner", to: "owner" with text and approval_phrase, then 201, the record appears in GET /api/nests/{id}/messages with approval_phrase, and SSE emits it. Red now: kind validation rejects ask_owner (not in the kind set).
  2. TestAskOwnerOnlyOwnerResolves — When another crow replies with the exact approval phrase, no resolution is recorded; when the owner replies with it, a resolution message appears (kind say, author owner, refers_to the ask_owner id) and GET shows the ask resolved.
  3. TestAskOwnerWrongPhraseStaysOpen — Owner replies "sounds good" without the exact phrase: ask stays unresolved (no resolution message).
  4. TestAskOwnerTimeoutFailSafe — With an injected short timeout (constructor-level, not wall-clock: use a time.go style clock or channel the test controls), an unanswered ask_owner is auto-resolved as rejected after the approval window (reuse the 10-minute timeout convention from approve.go, parameterized for tests).
  5. Crow-postable kinds still exclude ask_owner for header tagging (only harness/Quill/Sentry paths post it — assert POST with author crow and header ask_owner gets retagged).

Test command

go test -race -count=1 -run 'TestAskOwner' .

Blockers / unknowns

Approve.go's WebApprover is the pipeline's approval channel; the chatroom ask_owner must live in the nest log itself (owner resolves by replying in the nest) — do not wire it to WebApprover. This is the shared mechanism Epic E (#watchdog) builds on.

Epic: #36. Depends on: #38 ## Goal `ask_owner` becomes a real message kind (already in CHATROOM_SPEC section 4; add to EVENTS.md kind table first): a decision only the owner can make. It carries an exact `approval_phrase`; resolution happens only on the owner's reply matching that phrase (fail safe: anything else, including silence/timeout, is not a yes). Quill uses it when asked to decide something it must not decide alone. ## Acceptance criteria — falsifiable tests 1. `TestAskOwnerPostedAndSurfaced` (`askowner_test.go`) — Given a nest, when a crow (or the harness) posts `kind: "ask_owner", to: "owner"` with text and `approval_phrase`, then 201, the record appears in `GET /api/nests/{id}/messages` with `approval_phrase`, and SSE emits it. Red now: kind validation rejects `ask_owner` (not in the kind set). 2. `TestAskOwnerOnlyOwnerResolves` — When another crow replies with the exact approval phrase, no resolution is recorded; when the owner replies with it, a resolution message appears (kind `say`, author `owner`, `refers_to` the ask_owner id) and `GET` shows the ask resolved. 3. `TestAskOwnerWrongPhraseStaysOpen` — Owner replies "sounds good" without the exact phrase: ask stays unresolved (no resolution message). 4. `TestAskOwnerTimeoutFailSafe` — With an injected short timeout (constructor-level, not wall-clock: use a `time.go` style clock or channel the test controls), an unanswered ask_owner is auto-resolved as rejected after the approval window (reuse the 10-minute timeout convention from approve.go, parameterized for tests). 5. Crow-postable kinds still exclude `ask_owner` for header tagging (only harness/Quill/Sentry paths post it — assert POST with author crow and header `ask_owner` gets retagged). ## Test command `go test -race -count=1 -run 'TestAskOwner' .` ## Blockers / unknowns Approve.go's WebApprover is the pipeline's approval channel; the chatroom ask_owner must live in the nest log itself (owner resolves by replying in the nest) — do not wire it to WebApprover. This is the shared mechanism Epic E (#watchdog) builds on.
Sign in to join this conversation.