docs(skills): add task triggers and newer capabilities to gh skill description by littfed · Pull Request #14629 · cli/cli · GitHub
Skip to content

docs(skills): add task triggers and newer capabilities to gh skill description - #14629

Open
littfed wants to merge 1 commit into
cli:trunkfrom
littfed:fix/issue-14621
Open

littfed wants to merge 1 commit into
cli:trunkfrom
littfed:fix/issue-14621

Conversation

@littfed

@littfed littfed commented Oct 9, 2026

Copy link
Copy Markdown

Resolves #14621

Summary

  • Add explicit trigger conditions and highlight newer capabilities (--attach, discussions, repo read-file, issue relationships) in skills/gh/SKILL.md description

Verification

  • Tests and linter verified clean.

@littfed
littfed requested a review from a team as a code owner October 9, 2026 07:05
@littfed
littfed requested a review from sergiou87 October 9, 2026 07:05
@github-actions github-actions Bot added external pull request originating outside of the CLI core team needs-triage needs to be reviewed ready-for-review and removed needs-triage needs to be reviewed labels Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

howie added a commit to heyu-ai/yibi-stack that referenced this pull request Oct 10, 2026
…main 基準 (#532)

* feat(issue-triage): 新增證據基準檢查腳本 check-baseline.sh

驗證 issue 症狀之前先確認「被檢視的程式碼」就是剛 fetch 的 origin/main。
落後的 main 或沒合併的分支,會讓 DONE 與 NOT DONE 都判反。

- check-baseline.sh:fetch 失敗即停、不回退到本機殘留的 origin/main;
  以 exit 2/3/4/5 區分不在 repo、fetch 失敗、commit 不一致、tracked 檔案被修改
- test_check_baseline.py:bare origin + clone 的拋棄式 repo,每個具名 exit code
  都有實際會觸發它的輸入;靜態契約測試要求至少找到一行目標,避免空迴圈空洞通過
- 突變驗證:(1) 整支短路成 exit 0 時 10 個測試轉紅,(2) 移除 fetch 時 6 個測試轉紅,
  兩次皆以反向替換還原並 cmp 確認與原檔相同
- pyproject.toml:testpaths 是明列的,新測試目錄不加進去 make ci 不會收集
- 帶入 change add-issue-triage-staleness-review 的 artifact 與目前進度(1.1、2.1、2.2)

apply 階段實測(cli/cli 的 REST 與 gh JSON)推翻了 spec 對 bot 判定的假設:
gh issue list 的 JSON 會去掉 [bot] 後綴、Copilot 本來就沒有後綴,
所以改以 REST 的帳號型別判定,並已同步修正 spec、design、tasks。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(issue-triage): 新增程式碼漂移訊號腳本 staleness-signals.sh

issue 引用的檔案若自建立以來被刪除、改名或大量變動,就是比天數更直接的
「前提可能已消失」訊號。腳本對 origin/main 的歷史計算(不看工作樹),
每個路徑輸出一行 tab 分隔的「路徑、狀態、細節」,狀態為 unchanged、changed、
deleted、renamed、never-existed;沒有路徑時輸出 NOT_APPLICABLE。

- 路徑以 GIT_LITERAL_PATHSPECS 逐字比對,a*.py 與 :(glob)*.py 不會被當成 glob
- 改名偵測:log -- <舊路徑> 看不到改名(目的端不在 pathspec 內,會顯示成刪除),
  所以先定位刪除的 commit,再針對該 commit 做 -M 偵測
- 每個 git 呼叫失敗都以 exit 1 回報,不會被當成「沒有漂移」
- 20 個測試涵蓋五種狀態、無路徑、基準 ref 缺失、讀歷史而非工作樹、
  glob 與 pathspec magic、刪除後重建、GIT_DIR decoy、三種參數錯誤
- 突變驗證(皆以反向替換還原並 cmp 確認):
  M1 deleted 改成回報 unchanged -> test_ss_st_003 轉紅
  M2 關閉 rename 偵測 -> test_ss_st_004 轉紅
  M3 移除 GIT_LITERAL_PATHSPECS -> 第一次只有 011 轉紅、010 存活,
  原因是 a1.py 從未被刪除,glob 沒有機會誤命中刪除紀錄;
  改成「已被刪除的 a1.py」後 010 與 011 都會轉紅

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(issue-triage): 新增最後人為活動腳本 last-human-activity.sh

issue 的「最後一次實質人為活動」是過期分層的輸入。它必須排除 bot 與 skill 自己
貼的留言,否則 stale bot 或這個 skill 的每次盤點都會重置過期時鐘。

bot 只看 REST 的帳號型別(user.type 為 Bot),不看 login 文字。apply 階段在
cli/cli 實測:gh issue list 的 JSON 會去掉 [bot] 後綴(github-actions[bot]
顯示為 github-actions),Copilot 的 login 本來就沒有後綴。已刪除帳號與沒見過的
帳號型別一律視為人為活動,往較安全的方向失敗。

skill 自己的留言 = 內文含 triage 標記且作者是目前登入的帳號;標記單獨出現不夠,
否則任何人貼上標記就能讓自己的留言從度量中隱形。

- 輸出一行:最後人為活動時間、tab、stale notice 留言時間(沒有則為空)
- 取不到目前帳號時 exit 3,不回退成「沒有人是 skill」
- gh 的 stderr 另存暫存檔,不併進 stdout,避免成功時的警告污染 JSON
- gh api --paginate 把每頁的陣列連續輸出,用 jq -s 讀成陣列的陣列
- 29 個測試以假 gh 回放 REST 形狀的 JSON;靜態測試確認只做三種 gh 呼叫
- 突變驗證(皆以反向替換還原並 cmp 確認):
  M1 不排除 Bot -> 003、004 轉紅,反向對照 005 維持綠
  M2 標記不看作者 -> 009、015 轉紅
  M3 stale notice 不看作者 -> 只有 015 轉紅
- 真實資料核對:cli/cli#14629 建立於 07:05:39,唯一留言是 07:05:56 的
  github-actions[bot],腳本回傳 07:05:39(bot 被排除)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(issue-triage): 新增 OBSOLETE 與 STALE-CANDIDATE verdict,驗證前固定 origin/main 基準

issue-triage 的偏誤是單向的:只防誤關,沒有機制對抗堆積。前提已消失的 issue
落不進 CLOSE(症狀既非 DONE 也非 NOT DONE),久未更新反而被當成降優先的理由,
且程式碼驗證沒有固定基準,本機 main 落後或停在別的分支時 DONE 與 NOT DONE 會判反。

SKILL.md:
- Step 1c 證據基準:驗證前先 check-baseline.sh,exit 0..5 各為獨立分支;
  報告頂端寫出基準 SHA 與 fetch 時間;Jira-only 與單一項目執行同樣適用
- Step 3d' 過期檢視輸入(僅 GitHub issue):最後實質人為活動(排除 bot 與 skill 自己,
  標記必須搭配作者才生效)、30/90/180 天分層(只提高證據門檻,不決定結果)、
  程式碼漂移訊號、五種豁免、triage 標記
- Step 3e 決策表:新增 OBSOLETE(需要正向對照,零命中不是證據,關閉原因 not planned)
  與 STALE-CANDIDATE(先 stale notice、14 天寬限期、無回應才建議關閉,絕不僅憑天數);
  優先序改為 MERGE > CLOSE > OBSOLETE > UPDATE-SCOPE > STALE-CANDIDATE > KEEP
- Step 6:時效訊號只看 deadline;久未更新不降優先,改標 review-urgency
- Step 8:每則留言帶 triage 標記;新增 8h/8i/8j 三個寫入動作,仍只在 --apply 且逐項確認後執行;
  寬限期滿關閉前重新確認沒有新的人為活動
- FAQ:改寫 close-as-stale 條目(原本寫「KEEP 並降優先」,與新設計矛盾),補四筆新條目

同批:skills/README.md 與 plugins/dev-cycle/README.md 的索引列、change artifact 與進度
(task 1.1、2.1~4.7 已完成)。

apply 階段的兩個設計修正(已同步 design、spec、tasks):
- bot 判定改用 REST 帳號型別:gh issue list 的 JSON 會去掉 [bot] 後綴
- last-human-activity.sh 除了「天數小於 180」,遇到含 stale notice 標記的留言也要呼叫,
  否則 notice 早於 180 天時會把已過寬限期的 issue 誤當成第一次提醒

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs(openspec): add-issue-triage-staleness-review 補齊 spec 與 SKILL.md 的 guard 同步

task 5.2 逐項對照 spec、SKILL.md 與腳本,找到五處 SKILL.md 有、spec 沒有的守衛
(只存在於一邊的 guard 會讓 spec 無法用來交叉檢查 agent 行為):

- tier 2 以上的 KEEP 找不到正向證據:維持 KEEP 並標 premise-unverified,旗標本身不得導致關閉
- never-existed 不是前提消失的證據(多半是 issue 寫錯路徑)
- 寬限期滿關閉前重新量測最後人為活動,有新活動就取消(判定到確認之間可能有人回覆)
- 過期資料取不到時 fail-safe:不得升為 STALE-CANDIDATE 或 OBSOLETE,也不得把缺資料
  當成人為活動或沒有漂移(新 requirement:Unavailable staleness data fails safe)
- OBSOLETE 與 STALE-CANDIDATE 只適用 GitHub issue(新 requirement:Staleness verdicts
  apply to GitHub issues only)

同步 design 的 Implementation Contract(重新量測、fail-safe、premise-unverified),
task 4.2 與 4.4 補上新 requirement 名稱,並記錄全部 17 項 task 已完成。

spectra analyze:Coverage、Consistency、Gaps、Localization 皆 Clean,
僅剩 Ambiguity 的 Suggestion;spectra validate 通過。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* chore(release): 版本 lockstep 升為 1.23.12(issue-triage 過期檢視)

改到 plugins/** 內容後必須升版,Claude Code 的 plugin 更新靠 plugin.json 的
version 判斷;版本不變,已安裝的使用者不會收到這次的 issue-triage 改動。

起點的版本狀態不一致,先記錄下來:origin/main 上 plugin 全是 1.23.11,但
pyproject.toml、uv.lock、CHANGELOG.md 停在 1.23.10。#516 把三者推到 1.23.10,
之後 #526 只動了 plugin 檔案(到 1.23.11)。所以只 bump 到 1.23.11 的話
plugin 版號不會變,所以直接升為 1.23.12,並一併把 pyproject 與 uv.lock 拉齊。

- pyproject.toml、uv.lock 的 yibi-stack 版本行(不跑 uv lock,避免改寫無關的 wheel)
- scripts/sync-plugin-versions.sh 同步 6 個 plugin 共 12 個版本檔,驗證全為 1.23.12
- CHANGELOG.md 頂端新增 1.23.12 一筆

不執行 make release(含 git tag 與 GitHub Release,屬不可逆操作,由使用者執行)。
注意:make release 會讀 pyproject 現值再加一,in-PR 先 bump 再 make release
會再升一版。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(sdd): check_testplan_trace 的略過規則改看相對 root 的路徑,修正 worktree 內全部測試被略過

discover_test_files 用「絕對路徑」判斷要不要略過虛擬環境與 .claude/worktrees。
略過規則描述的是被掃描的 repo 裡面有什麼,不該取決於 repo 本身被 checkout 在哪裡:
repo root 位於 .claude/worktrees/<name>/(每個 background job 的 worktree)時,
所有測試檔都被略過,enforced 且 tasks 全勾的 change 會把每個 auto TC 都報成 missing,
pre-commit 的 check-testplan-trace 因此在 worktree 內無法通過,也會對其他 change
產生假的 WARN(本機實測:修正後 integrate-retro-hindsight 的 30 筆 missing 消失)。
祖先目錄名為 venv、node_modules 等時 _SKIP_DIRS 也是同樣的缺陷。

這是第一個同時滿足「trace: enforced」與「tasks 全勾」的 change 在 worktree 內提交時才被
撞到;CI 與主 checkout 不受影響。

修法:兩條規則都改看 path.relative_to(root).parts。

- 回歸測試 TPT-ST-009..012:repo root 在 .claude/worktrees 底下與祖先目錄叫 venv 時仍要
  找得到自己的測試(這個缺陷的兩個入口);repo 內巢狀的 worktree 與 .venv 仍要被略過
  (防止矯枉過正)
- red-first:修正前 009、011 轉紅,010、012 維持綠
- 四個單點突變各被恰好一個測試擊殺,皆以反向替換還原並 cmp 確認:
  worktree 規則改回絕對路徑 -> 009;_SKIP_DIRS 改回絕對路徑 -> 011;
  移除 worktree 規則 -> 010;移除 _SKIP_DIRS 規則 -> 012

屬於 PR #532(issue-triage 過期檢視)的 Review Contract AC-14,經 howie 同意納入範圍。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(issue-triage): 補上 testplan.md 與 SKILL.md 文字契約測試,綁定既有測試到 TC

PR #532 的 pre-review check(amplifier-verify)擋下:feat change 沒有 testplan.md。
type 是作者自填,不能用改標成 chore 來閃避,所以補上真正的 testplan。這是我先前沒有
跑 spectra-amplifier 的疏漏。

- testplan.md:trace: enforced;4 個 seam、37 個 auto TC、44 個 scenario 的 Coverage、
  4 項 Manual Verification。依賴 agent 執行期判斷的 scenario 一律標 partial,並說明
  [doc] 層的 PASS 不是行為證明;寬限期滿路徑無法端到端驗證(GitHub 留言時間無法回填)
- test_skill_contract.py(67 項):斷言 SKILL.md 有明文寫新規則,並防止舊措辭被寫回。
  突變自檢:移除任一錨點的所有出現處、或注入舊措辭,檢查器必須變紅
- 既有三份腳本測試的 docstring 加上 spec 與 tc 綁定(測試名稱與邏輯不變)
- proposal 的 Impact 與 tasks(6.1、6.2)記錄範圍追加

驗證:
- check_testplan_trace.py 在 --repo-root . 下無 finding;換成無關測試目錄回報 37 個 missing
  (檢查器不是空殼);--strict 恰好只剩 4 個 manual-open
- 對真實 SKILL.md 做兩個單點突變(舊優先序、FAQ 寫回「KEEP 並降優先」)皆被擊殺,
  以備份還原並 cmp 確認一致
- 突變自檢抓到我自己的設計缺陷:6 個錨點在 SKILL.md 出現不只一次,只移除第一處不算規則被刪掉,
  改為移除所有出現處

與前一個 commit(516a074f,修正 check_testplan_trace 在 worktree 內略過所有測試檔)搭配:
沒有那個修正,這份 testplan 在 worktree 內提交時 hook 會對每個 TC 誤報 missing。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs(changelog): 1.23.12 補記 check_testplan_trace 的 worktree 路徑修正

這個 PR 後來把 plugins/sdd 的 checker 修正納入範圍(Review Contract AC-14),
CHANGELOG 的 1.23.12 條目要如實記錄;sdd 的版本已隨 lockstep 升為 1.23.12。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(issue-triage): check-baseline 補上被 index 旗標隱藏的 tracked 修改

assume-unchanged 與 skip-worktree 會讓 `git status` 看不到修改,但 Read/Grep
讀到的是被改過的磁碟內容,基準檢查因此在 tracked 檔案已被竄改時仍 exit 0。
現在對 `git ls-files -v -z` 標出的這類檔案,只要存在於磁碟就拿 hash-object 與
HEAD 的 blob 比對,不同即 exit 5;sparse checkout 不在磁碟上的檔案不算。
tag 明列為 h/s/m/r/c/k/S,不用 [a-z],避免 bash 範圍比對依 locale 把大寫 H 也算進去。

順手處理 review 的小項:
- rev-parse / rev-list 改用完整 ref refs/remotes/origin/main 與解析後的 SHA,
  本機若有叫 origin/main 的分支不會再蓋過遠端 ref;
- 解析值只取 stdout,stderr 另存暫存檔,ambiguity warning 不再混進
  ahead/behind 計數造成亂碼訊息;
- git 呼叫加 GIT_TERMINAL_PROMPT=0,fetch 不會卡在認證提示。

新增 ITB-ST-006 到 009(含 sparse 與旗標但內容相同的對照、本機同名分支);
先確認 006、007、009 在舊程式碼為紅,再修成綠。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(issue-triage): last-human-activity 只認完整標記,staleness-signals 路徑改為 repo 根目錄相對

last-human-activity.sh:舊判定只比對 `<!-- issue-triage:` 前綴,內文只是提到
`<!-- issue-triage:stale-notice`(無日期、無結尾)的人為留言,或 `stale-notice-foo`
這種長得像的種類(`\b` 會放行),都會被當成 skill 的 notice:該留言從人為活動消失、
同時被算成 stale notice,過期時鐘被錯誤延長。現在只認「內文最後一個非空行」恰好是
`<!-- issue-triage:<close|update-scope|merge|stale-notice> YYYY-MM-DD -->` 的留言,
種類精確比對;CRLF 與尾端空白行仍能辨識。

staleness-signals.sh:pathspec 預設相對於 cwd,從 repo 子目錄呼叫時 `sub/x.txt`
變成 `sub/sub/x.txt` 而回報 never-existed 且 exit 0,與從根目錄呼叫的結果相反。
驗證完參數後改為先切到 `git rev-parse --show-toplevel`。同時 stderr 不再併入
解析值(改存暫存檔),檔頭補上 exit 2 也涵蓋空字串、tab、換行路徑。

測試:新增 ITA-ST-009 到 013 與 ITD-ST-005(修正前 009 到 012 與 017 為紅,029、030
為真標記的對照);test_ss_st_016 擴充 tab、換行、空字串、`..`、`src/..`,移除任一個
路徑守衛分支的突變都會被擊殺。spec 補上 incomplete-marker、merge-note、
drift-lookup 與 repeated-comment-lookup 的 scenario,testplan 補上對應的 TC。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(issue-triage): SKILL.md 補齊過期資料不可用的 fail-safe 並把文字契約錨點綁到負責段落

SKILL.md:
- last-human-activity.sh 的 exit 1/3/4 與 staleness-signals.sh 的 exit 1/3 都導向
  「過期檢視不可用」,不得成為 STALE-CANDIDATE 或 OBSOLETE;缺 jq 時所有需要呼叫的
  issue 都標不可用,不再只寫「略過過期檢視並繼續」;
- 「連續失敗」改成數字:同一次執行第二次 exit 3 即 `[FAIL]` 並停止過期檢視,其餘
  尚未檢視的 issue 全部標不可用;
- 決策表 guard 列「任一前置呼叫失敗 -> STOP」限縮為 Step 1/Step 2 的必要前置呼叫,
  另加「任一過期資料取不到」的 guard 列,避免與「單一 issue 失敗仍繼續」互相矛盾;
- 8g 跨系統整併貼在 GitHub issue 上的留言也要帶 `merge` 標記,並更新 8a 到 8j 的清單;
- 標記定義改為「最後一個非空行的完整標記」,與 last-human-activity.sh 一致。

test_skill_contract.py:錨點改綁到負責段落(SCOPES)且在段落內唯一,補上決策表 guard 與
列 1 到 8、寬限期表每一列的逐列錨點,ITS-EG-014 改為一次只移除一個出現處(段落內的
變紅、段落外的不影響)。舊文字上 38 個測試為紅;單點突變 M1(14 天改 1 天)、M3(列 6
的 180 改 30)、M4(列 6 拿掉無豁免)、M5(列 4 的 not planned 改 completed)各被擊殺。

文件同步:design.md(renamed 的細節是新路徑而不是 commit、viewerDidAuthor 改為作者 login
比對、腳本與寫入動作數量、REST 呼叫條件、新的 failure mode 與 exit code 對應)、tasks.md
(4.2 改寫,新增第 7 節)、testplan.md(ITD-ST-003/004 改為 partial、Legend 的 covered
限縮為腳本層、AC-1~AC-14、新增 ITS-DT-014 與 ITS-EG-016)、CHANGELOG.md(1.23.12)。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(sdd): 鎖住 discover_test_files 的略過條件必須同時含 .claude 與 worktrees

TPT-ST-009 到 012 只涵蓋「repo 在 worktree 之內」與「巢狀 worktree、venv 仍被略過」,
沒有任何測試釘住略過條件是 `.claude` 且 `worktrees` 都在相對路徑裡:把 `and` 改成
`or` 後,repo 內部的 `.claude/hooks/tests/test_x.py`(沒有 worktrees)與 `worktrees/`
目錄(不在 .claude 底下)都會被誤略過,原測試全綠。新增 TPT-ST-013、014 各自綁定一個
TC;`and` 改 `or` 的突變兩個測試都會擊殺。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(issue-triage): check-baseline 從任何子目錄都掃整個 repo,並把旗標隱藏的缺檔算成修改

第二輪 review 的 Critical 與 Important,lead 以拋棄式 repo 重現:

- git status 與 git ls-files 的範圍預設是 cwd。從 docs/ 執行時,根目錄的
  assume-unchanged 加被改寫的 top.txt 整個不被檢查(exit 0,從根目錄是 exit 5),
  cwd 內未變的旗標檔案反而以 cwd 相對路徑查不到 HEAD 的 blob 而誤報 exit 5。
  確認在工作樹內之後先 cd 到 rev-parse --show-toplevel(失敗 exit 2)。
- 旗標隱藏、又被刪掉的檔案原本直接 continue,status 為空所以 exit 0。
  現在只有 core.sparseCheckout 為 true 且 tag 為 S 或 s 的缺檔才豁免,
  其餘算修改 exit 5;tag 明列,不用 [a-z](bash 範圍依 locale,會吃到 H)。
- 補測:symlink 改指向與未變、index 有但 HEAD 沒有的檔案(intent-to-add 加
  assume-unchanged)、以 PATH 上的假 git 讓 rev-list、status、config、ls-files、
  hash-object(一般檔案與 symlink 各一)失敗時 exit 1 且 stdout 為空。
- 既有的 sparse 對照改成真的 git sparse-checkout,而不是只加 skip-worktree 旗標。
- SKILL.md 1c 改為「根目錄或任一子目錄皆可」,exit 5 的說明含旗標隱藏的缺檔。
- openspec:spec 新增 Run from a subdirectory、Hidden tracked file deleted from
  disk、Unexpected git failure is not a pass 三個 scenario;testplan 補 ITB-ST-010
  到 016 與 ITB-EG-017;design 與 tasks 8.1 同步。

驗證:新測試 ITB-ST-010、011、012、013 在舊程式碼上為紅;十一個單點突變(移除 cd、
豁免加入 h、移除 sparse 條件、哨兵值等於磁碟 hash、略過 symlink 分支、六個
fail 1 改 true)全部被擊殺。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(issue-triage): staleness-signals 一律用完整 ref 解析基準,並補齊刪除與改名的邊界測試

第二輪 review 的 Critical 與 Important:

- 腳本先前以短名稱 origin/main 查詢。本機若有叫 origin/main 的分支,git 會先解析
  到 refs/heads/origin/main,遠端已刪掉的檔案因此被回報成 changed(lead 以拋棄式
  repo 重現)。現在定義 REF=refs/remotes/origin/main,rev-parse --verify 只解析一次,
  ls-tree、rev-list、log 全部用解析出的 SHA;exit 3 的訊息附上 git 的 stderr,
  不再丟進 /dev/null。
- 補測:同名本機分支(遠端已刪檔案回報 deleted;沒有遠端 ref 仍 exit 3)與一個
  靜態測試(非註解程式行只准出現完整 ref)、刪除、重建、再刪除回報單一最近 SHA、
  非 ASCII 檔名改名、改名加小幅修改(R088)、同一 commit 兩個改名各對各,以及以 PATH
  上的假 git 讓 ls-tree、rev-list、log、show 失敗時 exit 1 且 stdout 為空。
- 測試檔 docstring 的 exit 2、3 敘述與腳本檔頭對齊。
- openspec:spec 新增 Referenced file was renamed、Deleted again after recreation、
  Same-named local branch does not shadow the baseline;testplan 補 ITD-ST-006 到
  010 與 ITD-EG-011;design 與 tasks 8.2 同步。

驗證:同名分支的行為測試與靜態測試在舊程式碼上為紅;十二個單點突變(回到短名稱、
三個查詢各改回 origin/main、log 拿掉 -1、只認 R100、不比對舊路徑、關掉
core.quotepath、四個 fail 1 改 true)全部被擊殺。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(issue-triage): last-human-activity 的缺欄位回應必須 exit 4,鎖住 jq -er

第二輪 review 的 Important:pr-test-analyzer 以副本突變發現,把 last-human-activity.sh
的 jq -er 改成 jq -r 後全部測試仍綠。jq -r 對缺欄位印出字串 null 並 exit 0,
目前帳號會變成 null、issue 建立時間會輸出 null,後續日期運算全部落空。

- 假 gh 新增 FAKE_GH_USER_JSON 與 FAKE_GH_ISSUE_JSON 覆寫回應內容。
- 補測 api user 與 issue 的回應都是 {}:exit 4、stdout 為空、stderr 含 [FAIL]。
- openspec:spec 新增 Malformed API response scenario;testplan 補 ITA-EG-014、015;
  tasks 8.3 同步。

驗證:兩處 jq -er 各改成 jq -r 的單點突變各被對應的測試擊殺。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(issue-triage): SKILL.md 先過濾 issue 內文的不合法路徑,並讓 8j 重新量測失敗時放棄該筆

第二輪 review 的 Important 與 Actionable NIT:

- 3d′ 的路徑抽出規則只排除 URL,但 staleness-signals.sh 對絕對路徑、含 .. 、空字串、
  含 tab 或換行一律 exit 2,而 SKILL.md 把 exit 2 當成 skill 自己的 bug 並停止。
  一份提到 /etc/hosts 的普通 issue 就會中止整個盤點。現在呼叫腳本前先丟掉這些 token
  並在條目註明「已略過的路徑」;腳本仍 exit 2 時依 stderr 區分來源:內文路徑漏網只標該
  issue 過期檢視不可用,建立時間參數錯誤才是 skill 的 bug 而停止。
- 8j 寬限期滿關閉前的重新量測沒有失敗分支:last-human-activity.sh exit 1、3、4 時
  agent 沒有規則可依,可能在看不到新活動的情況下直接關閉。現在放棄該筆、列入「已取消」
  並註明原因,不貼留言、不關閉,回報計數含這一類。
- NIT:3d′ 的 exit 3 說明那個 [FAIL] 只停止過期檢視,不終止整個盤點;exit 4 說明以
  stderr 區分缺 jq 與單一回應壞掉。
- NIT:proposal.md Impact 的 TPT-ST-009 到 012 改為 014;testplan.md 前言的突變自檢
  敘述改為一次只移除一個出現處,與 ITS-EG-014 實際行為一致。
- test_skill_contract.py 新增 ITS-DT-015、016 與 ITS-DT-012 的補充錨點,逐段落綁定且
  各恰好出現一次。
- openspec:spec 新增 Unsafe path in an issue body、Re-measurement fails before the
  write 兩個 scenario 並補相關 Requirement 文字;testplan 補 ITS-DT-015、016;
  design 與 tasks 8.4 同步。
- CHANGELOG 1.23.12 補記本輪第二輪修正(不升版)。

驗證:新錨點在舊 SKILL.md 上有 31 個測試為紅(含逐錨點的移除自檢與唯一性檢查);
套用後 plugins/dev-cycle/skills/issue-triage 共 316 個測試全綠。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs(issue-triage): 勾選 MV-001 到 MV-004 並記錄走查的限制

以 PR 版 skill 在拋棄式 private repo(triage-sandbox-532)完成四項人工走查:

- MV-001:證據基準行、唯讀無寫入、review-urgency、豁免清單、不安全路徑被前置過濾且整輪不中止。
  限制:單一 issue 過期資料失敗時其餘照常沒有 agent 層實測(使用者接受目前覆蓋);
  tier 1 到 3 以 prompt 把門檻視為 0 天模擬。
- MV-002:OBSOLETE 需正向對照並以 not planned 關閉;從未存在的路徑判 UNCLEAR;改名的路徑追到新路徑。
- MV-003:使用者逐項確認後貼出 stale notice,last-human-activity.sh 找回 notice 時間,
  skill 自己的留言不算人為活動;寬限期內不提議關閉。寬限期滿與判定到寫入之間有人回覆沒有端到端驗證。
- MV-004:claude -p 帶 --apply 且放行 gh 寫入權限、有可寫入候選的情況下,前後快照完全相同。
  限制:prompt 有告知無人環境,驗的是被告知無人時守 Core Contract 第 3 點,不是 skill 自行偵測;
  skill 沒有偵測排程或 webhook 的機制,列為 Follow-up。

check_testplan_trace.py --strict 對本 change exit 0。只改 testplan.md。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* chore(release): 版本改升到 1.23.13,避開 main 的 #528 已使用的 1.23.12

main 的 #528 在 review 期間把所有 plugin 推到 1.23.12,與本 PR 原本的 1.23.12 撞號:
merge 後 plugin 版號不變,已安裝 1.23.12 的使用者不會收到 issue-triage 等變更。

- scripts/sync-plugin-versions.sh 1.23.13:六個 plugin 的 package.json 與 .claude-plugin/plugin.json
- pyproject.toml、uv.lock(uv lock --check 通過)
- CHANGELOG.md:條目標題改為 [1.23.13],日期改為 2026-10-11

Review Contract AC-12 同步改為 1.23.13(howie 已確認)。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external pull request originating outside of the CLI core team ready-for-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gh skill description does not tell agents when to use it, so it is skipped for tasks it covers

1 participant