dispatch-format-guard 修兩處:規則自己的合格範例會被自己擋,禮貌收尾不該算違規
inkstone/ISEP#65:leo 發現「寫完 ISEP#30 那條規則之後,同一天總管又犯了 8 次」, 派來查「現行閘為什麼抓不到」。查證結果分兩層: ━━ 真正在跑的閘其實是 dispatch-format-guard.sh,不是 no-ticket-no-dispatch.sh ━━ no-ticket-no-dispatch.sh 的殼驗證早就是已知行為(只驗有沒有一行【工單】), 但 ISEP#30 已經為此新增了 dispatch-format-guard.sh 做內容判定,測試 19/19 通過。 問題是它有兩個沒被那 19 條測資蓋到的洞: 1. **regex 洞(本體 bug)**:頂層 CLAUDE.md 規定的合格格式帶全形括號—— 「【工單】owner/repo#N(→ comment M)」。_COMMENT_RE 只吃「→ comment M」 本體,兩側括號沒被算進去,殘留括號讓 _REF_RE 比不過,於是**規則自己定義 的合格範例會被自己的閘擋下**(半形括號 `(...)` 同樣會中)。用今天派我這張 票的那份派工單原句實測,改之前 exit=2「票號形狀不對」。 2. **零容忍過頭**:純禮貌收尾(「謝謝」)跟「記得先讀 CLAUDE.md」這種真內容 一樣被當「派工單不只有票號」擋下。ISEP#65 test 4 明講這四種不該擋 (只有票號/空行/「謝謝」/括號包住的 comment 格式),優先做成低誤鎖。 判斷:不改 no-ticket-no-dispatch.sh、不另立第三支閘——dispatch-format-guard.sh 已經是「另立一支」的正確位置,這兩個洞在它自己的地盤上補。 修法: - _COMMENT_RE 兩側括號(全形/半形)都設可選 - 新增 _COURTESY_CLOSERS 白名單(謝謝/多謝/感謝/辛苦了…)+ _is_courtesy_closer(), 只在圍欄外生效,判準仍是「整行清乾淨標點後完全相等」不是「包含」—— 白名單不是黑名單,猜漏頂多誤鎖一次,不會反過來放走真內容(③g 測資證明) 測試:hooks/tests/dispatch-format-guard.test.sh 19→33 條,全過。新增: - ③b/③c 全形/半形括號格式(規則自己的例句) - ③d/③e/③f ISEP#65 test 4 的三種不該擋 - ③g 白名單邊界(禮貌詞混真內容裡照樣算數,防止白名單被誤用成漏洞) - ⑮b–⑮i:leo 點名的「寫完規則後又犯的 8 次」當回歸樣本,內容是從 ISEP#60/#61/#64、Arcrun#142/#144/#165、arcrun-rag#104、InkStoneCo#102 的真實票內文摘錄(見 hooks/tests/fixtures/README.md 記載來歷), 不是想像出來的例子;8 種形狀全部驗證會被擋 reply-identity.test.sh 11/11 仍全過(共用 dispatch_parse.py 沒有回歸) 升版 0.5.0 → 0.5.1(改完不升版沒人吃得到;check-version-consistency.sh 在本分支照慣例是紅的,tag 於 merge 時打)。 另查:.shell-payload/ 整個被 gitignore(scripts/vendor-to-shell.py 產物), 不是 git 分發的一部分——「這支閘會不會被吃到」取決於消費端有沒有重跑 plugin update/vendor-to-shell.py,不是這個 repo 委交的內容缺漏,故不在 本票改動範圍內,僅記錄供總管排查用。 未動 no-ticket-no-dispatch.sh(判斷見上,職責保持不重疊,兩支閘互斥見 dispatch_parse.py 的 has_ticket_marker 分岔)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,12 +37,16 @@
|
||||
當日實證:文字層的閘 8 次誤攔、0 次正確攔截,**紅線寫得越細,命中關鍵字的機率越高
|
||||
⇒ 那些閘在懲罰謹慎**。
|
||||
|
||||
本檔**全檔零個「命中某個詞就違規」的比對**。判準是「這一行是不是【工單】欄位」——
|
||||
**在不在**,不是**寫什麼**。用到的正則只有兩種,都在認形狀:
|
||||
本檔**沒有「命中某個詞就違規」的比對**。判準是「這一行是不是【工單】欄位」——
|
||||
**在不在**,不是**寫什麼**。用到的正則有三種,全部在認形狀:
|
||||
- `【某某】` 欄位標記本身
|
||||
- `owner/repo#N` 票號形狀
|
||||
措辭多謹慎、有沒有提到「紅線」「部署」「main」,本檔一律不看。
|
||||
⇒ 也因此它不會像文字層的閘那樣「寫得越小心越容易被罰」。
|
||||
- `owner/repo#N`(可選外掛全形/半形括號的 `→ comment M`)票號形狀
|
||||
- 唯一例外(ISEP#65):`_COURTESY_CLOSERS` 是一份**白名單**,只用來認出
|
||||
「這一行是不是零資訊的禮貌收尾」,作用方向與黑名單相反——認出的是
|
||||
「不算違規」,不是「算違規」;且要求整行清乾淨標點後完全相等,不是
|
||||
「包含」,所以不會反過來放走任何真正的內容。
|
||||
措辭多謹慎、有沒有提到「紅線」「部署」「main」,本檔一律不看,仍然不會被
|
||||
「寫得越小心越容易被罰」的病拖下水。
|
||||
|
||||
━━ 派工單格式 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
【工單】inkstone/ISEP#30 → comment 4322
|
||||
@@ -83,9 +87,32 @@ IDENTITY_ROLES = ("總管", "subagent", "leo")
|
||||
|
||||
_MARKER_RE = re.compile(r"^【([^】]{1,12})】\s*(.*)$")
|
||||
_REF_RE = re.compile(r"^([A-Za-z0-9_.-]+)/([A-Za-z0-9_.-]+)#(\d+)\s*$")
|
||||
_COMMENT_RE = re.compile(r"(?:#issuecomment-|→\s*comment\s*)(\d+)")
|
||||
# 🔴 inkstone/ISEP#65:頂層 CLAUDE.md 規定的合格格式帶著全形括號——
|
||||
# 「【工單】owner/repo#N(→ comment M)」。舊版正則只吃「→ comment M」本體,
|
||||
# 兩側的括號(全形/半形都要吃)沒被算進去,殘留的括號讓 _REF_RE 比不過,
|
||||
# 於是**規則自己定義的合格範例會被自己的閘擋下**。這裡把左右括號都收進來,
|
||||
# 兩種都設成可選(沒有括號的舊寫法、純 #issuecomment- 連結都還要能過)。
|
||||
_COMMENT_RE = re.compile(r"[((]?\s*(?:#issuecomment-|→\s*comment\s*)(\d+)\s*[))]?")
|
||||
_FENCE_RE = re.compile(r"^\s*(```|~~~)")
|
||||
|
||||
# 🔴 inkstone/ISEP#65:票號後面只掛一句純禮貌收尾(例:「謝謝」),不該被當成
|
||||
# 「派工單不只有票號」的違規——它不含任何要搬去票上或共通規定的實質內容。
|
||||
# 這是**白名單,不是黑名單**:判準仍是結構(整行清乾淨標點後「等於」清單裡的
|
||||
# 固定字串,不是「包含」),漏收某個禮貌講法頂多誤鎖一次(代價小,見 ISEP#65
|
||||
# 的「優先做成低誤鎖」),但不會反過來放走任何真正的內容——真內容不會剛好
|
||||
# 打出一個字不差的空話。全檔仍然沒有「命中某個詞就違規」的比對,這裡是唯一
|
||||
# 一處字面比對,且作用方向相反:認出「不是內容」,不是認出「是違規」。
|
||||
_COURTESY_CLOSERS = frozenset({
|
||||
"謝謝", "謝謝你", "謝謝您", "謝謝囉", "多謝", "感謝", "感恩", "辛苦了", "收到",
|
||||
"thanks", "thank you", "thx",
|
||||
})
|
||||
_COURTESY_STRIP_RE = re.compile(r"[\s。!!.,~~,、]+$")
|
||||
|
||||
|
||||
def _is_courtesy_closer(line):
|
||||
s = _COURTESY_STRIP_RE.sub("", line.strip())
|
||||
return s.lower() in _COURTESY_CLOSERS
|
||||
|
||||
|
||||
def _split_lines(text):
|
||||
"""切成 (是否在圍欄內, 原始行)。
|
||||
@@ -146,6 +173,10 @@ def parse_dispatch(prompt):
|
||||
continue
|
||||
if raw.strip():
|
||||
# 【工單】欄位本身只准佔它自己那一行;它下面的續行也是多的。
|
||||
# 白名單豁免只在圍欄外生效——圍欄裡的東西本來就該一律算數(test ⑮),
|
||||
# 這裡不額外放寬,避免有人把真內容包在圍欄裡再貼一句「謝謝」蒙混。
|
||||
if not in_fence and _is_courtesy_closer(raw):
|
||||
continue
|
||||
extra.append((cur, raw))
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user