feat(slot): Add merge-slot gate for serialized conflict resolution
Adds a new slot bead type and merge-slot commands for serializing conflict resolution in the merge queue. This prevents "monkey knife fights" where multiple polecats race to resolve conflicts. - Add TypeSlot to bead types - Add Holder field to Issue struct - Add bd merge-slot create/check/acquire/release commands - Add Holder field to UpdateArgs in RPC protocol (gt-4u49x) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -164,6 +164,8 @@ type UpdateArgs struct {
|
||||
// Gate fields
|
||||
AwaitID *string `json:"await_id,omitempty"` // Condition identifier for gates (run ID, PR number, etc.)
|
||||
Waiters []string `json:"waiters,omitempty"` // Mail addresses to notify when gate clears
|
||||
// Slot fields
|
||||
Holder *string `json:"holder,omitempty"` // Who currently holds the slot (for type=slot beads)
|
||||
}
|
||||
|
||||
// CloseArgs represents arguments for the close operation
|
||||
|
||||
@@ -142,6 +142,10 @@ func updatesFromArgs(a UpdateArgs) map[string]interface{} {
|
||||
if len(a.Waiters) > 0 {
|
||||
u["waiters"] = a.Waiters
|
||||
}
|
||||
// Slot fields
|
||||
if a.Holder != nil {
|
||||
u["holder"] = *a.Holder
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,9 @@ type Issue struct {
|
||||
Timeout time.Duration `json:"timeout,omitempty"` // Max wait time before escalation
|
||||
Waiters []string `json:"waiters,omitempty"` // Mail addresses to notify when gate clears
|
||||
|
||||
// ===== Slot Fields (exclusive access primitives) =====
|
||||
Holder string `json:"holder,omitempty"` // Who currently holds the slot (empty = available)
|
||||
|
||||
// ===== Source Tracing Fields (formula cooking origin) =====
|
||||
SourceFormula string `json:"source_formula,omitempty"` // Formula name where step was defined
|
||||
SourceLocation string `json:"source_location,omitempty"` // Path: "steps[0]", "advice[0].after"
|
||||
@@ -163,6 +166,9 @@ func (i *Issue) ComputeContentHash() string {
|
||||
w.str(waiter)
|
||||
}
|
||||
|
||||
// Slot fields for exclusive access
|
||||
w.str(i.Holder)
|
||||
|
||||
// Agent identity fields
|
||||
w.str(i.HookBead)
|
||||
w.str(i.RoleBead)
|
||||
@@ -413,12 +419,13 @@ const (
|
||||
TypeRole IssueType = "role" // Agent role definition
|
||||
TypeConvoy IssueType = "convoy" // Cross-project tracking with reactive completion
|
||||
TypeEvent IssueType = "event" // Operational state change record
|
||||
TypeSlot IssueType = "slot" // Exclusive access slot (merge-slot gate)
|
||||
)
|
||||
|
||||
// IsValid checks if the issue type value is valid
|
||||
func (t IssueType) IsValid() bool {
|
||||
switch t {
|
||||
case TypeBug, TypeFeature, TypeTask, TypeEpic, TypeChore, TypeMessage, TypeMergeRequest, TypeMolecule, TypeGate, TypeAgent, TypeRole, TypeConvoy, TypeEvent:
|
||||
case TypeBug, TypeFeature, TypeTask, TypeEpic, TypeChore, TypeMessage, TypeMergeRequest, TypeMolecule, TypeGate, TypeAgent, TypeRole, TypeConvoy, TypeEvent, TypeSlot:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user