fix:stalled 分類同步 agents#47——assignee 交付報告待確認改判 waiting-outside
與 agents 86f570a(PR alterminal/agents#48)同語義:最後一則 assignee 留言符合交付報告特徵(結構訊號:逐項查核/驗收結果、彙總 verdict、內文 含「完成定義」段落時簡式交付語也算;∧ 交棒訊號:回報/關閉他件 #N、 或請/可由/待他人確認關閉)時,assignee-idle 改判 waiting-outside。 兩訊號同時命中才翻轉:認領/進度/預告式留言(無交棒對象)保持 assignee-idle,不製造「認領後棄置永不被催」的新死角。 驗證:TestIsDeliveryReport(8 案例,與 gitea.py 離線驗證同集)+ TestScanStalledDeliveryReport(stalled 整合:交付報告翻轉、認領不翻轉) +全套 go test 綠;live A/B 對安裝版二進位:bear#52 assignee-idle → waiting-outside,bear#39 parent-tracking 不變。
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
package workflow
|
||||
|
||||
import "sort"
|
||||
import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// sortComments 依 created_at 字典序穩定排序(ISO8601 字串字典序與時間序一致),
|
||||
// 對應 gitea.py 各處的 comments.sort(key=created_at)。
|
||||
@@ -135,3 +139,65 @@ func LastCommentNotByAssignee(issue *Issue, comments []Comment) bool {
|
||||
func IssueNeedsWork(issue *Issue, comments []Comment, members []string) bool {
|
||||
return AssigneeOverlaps(issue, members) && LastCommentNotByAssignee(issue, comments)
|
||||
}
|
||||
|
||||
// ── 交付報告判定(agents #47,同步 gitea.py _is_delivery_report)──────────
|
||||
//
|
||||
// 最後一則 assignee 留言已把工作交棒給發起人/他人確認(逐項查核/驗收
|
||||
// 結果+回報他件或請確認關閉)時,停滯點不在 assignee:stalled 分類由
|
||||
// assignee-idle 改判 waiting-outside,管理者巡邏不再對已交付、待確認的
|
||||
// 處理者觸發自動催促。
|
||||
|
||||
var (
|
||||
// deliveryVerdictRe 對應 gitea.py _DELIVERY_VERDICT_RE:彙總 verdict 語。
|
||||
deliveryVerdictRe = regexp.MustCompile(`(全數|全部|\d+\s*項)通過|項全過|不通過|未通過`)
|
||||
// deliveryHandoffRe 對應 gitea.py _DELIVERY_HANDOFF_RE:交棒訊號。
|
||||
deliveryHandoffRe = regexp.MustCompile(`回報\s*#\d+|關閉\s*#\d+|請[^\n。]{0,40}(確認|關閉)|可由[^\n。]{0,40}關閉|待[^\n。]{0,20}確認`)
|
||||
// completionDefinitionRe 對應 _has_completion_definition:內文「完成定義」
|
||||
// 段落(ATX 標題或行首字樣)。
|
||||
completionDefinitionRe = regexp.MustCompile(`(?m)^#{1,6}\s*完成定義|^完成定義\s*[::]?`)
|
||||
// simpleDeliveryRe 內文有「完成定義」時的簡式交付語。
|
||||
simpleDeliveryRe = regexp.MustCompile(`已完成|已交付|已通過|已全數`)
|
||||
)
|
||||
|
||||
// hasCompletionDefinition 內文是否含「完成定義」段落。
|
||||
func hasCompletionDefinition(body string) bool {
|
||||
return completionDefinitionRe.MatchString(body)
|
||||
}
|
||||
|
||||
// IsDeliveryReport 判定最後一則 assignee 留言是否符合交付報告特徵
|
||||
// (agents #47;gitea.py _is_delivery_report 的同語義實作)。
|
||||
//
|
||||
// 交付報告=「結構訊號」∧「交棒訊號」同時命中:
|
||||
// - 結構訊號:逐項查核/驗收/測試結果、結論、或彙總 verdict 語;內文有
|
||||
// 「完成定義」段落時,簡式交付語(已完成/已交付)也算。
|
||||
// - 交棒訊號:回報/關閉他件(#N)、或請/可由/待他人確認關閉。
|
||||
//
|
||||
// 只命中結構訊號不算:認領/進度/預告式留言(「完成後逐項回報結果至此」)
|
||||
// 沒有交棒對象,仍是 assignee 自己該做——保持 assignee-idle,修正不製造
|
||||
// 「認領後棄置永不被催促」的新死角。
|
||||
func IsDeliveryReport(issueBody string, last *Comment) bool {
|
||||
if last == nil {
|
||||
return false
|
||||
}
|
||||
body := last.Body
|
||||
if body == "" {
|
||||
return false
|
||||
}
|
||||
structural := false
|
||||
for _, marker := range []string{"查核結果", "驗收結果", "測試結果", "逐項", "結論", "完成定義"} {
|
||||
if strings.Contains(body, marker) {
|
||||
structural = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !structural && deliveryVerdictRe.MatchString(body) {
|
||||
structural = true
|
||||
}
|
||||
if !structural && hasCompletionDefinition(issueBody) && simpleDeliveryRe.MatchString(body) {
|
||||
structural = true
|
||||
}
|
||||
if !structural {
|
||||
return false
|
||||
}
|
||||
return deliveryHandoffRe.MatchString(body)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user