fix(docgov): reclaim orphan squad leases and align run_id

Use task run_id as doc lease holder so release tracks execution, and reclaim squad locks when the holder run is missing or no longer running.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-13 03:32:20 +00:00
co-authored by Cursor
parent 0c5256c60c
commit 3e242e6d36
2 changed files with 32 additions and 2 deletions
+4 -1
View File
@@ -538,7 +538,10 @@ func (s *Service) ExecuteTask(ctx context.Context, req TaskRunRequest) (*TaskRun
}
// 通过权限检查后获取小队编辑租约(提案拦截路径不持锁)
leaseHolderID = fmt.Sprintf("run_%d", time.Now().UnixNano())
leaseHolderID = strings.TrimSpace(req.RunID)
if leaseHolderID == "" {
leaseHolderID = fmt.Sprintf("run_%d", time.Now().UnixNano())
}
leaseTTL := req.Timeout
if leaseTTL <= 0 && s.cfg != nil {
leaseTTL = s.cfg.AgentTimeout
+28 -1
View File
@@ -67,7 +67,14 @@ func (e *GovernanceEngine) AcquireLease(ctx context.Context, req LeaseAcquireReq
if doc.HasActiveLease(now) {
sameHolder := doc.LeaseHolderType == req.HolderType && doc.LeaseHolderID == req.HolderID
if !sameHolder {
if !sameHolder && req.HolderType == LeaseHolderSquad && e.shouldReclaimSquadLease(ctx, doc) {
e.appendAuditLocked(doc, "lease_reclaim_orphan", 0, string(req.HolderType), RoleSystem, map[string]any{
"previous_holder_type": doc.LeaseHolderType,
"previous_holder_id": doc.LeaseHolderID,
})
doc.ClearLease()
e.persistLeaseLocked(ctx, doc)
} else if !sameHolder {
e.appendAuditLocked(doc, "lease_deny", 0, string(req.HolderType), RoleSystem, map[string]any{
"requester_type": req.HolderType,
"requester_id": req.HolderID,
@@ -173,6 +180,26 @@ func (e *GovernanceEngine) HeartbeatLease(ctx context.Context, docID, holderType
return doc, nil
}
// shouldReclaimSquadLease 当 squad 租约 holder 无对应 running task_run 时视为孤儿锁并回收。
func (e *GovernanceEngine) shouldReclaimSquadLease(ctx context.Context, doc *DocumentRecord) bool {
if doc == nil || doc.LeaseHolderType != LeaseHolderSquad {
return false
}
holderID := strings.TrimSpace(doc.LeaseHolderID)
if holderID == "" || !strings.HasPrefix(holderID, "run_") {
return false
}
if e.pool == nil {
return false
}
var status string
err := e.pool.QueryRow(ctx, `SELECT status FROM task_runs WHERE run_id = $1`, holderID).Scan(&status)
if err != nil {
return true
}
return status != "running"
}
// AssertWritableForComment 批注前检查:有效 edit lease 期间禁止批注
func (e *GovernanceEngine) AssertWritableForComment(ctx context.Context, docID string) error {
e.mu.Lock()