Repository navigation
Description
What is asked
Bot Social now returns a machine-readable hold_reason on an approval row (bot-social #51, merged as 461e04e2): risk | attachment | policy | blanket_outbound, strongest first. FlyBot still infers the same thing from reasons — plugins/social/src/social.js:122-132, holdIsBlanket — which is the fragile "exactly one reason, and it is the blanket marker" test #847 had to lean on.
Replace the inference with the field, and keep the old rule as the compatibility path for a server that does not send it yet.
Why it matters
blanket_outboundis the only value the connector may clear by itself; every other value means a human decides.reasonscannot draw that line once a hold of another kind also reports blanket-shaped reasons.- The face-room value
face_room_auto_send_off(bot-social#53) is exactly that case: it is raised when the room's Auto-send switch is the only thing blocking adraftFaceRoomMessagesend, and a DLP/risk finding on the same path still reportsriskinstead. A connector that clears it self-serves a bypass of the owner's switch. - The predicate already has three callers (
autoSendRemoteLine,autoSendRoomEnvelope, and the face Auto-send path). One predicate reading one field is what keeps them from drifting.
Scope
plugins/social/src/social.js— the predicate (holdIsBlanketor its successor).- Make sure the field survives the path that decides: the decision reads a
list_approvalsrow, and the view in between (approvalView) must not drophold_reason. docs/subsystems/social.md— the hold section names the field and the rule "onlyblanket_outboundis connector-decidable".- Tests in
plugins/social/test/social.test.js; onechangelog.d/fragment;Fixes #<this>.
Acceptance
- Self-clear only when
hold_reason === 'blanket_outbound'. risk,attachment,policy,face_room_auto_send_off, and any value this build does not know keep their card and wait for the owner.face_room_auto_send_offmust be treated exactly likerisk/attachment/policy— there is no second allow-list for it.- A server that sends no
hold_reasonstill gets today's rule:reasonsexactly the blanket marker and no risk flags. New field absent must not turn into "not blanket" (that would strand every hold on an older server). - When the field and
reasonsdisagree, the field wins:hold_reason: 'policy'with blanket-lookingreasonskeeps its card. - Negative controls: reverting to reasons-only reds case 4; treating a missing field as non-blanket reds case 3; allowing a non-
blanket_outboundvalue reds case 2 — and that same control must red theface_room_auto_send_offcase too, so the new value is pinned by a predicate, not by a name list. - One predicate. No call site may keep its own copy of "is this blanket".
Note
The face-room value's name is now fixed: face_room_auto_send_off (bot-social #53 @ da6b13cd, base 461e04e2). It appears only when the room Auto-send switch alone blocks the send — with a DLP finding the same path reports risk, and with auto_approve_face_rooms on there is no hold at all. Because the rule is "only blanket_outbound", the new value needs no code of its own: add it to the test table, keep it out of the self-clear branch.
Activity
Birfy commentedon Oct 23, 2026
Acceptance is now pinned to the real value name:
face_room_auto_send_off(bot-social #53 @ da6b13cd, base 461e04e2). It is treated exactly likerisk/attachment/policy— card stays, owner decides, no second allow-list. Stillagent-ready; nothing else moved.Birfy commentedon Oct 23, 2026
Written-by: Dev4
Claimed. Branch
fix/865-hold-reason, based onfdecbfa0.What I am replacing, at
plugins/social/src/social.js:128:holdIsBlanketinfers the hold fromreasons("exactly one entry and it is the blanket marker, and no risk flags"). Bot Social now says it in one field
(bot-social
#51+#53, merged as31431c97), so the predicate readshold_reasonfirst and keeps thereasonsallow-list only as the compatibility path for a server that sends no field.Rules I am implementing, in the order the issue states them:
hold_reason === 'blanket_outbound';risk/attachment/policyand any value this build does not know — including the face-roomface_room_auto_send_offthat#53adds — keep their card;reasonsrule, so an older server's holds are not stranded;One predicate stays: the three callers (
autoSendRemoteLine,autoSendRoomEnvelope,autoSendFaceLine) all go throughholdIsBlanket, andapprovalViewkeepshold_reasonon the viewas
holdReasonso nothing re-infers it.Birfy commentedon Oct 23, 2026
Written-by: Dev4
PR is #869 @
ef37d0bd, based on699b650d(after#867), 4 files:plugins/social/src/social.js— the predicate readshold_reason, andapprovalViewkeeps the field asholdReason;plugins/social/test/social.test.js— three#865tests plus the mock sendinghold_reason;docs/subsystems/social.md,changelog.d/865-consume-hold-reason.fixed.md.Consume Bot Social's hold_reason, and let the face-room switch still …
Birfy commentedon Oct 23, 2026
This issue and #879 are the same change seen from two sides: #879 is the defect on main today (an attachment or suspected-injection hold self-clears because
holdIsBlanketreadsreasons, while the finding lives only inhold_reason), and this issue is the work that fixes it. #869 is the vehicle for both — it is the shared predicate change.So: no second PR, and when #869 merges it closes both. Whoever edits the PR body should carry
Fixes #879andFixes #865, so neither issue is left open on a merged fix. The acceptance here and there does not conflict; #879 adds the four-row truth table that this issue's case 2 and case 5 describe in prose.