From 8ce8f410edba693b2a96b8b5be85cbbd59012af0 Mon Sep 17 00:00:00 2001 From: chenyunda218 Date: Sun, 4 Oct 2026 08:25:55 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AF=A9=E6=A0=B8=E4=BA=A4=E6=A3=92?= =?UTF-8?q?=E8=A4=87=E5=90=88=E8=A8=8A=E8=99=9F=E2=80=94=E2=80=94=E7=AD=89?= =?UTF-8?q?=E5=80=99=E5=AF=A9=E6=A0=B8/=E8=AB=8B=E5=90=88=E4=BD=B5?= =?UTF-8?q?=E5=BD=A2=E6=85=8B=E4=B8=8D=E5=86=8D=E8=AA=A4=E5=88=A4=20author?= =?UTF-8?q?-idle=EF=BC=88agents=20#53=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #51 的三就緒詞漏掉「等候審核」形態:alterminal#2 作者留言「無待修改 項目…等候 @chenyunda218 審核…請直接合併」實質已交棒,仍誤判 author-idle,巡邏回頭催已無待辦的作者。 IsReviewHandoff 改複合訊號:@目前審核者 ∧(就緒語 ∨(完成語 ∧ 等候語))。就緒語補「請…審核」;等候語=等候/等待…審核、待審、 請…合併(間距容 @帳號);完成語=已完成/無待修改等。新增防護: 預告式(即將/稍後/之後/預計…、條件句「…後請審核」)與百分比進度 (完成 80%)一律不算——作者自述還沒到位不能解讀成已交棒;句讀阻斷 避免誤傷「合併後,我會回報」真交棒尾巴,「後續」除外。 gitea.py _is_review_handoff 同步(另 PR);測試案例兩側同集 (fox#60、alterminal#2 實例+17 個邊界)。 --- README.md | 12 ++++--- internal/workflow/judge.go | 58 ++++++++++++++++++++++++++++----- internal/workflow/judge_test.go | 19 +++++++++-- 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 72eaaa4..27d2f9a 100644 --- a/README.md +++ b/README.md @@ -242,11 +242,13 @@ PR 改帶 `author` 與 `reviewers` 欄位。`reason` 取值: 改判 `waiting-outside`——已交付待發起人確認不是 assignee 停滯。認領/進度/預告式 留言(無交棒對象)維持 `assignee-idle`,不製造「認領後棄置永不被催」的新死角。 -`author-idle` 判定前會先檢查 PR 作者的最後一則留言是否為**審核交棒**(agents #51): -@目前審核者帳號 ∧ 就緒語(已就緒/可審閱/請審閱)同時命中 → 改判 `reviewer-idle` -——作者已表明就緒並點名審核者,球在審核者,讓既有 reviewer 催促與 48 小時改派規則 -自然適用。@的帳號必須在目前審核者清單且為完整匹配(@chenyunda218 不算提及 -chenyunda);僅就緒語而無點名對象(進度回報、預告式)維持 `author-idle`。 +`author-idle` 判定前會先檢查 PR 作者的最後一則留言是否為**審核交棒**(agents #51、#53): +@目前審核者帳號 ∧ 交棒訊號(就緒語 ∨(完成語 ∧ 等候語))同時命中 → 改判 `reviewer-idle` +——作者已表明就緒(或已完成+等候審核,如 alterminal#2「無待修改項目…等候 @審核者 審核… +請直接合併」)、點名審核者,球在審核者,讓既有 reviewer 催促與 48 小時改派規則自然適用。 +@的帳號必須在目前審核者清單且為完整匹配(@chenyunda218 不算提及 chenyunda);預告式 +(「即將就緒」「之後再審」「實作完成後請審核」)與百分比進度(「已完成 80%」)不算; +僅就緒語而無點名對象(進度回報)維持 `author-idle`。 ### `teai milestones` — 跨倉庫里程碑總覽 diff --git a/internal/workflow/judge.go b/internal/workflow/judge.go index cdf2274..cc2f546 100644 --- a/internal/workflow/judge.go +++ b/internal/workflow/judge.go @@ -202,27 +202,69 @@ func IsDeliveryReport(issueBody string, last *Comment) bool { return deliveryHandoffRe.MatchString(body) } -// ── 審核交棒判定(agents #51,同步 gitea.py _is_review_handoff)────────── +// ── 審核交棒判定(agents #51、#53,同步 gitea.py _is_review_handoff)────── // // PR 作者的最後一則留言已把審核交棒給審核者(@審核者帳號+就緒語)時, // 停滯點不在作者:stalled 分類由 author-idle 改判 reviewer-idle,既有 // 48 小時改派規則自然適用。案例:fox#60 作者留言「PR 已就緒,可審閱」 // 並 @chenyunda218,teai stalled 仍判 author-idle——作者已無待辦。 +// #53 補遺:alterminal#2 作者留言「等候 @chenyunda218 審核…無待修改 +// 項目…請直接合併」——實質已交棒但無三就緒詞,仍誤判 author-idle。 var ( // reviewReadyRe 對應 gitea.py _REVIEW_READY_RE:PR 端就緒語。 - reviewReadyRe = regexp.MustCompile(`已就緒|可審閱|請審閱`) + reviewReadyRe = regexp.MustCompile(`已就緒|可審閱|請審閱|請[^,。;\n]{0,8}審核`) + // reviewWaitMergeRe 對應 gitea.py _REVIEW_WAIT_MERGE_RE:等候審核語 + //(#53)——「等候/等待…審核」「待審」與「請…合併」形態。R2/R3 允許 + // @帳號夾在中間(「等候 @chenyunda218 審核」),故不含 @; + // 「即將/稍後…」的請求不合併語義,由前瞻防護 reviewHedgeRe 排除。 + reviewWaitMergeRe = regexp.MustCompile(`(等候|等待)[^,。;\n]{0,12}(審核|審閱|review)|待審|請[^,。;\n]{0,20}合併`) + // reviewDoneRe 對應 gitea.py _REVIEW_DONE_RE:完成語(#53)—— + // 作者自述 PR 內容已完成/無待辦。 + reviewDoneRe = regexp.MustCompile(`已完成|已完成實作|全數完成|已完成全部|完成[^,。;\n]{0,6}(修改|調整|實作|更新)|無待修改|無待辦|沒有.{0,4}待修改|不再有.{0,4}待修改`) + // reviewPercentRe 對應 gitea.py _REVIEW_PERCENT_RE:百分比進度 + //(#53)——「完成 80%」「已完成 90%」是進度回報,不是完成;命中時 + // 整則留言視為未交棒(保守:作者仍有待辦,維持 author-idle)。 + reviewPercentRe = regexp.MustCompile(`完成[^,。;\n]{0,6}[0-90-9]{1,3}\s*[%%]`) + // reviewHedgeRe 對應 gitea.py _REVIEW_HEDGE_RE:預告式防護(#51 既有 + // 精神+#53 擴詞彙後更顯重要)——「即將/稍後/之後/預計+就緒/審核/ + // review/完成/合併」與條件句「…後請審核/合併」(「實作完成後請審核」) + // 的前瞻字眼。命中時就緒語/等候語一律不算,保持 author-idle:作者 + // 自己說還沒到位,不能解讀成已交棒。句讀(,。;)阻斷間距,避免 + // 「合併後,我會回報」這類真交棒尾巴被誤傷;「後」後接「續」除外 + //(「已完成修改,後續請審核」——完成已發生,非條件句)。 + reviewHedgeRe = regexp.MustCompile(`(即將|稍後|之後|預計)[^,。;\n]{0,10}(就緒|審核|審閱|review|完成|合併)|後[^續,。;\n]{0,4}(審核|審閱|合併|review|就緒)`) ) +// isReviewHandoffSignal 判定留言文字是否命中交棒訊號(#53 複合訊號): +// +// 就緒語 ∨(完成語 ∧ 等候語) +// +// 兩路徑都先過防護:預告式(reviewHedgeRe)與百分比進度(reviewPercentRe) +// 命中時一律不算,保持 author-idle——作者自己說還沒到位/還在做,不能解讀 +// 成已交棒。等候語與完成語同現才算:仍在實作的進度回報(「實作完成後請 +// 審核」是條件句、無完成自述)不誤傷。 +func isReviewHandoffSignal(body string) bool { + if reviewHedgeRe.MatchString(body) || reviewPercentRe.MatchString(body) { + return false + } + if reviewReadyRe.MatchString(body) { + return true + } + return reviewDoneRe.MatchString(body) && reviewWaitMergeRe.MatchString(body) +} + // IsReviewHandoff 判定 PR 作者的最後一則留言是否已把審核交棒給審核者 -// (agents #51;gitea.py _is_review_handoff 的同語義實作)。 +// (agents #51、#53;gitea.py _is_review_handoff 的同語義實作)。 // -// 審核交棒=「@審核者帳號」∧「就緒語」同時命中:作者已表明 PR 就緒、 -// 明確點名目前指定的審核者,球在審核者——author-idle 改判 reviewer-idle。 +// 審核交棒=「@審核者帳號」∧「交棒訊號」同時命中:作者已表明 PR 就緒 +// (或已完成+等候審核)、明確點名目前指定的審核者,球在審核者—— +// author-idle 改判 reviewer-idle。 // -// 只命中就緒語不算:進度回報(「快好了,即將就緒」)沒有點名對象,作者 +// 只命中訊號不算:進度回報(「快好了,即將就緒」)沒有點名對象,作者 // 仍可能有待辦——保持 author-idle,修正不製造「丟一句已就緒就永不被催」 -// 的新死角。@的帳號不在目前審核者清單也不算:交棒對象需為實際審核者。 +// 的新死角。預告式(「即將就緒」「之後再審」)由 reviewHedgeRe 排除。 +// @的帳號不在目前審核者清單也不算:交棒對象需為實際審核者。 func IsReviewHandoff(last *Comment, reviewers []string) bool { if last == nil { return false @@ -231,7 +273,7 @@ func IsReviewHandoff(last *Comment, reviewers []string) bool { if body == "" || len(reviewers) == 0 { return false } - if !reviewReadyRe.MatchString(body) { + if !isReviewHandoffSignal(body) { return false } for _, r := range reviewers { diff --git a/internal/workflow/judge_test.go b/internal/workflow/judge_test.go index a58ce1a..9f4b4da 100644 --- a/internal/workflow/judge_test.go +++ b/internal/workflow/judge_test.go @@ -180,11 +180,15 @@ func TestIsDeliveryReport(t *testing.T) { } } -// TestIsReviewHandoff(agents #51):審核交棒=@審核者帳號 ∧ 就緒語。 -// 案例與 gitea.py _is_review_handoff 的離線驗證同集(fox#60 實例)。 +// TestIsReviewHandoff(agents #51、#53):審核交棒=@審核者帳號 ∧ 交棒訊號 +// (就緒語 ∨(完成語 ∧ 等候語))。案例與 gitea.py _is_review_handoff 的 +// 離線驗證同集(fox#60、alterminal#2 實例)。 func TestIsReviewHandoff(t *testing.T) { // fox#60 作者(alex)最後留言結尾(2026-09-16 08:05)。 fox60 := "狀態回報(作者端自查,分支無需再變更):\n\n- 已重新核對分支與 main 的差異…\n- PR 分支 CI 已通過(run 209)。\n\n@chenyunda218 PR 已就緒,可審閱。@ceo 已知悉管理者巡邏的備註;審核合併後,我會在下一個 main 部署 run 跑通時回 #58 驗收。" + // alterminal#2 作者(alex)最後留言節錄(2026-10-04 03:06,#53 案例): + // 有 @審核者+完成回報+「等候審核」+「請直接合併」,但無 #51 三就緒詞。 + al2 := "狀態確認:PR #2 內容已依 issue #1 完成(commit e1f2516、分支 feat/dockerfile),交付回報已於 2026-10-03 22:59 留在 #1,包含建置驗證與煙霧測試結果;目前 mergeable、無待修改項目。\n\n等候 @chenyunda218 審核:若內容符合預期請直接合併(合併後 #1 即可關閉);若有修改意見請在 PR 留言,我會在原分支 feat/dockerfile 接續更新。若本週仍無法排入審核,請回報,以便另安排審核者。" cases := []struct { name string comment string @@ -192,11 +196,22 @@ func TestIsReviewHandoff(t *testing.T) { want bool }{ {"fox#60 實例(@審核者+已就緒,可審閱)", fox60, []string{"chenyunda218"}, true}, + {"alterminal#2 實例(@審核者+無待修改+等候審核+請合併,#53)", al2, []string{"chenyunda218"}, true}, {"多位審核者命中其一", fox60, []string{"ceo", "chenyunda218"}, true}, {"前綴碰撞(@chenyunda218 ≠ chenyunda)", fox60, []string{"chenyunda"}, false}, {"就緒語但無 @(無點名對象)", fox60, []string{"dan"}, false}, {"進度回報(無就緒語)", "進行中:已改完兩步,CI 跑著,@chenyunda218 稍後再看。", []string{"chenyunda218"}, false}, {"預告式(即將就緒不算)", "@chenyunda218 快好了,即將整理完成。", []string{"chenyunda218"}, false}, + {"預告式(之後再請審核不算)", "@chenyunda218 還有兩項要改,之後再請審核。", []string{"chenyunda218"}, false}, + {"百分比進度(完成 80% 不算)", "@chenyunda218 進度:已完成 80%,剩下的明天補上,屆時再請合併。", []string{"chenyunda218"}, false}, + {"仍在實作(有請合併但無完成自述)", "@chenyunda218 實作完成後請審核合併。", []string{"chenyunda218"}, false}, + {"仍在實作(有等候審核但無完成自述)", "@chenyunda218 還在實作,等候審核語先記著:等待審核中。", []string{"chenyunda218"}, false}, + {"等候審核+已完成(複合訊號命中)", "@chenyunda218 所有修改已完成,等待審核。", []string{"chenyunda218"}, true}, + {"待審+無待辦(複合訊號命中)", "PR 無待辦,@chenyunda218 待審中。", []string{"chenyunda218"}, true}, + {"請審核(點名就緒語命中)", "@chenyunda218 請審核。", []string{"chenyunda218"}, true}, + {"請儘速審核(擴充就緒語命中)", "@chenyunda218 內容無待辦,請儘速審核。", []string{"chenyunda218"}, true}, + {"預告式(預計完成後請合併不算)", "@chenyunda218 預計今晚完成,屆時請合併。", []string{"chenyunda218"}, false}, + {"後續請審核(完成已發生,非條件句)", "@chenyunda218 所有修改已完成,後續請審核。", []string{"chenyunda218"}, true}, {"無審核者", fox60, nil, false}, {"空留言", "", []string{"chenyunda218"}, false}, } -- 2.54.0