Quarantine escalates, never hard-kills: on flag, the Sentry opens an ask_owner ("Reinstate Hugin" with exact approval phrase reinstate Hugin). Owner's exact phrase lifts quarantine; anything else — wrong phrase, other crows' replies, timeout — keeps it (fail safe). Sentry's own watch record moves: a reinstate (explicit yes) counts as an approval for Sentry|triage/watch; a timeout that keeps the quarantine counts as nothing (no penalty, pattern from spec §10: misses don't move trust). An explicit retire Hugin phrase removes the crow from the registry/nests (persona crows: removed from nest membership only; the persona itself never dies).
Acceptance criteria — falsifiable tests
TestQuarantineOpensAskOwner — after E3's flag path fires, an ask_owner from Sentry exists with to: "owner", refers_to the flag, and approval_phrase: "reinstate <crow>". Red now: flag posts without escalation.
TestReinstateOnlyOnExactYes — owner replying reinstate Hugin lifts quarantine: next claim POST returns 201; owner replying let him back keeps the 403.
TestAskOwnerTimeoutKeepsQuarantine — unresolved ask (injected short timeout from D4's mechanism) leaves the crow quarantined; nothing else changes (assert flag and 403 still in effect).
TestRetireRemovesCrow — owner reply retire Hugin (the ask offers reinstate-or-retire both as exact phrases): Hugin removed from the nest's membership and cannot claim (registry crow would be deleted — assert the nest membership case for persona crow, registry case for spun crow).
TestWatchTrustMoves — after a reinstate approval, ReadLedger shows Sentry|triage/watch with Approved 1 / Streak 1; after a wrong-phrase reply, unchanged.
EVENTS.md first: ask_owner row (from D4) gains the reinstate|retire <crow> usage note; the SSE event names land before the server.
Test command
go test -race -count=1 -run 'TestQuarantine|TestReinstate|TestRetire|TestWatch' .
Blockers / unknowns
Two exact phrases per ask (reinstate/retire) or one ask resolved by either? Spec: "brings an ask_owner to reinstate or retire" — a single ask carrying both phrases; resolution by whichever exact phrase the owner uses first.
Epic: #37. Depends on: #44, Epic D ask_owner task
## Goal
Quarantine escalates, never hard-kills: on flag, the Sentry opens an `ask_owner` ("Reinstate Hugin" with exact approval phrase `reinstate Hugin`). Owner's exact phrase lifts quarantine; anything else — wrong phrase, other crows' replies, timeout — keeps it (fail safe). Sentry's own watch record moves: a reinstate (explicit yes) counts as an approval for `Sentry|triage/watch`; a timeout that keeps the quarantine counts as nothing (no penalty, pattern from spec §10: misses don't move trust). An explicit `retire Hugin` phrase removes the crow from the registry/nests (persona crows: removed from nest membership only; the persona itself never dies).
## Acceptance criteria — falsifiable tests
1. `TestQuarantineOpensAskOwner` — after E3's flag path fires, an `ask_owner` from Sentry exists with `to: "owner"`, `refers_to` the flag, and `approval_phrase: "reinstate <crow>"`. Red now: flag posts without escalation.
2. `TestReinstateOnlyOnExactYes` — owner replying `reinstate Hugin` lifts quarantine: next claim POST returns 201; owner replying `let him back` keeps the 403.
3. `TestAskOwnerTimeoutKeepsQuarantine` — unresolved ask (injected short timeout from D4's mechanism) leaves the crow quarantined; nothing else changes (assert flag and 403 still in effect).
4. `TestRetireRemovesCrow` — owner reply `retire Hugin` (the ask offers reinstate-or-retire both as exact phrases): Hugin removed from the nest's membership and cannot claim (registry crow would be deleted — assert the nest membership case for persona crow, registry case for spun crow).
5. `TestWatchTrustMoves` — after a reinstate approval, `ReadLedger` shows `Sentry|triage/watch` with Approved 1 / Streak 1; after a wrong-phrase reply, unchanged.
6. EVENTS.md first: ask_owner row (from D4) gains the `reinstate|retire <crow>` usage note; the SSE event names land before the server.
## Test command
`go test -race -count=1 -run 'TestQuarantine|TestReinstate|TestRetire|TestWatch' .`
## Blockers / unknowns
Two exact phrases per ask (reinstate/retire) or one ask resolved by either? Spec: "brings an ask_owner to reinstate or retire" — a single ask carrying both phrases; resolution by whichever exact phrase the owner uses first.
Implementation notes from #53 (within the decided design, flagged as small deviations):
Server.askTimeout became an atomic.Int64 (nanos). The field is read on every GET/SSE handler goroutine and on the watchdog's ask-emit path; a plain test write while the server runs trips the race detector (askowner_test's write site updated to the Store API).
The quarantine 403 gate now runs before the nest-membership check, so a retired-but-still-quarantined persona crow reads 403 rather than 400 (documented in the EVENTS.md guardrails line).
The reinstate/retire ask opens only when the flag append succeeds; quarantine itself is unchanged in that edge.
Implementation notes from #53 (within the decided design, flagged as small deviations):
- `Server.askTimeout` became an `atomic.Int64` (nanos). The field is read on every GET/SSE handler goroutine and on the watchdog's ask-emit path; a plain test write while the server runs trips the race detector (askowner_test's write site updated to the Store API).
- The quarantine 403 gate now runs before the nest-membership check, so a retired-but-still-quarantined persona crow reads 403 rather than 400 (documented in the EVENTS.md guardrails line).
- The reinstate/retire ask opens only when the flag append succeeds; quarantine itself is unchanged in that edge.
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: #37. Depends on: #44, Epic D ask_owner task
Goal
Quarantine escalates, never hard-kills: on flag, the Sentry opens an
ask_owner("Reinstate Hugin" with exact approval phrasereinstate Hugin). Owner's exact phrase lifts quarantine; anything else — wrong phrase, other crows' replies, timeout — keeps it (fail safe). Sentry's own watch record moves: a reinstate (explicit yes) counts as an approval forSentry|triage/watch; a timeout that keeps the quarantine counts as nothing (no penalty, pattern from spec §10: misses don't move trust). An explicitretire Huginphrase removes the crow from the registry/nests (persona crows: removed from nest membership only; the persona itself never dies).Acceptance criteria — falsifiable tests
TestQuarantineOpensAskOwner— after E3's flag path fires, anask_ownerfrom Sentry exists withto: "owner",refers_tothe flag, andapproval_phrase: "reinstate <crow>". Red now: flag posts without escalation.TestReinstateOnlyOnExactYes— owner replyingreinstate Huginlifts quarantine: next claim POST returns 201; owner replyinglet him backkeeps the 403.TestAskOwnerTimeoutKeepsQuarantine— unresolved ask (injected short timeout from D4's mechanism) leaves the crow quarantined; nothing else changes (assert flag and 403 still in effect).TestRetireRemovesCrow— owner replyretire Hugin(the ask offers reinstate-or-retire both as exact phrases): Hugin removed from the nest's membership and cannot claim (registry crow would be deleted — assert the nest membership case for persona crow, registry case for spun crow).TestWatchTrustMoves— after a reinstate approval,ReadLedgershowsSentry|triage/watchwith Approved 1 / Streak 1; after a wrong-phrase reply, unchanged.reinstate|retire <crow>usage note; the SSE event names land before the server.Test command
go test -race -count=1 -run 'TestQuarantine|TestReinstate|TestRetire|TestWatch' .Blockers / unknowns
Two exact phrases per ask (reinstate/retire) or one ask resolved by either? Spec: "brings an ask_owner to reinstate or retire" — a single ask carrying both phrases; resolution by whichever exact phrase the owner uses first.
Implementation notes from #53 (within the decided design, flagged as small deviations):
Server.askTimeoutbecame anatomic.Int64(nanos). The field is read on every GET/SSE handler goroutine and on the watchdog's ask-emit path; a plain test write while the server runs trips the race detector (askowner_test's write site updated to the Store API).