Context
Per BT-06-001 and BT-15-001, protocol-significant state transitions and domain
object mutations MUST live in reusable BT leaf nodes/subtrees, not in use-case
execute() bodies or procedural helpers. Use cases should be infrastructure
glue only: construct the BT, set up the blackboard, execute through BTBridge,
inspect result, and surface errors.
Currently, several received-side use cases contain direct DataLayer/domain mutations:
AcceptInviteActorToCaseReceivedUseCase (received/actor/invite.py)
Directly creates a VultronParticipant, appends three RM state transitions
(RM.RECEIVED → RM.VALID → RM.ACCEPTED), records case events, saves the case,
and queues the outbox Announce. These are all protocol-significant operations.
Constraint: per PCR-08-010, the receiving use case MUST NOT run an engage-case
BT as the invitee actor (identity spoofing). The correct architecture is:
the receiving actor (the Case Actor) runs a BT as itself to record what
it is authorized to record in its own DataLayer — the new participant's state.
_ensure_reporter_participant() (received/case/_helpers.py)
Directly creates or upgrades a ParticipantStatus(rm_state=RM.ACCEPTED). This
is protocol-significant: it records the reporter's RM state transition. Should
move to a BT leaf node.
Acceptance Criteria
References
Context
Per BT-06-001 and BT-15-001, protocol-significant state transitions and domain
object mutations MUST live in reusable BT leaf nodes/subtrees, not in use-case
execute()bodies or procedural helpers. Use cases should be infrastructureglue only: construct the BT, set up the blackboard, execute through
BTBridge,inspect result, and surface errors.
Currently, several received-side use cases contain direct DataLayer/domain mutations:
AcceptInviteActorToCaseReceivedUseCase(received/actor/invite.py)Directly creates a
VultronParticipant, appends three RM state transitions(
RM.RECEIVED → RM.VALID → RM.ACCEPTED), records case events, saves the case,and queues the outbox Announce. These are all protocol-significant operations.
Constraint: per PCR-08-010, the receiving use case MUST NOT run an engage-case
BT as the invitee actor (identity spoofing). The correct architecture is:
the receiving actor (the Case Actor) runs a BT as itself to record what
it is authorized to record in its own DataLayer — the new participant's state.
_ensure_reporter_participant()(received/case/_helpers.py)Directly creates or upgrades a
ParticipantStatus(rm_state=RM.ACCEPTED). Thisis protocol-significant: it records the reporter's RM state transition. Should
move to a BT leaf node.
Acceptance Criteria
AcceptInviteActorToCaseReceivedUseCase.execute()delegatesparticipant creation, RM transitions, case events, and outbox work to BT
leaf nodes/subtrees via
BTBridge. The receiving actor runs the BT asitself (Case Actor identity), not as the invitee.
_ensure_reporter_participant()logic moves to a reusable BT leaf node.References