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
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).
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.
TestAskOwnerWrongPhraseStaysOpen — Owner replies "sounds good" without the exact phrase: ask stays unresolved (no resolution message).
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).
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.
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.
Epic: #36. Depends on: #38
Goal
ask_ownerbecomes 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 exactapproval_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
TestAskOwnerPostedAndSurfaced(askowner_test.go) — Given a nest, when a crow (or the harness) postskind: "ask_owner", to: "owner"with text andapproval_phrase, then 201, the record appears inGET /api/nests/{id}/messageswithapproval_phrase, and SSE emits it. Red now: kind validation rejectsask_owner(not in the kind set).TestAskOwnerOnlyOwnerResolves— When another crow replies with the exact approval phrase, no resolution is recorded; when the owner replies with it, a resolution message appears (kindsay, authorowner,refers_tothe ask_owner id) andGETshows the ask resolved.TestAskOwnerWrongPhraseStaysOpen— Owner replies "sounds good" without the exact phrase: ask stays unresolved (no resolution message).TestAskOwnerTimeoutFailSafe— With an injected short timeout (constructor-level, not wall-clock: use atime.gostyle 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).ask_ownerfor header tagging (only harness/Quill/Sentry paths post it — assert POST with author crow and headerask_ownergets 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.