Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d89caf4af2 | ||
|
|
d45a8243c8 |
@@ -530,7 +530,11 @@ func considerIssue(src Source, org, repo string, issue Issue, comments []Comment
|
|||||||
case lastCommentBy == "":
|
case lastCommentBy == "":
|
||||||
reason = "no-commenter"
|
reason = "no-commenter"
|
||||||
}
|
}
|
||||||
if len(children) > 0 && anyOpen(children) {
|
if len(children) > 0 {
|
||||||
|
// 父追蹤項一律標 parent-tracking(agents #44,與 gitea.py 同步):
|
||||||
|
// 有 open 子項在推進時,父項留言閒置屬等待子項;子項全關閉時只剩
|
||||||
|
// 父項收尾(回報驗收並關閉),兩者都不是 assignee 停滯。統一標記
|
||||||
|
// 讓「父項收尾」規則能正確匹配,不退回通用原因(如 assignee-idle)。
|
||||||
reason = "parent-tracking"
|
reason = "parent-tracking"
|
||||||
}
|
}
|
||||||
item := Item{
|
item := Item{
|
||||||
@@ -606,15 +610,6 @@ func considerPull(src Source, org, repo string, pr PullRequest, comments []Comme
|
|||||||
return item, true
|
return item, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func anyOpen(children []Child) bool {
|
|
||||||
for _, c := range children {
|
|
||||||
if c.State == "open" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// round1 舍入到小數一位(對應 Python round(x, 1))。
|
// round1 舍入到小數一位(對應 Python round(x, 1))。
|
||||||
// 經 strconv 的十進位正確舍入(半偶數),與 Python 的浮點 round 行為一致,
|
// 經 strconv 的十進位正確舍入(半偶數),與 Python 的浮點 round 行為一致,
|
||||||
// 避免 (x*10+0.5) 截斷在 .x5 邊界產生偏差。
|
// 避免 (x*10+0.5) 截斷在 .x5 邊界產生偏差。
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ func (f *fakeSource) OrganizationRepositories(org string) ([]Repo, error) {
|
|||||||
func (f *fakeSource) OpenIssues(owner, repo string) ([]Issue, error) {
|
func (f *fakeSource) OpenIssues(owner, repo string) ([]Issue, error) {
|
||||||
var out []Issue
|
var out []Issue
|
||||||
for _, i := range f.issues[owner+"/"+repo] {
|
for _, i := range f.issues[owner+"/"+repo] {
|
||||||
|
if i.State == "closed" {
|
||||||
|
continue // 對齊真實 API:OpenIssues 只回 open;closed 條目僅供 TryGetIssue 解引用。
|
||||||
|
}
|
||||||
out = append(out, i)
|
out = append(out, i)
|
||||||
}
|
}
|
||||||
// 對齊真實 API:issues 依 id(=number)遞增回傳,消除 map 迭代隨機性。
|
// 對齊真實 API:issues 依 id(=number)遞增回傳,消除 map 迭代隨機性。
|
||||||
@@ -245,6 +248,46 @@ func TestScanStalledNudgeCooldown(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestScanStalledParentWrapup(teai #47,同步 agents #44):子項全關閉的父追蹤項
|
||||||
|
// 不退回通用原因(assignee-idle),一律標 parent-tracking——「父項收尾」情境。
|
||||||
|
func TestScanStalledParentWrapup(t *testing.T) {
|
||||||
|
now := at(0)
|
||||||
|
// 父項 3 最後留言來自 assignee ceo(舊行為會誤標 assignee-idle);
|
||||||
|
// 唯一子項 7 已關閉,父子最後活動皆 5 小時前。
|
||||||
|
src := &fakeSource{
|
||||||
|
orgs: []string{"alterminal"},
|
||||||
|
repos: map[string][]Repo{"alterminal": repoWith("teai", true)},
|
||||||
|
issues: map[string]map[int64]Issue{
|
||||||
|
"alterminal/teai": {
|
||||||
|
3: {Number: 3, Title: "父", State: "open", Body: "子項:#7", CreatedAt: iso(-700), UpdatedAt: iso(-300), Assignees: []User{{UserName: "ceo"}}, Repository: &Repository{FullName: "alterminal/teai"}},
|
||||||
|
7: {Number: 7, Title: "子", State: "closed", CreatedAt: iso(-650), UpdatedAt: iso(-300), Repository: &Repository{FullName: "alterminal/teai"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
comments: map[string][]Comment{
|
||||||
|
"alterminal/teai/3": {{User: &User{UserName: "ceo"}, CreatedAt: iso(-300)}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
got, err := ScanStalled(src, "admin", 4.0, now)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ScanStalled: %v", err)
|
||||||
|
}
|
||||||
|
var parent *Item
|
||||||
|
for i := range got {
|
||||||
|
if got[i].Number == 3 {
|
||||||
|
parent = &got[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if parent == nil {
|
||||||
|
t.Fatalf("父項 3 應列入(5h 無活動),got %v", got)
|
||||||
|
}
|
||||||
|
if parent.Reason != "parent-tracking" {
|
||||||
|
t.Errorf("子項全關閉的父項 reason = %q, want parent-tracking", parent.Reason)
|
||||||
|
}
|
||||||
|
if len(parent.ChildActivity) == 0 {
|
||||||
|
t.Errorf("父項 3 應附 child_activity,got %v", parent.ChildActivity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestScanStalledParentTracking 父追蹤項:子項活動計入 last_activity、reason 標記。
|
// TestScanStalledParentTracking 父追蹤項:子項活動計入 last_activity、reason 標記。
|
||||||
func TestScanStalledParentTracking(t *testing.T) {
|
func TestScanStalledParentTracking(t *testing.T) {
|
||||||
now := at(0)
|
now := at(0)
|
||||||
|
|||||||
Reference in New Issue
Block a user