Files

19 KiB
Raw Permalink Blame History

name, description, argument-hint
name description argument-hint
target 用專案根目錄的 `TARGET.md` 當每日待辦清單,並以系統排程(LinuxWSLmacOS 用 crontab、Windows 用 schtasks)在每天 00:00 自動跑完它。`--schedule on` 建立或更新排程、`--schedule off` 移除排程、`--run` 立即(或由排程)執行一次:先同步 git 並切到 `develop`(遠端沒有就從預設分支建立),逐項實作 `TARGET.md` 中未勾選的項目、完成一項就勾選並補完成時間,接著把工作區變更依 conventional commit 類型分類提交、push `develop`,最後透過 Gitea API 對**遠端預設分支**發 PR(已有同 head→base 的 open PR 就沿用不重開)。當使用者說把 TARGET.md 排成每天執行、每天半夜自動跑待辦、開啟/關閉每日自動任務、建立每日排程做完 TARGET、移除 TARGET 排程、跑一次 TARGET.md 的項目、讓 AI 每天自動做完待辦並發 PR,或提到 TARGET.md、每日排程、cron 每天 00:00、schtasks 每日任務時觸發。不適用於:解決 AI review findings(用 review-resolve)、實作 Gitea 議題的 TODO(用 issues)、角色記憶的睡眠排程(用 role)。 [--schedule on|off] [--run] [--project-dir <專案根目錄>] [--cli <claude|codex|agy|opencode|copilot>] [--base <PR 目標分支>] [--no-pr] [--yes]

target — TARGET.md 每日排程執行、提交、push develop 並發 PR

兩個用途合在一個 skill管理排程(開/關每天 00:00 的系統排程)與執行一次(把 TARGET.md 的待辦做完並走完 git 流程)。排程觸發時,執行的就是本 skill 的 --run

模式 觸發 動作
--schedule on 使用者 依 OS 建立/更新「每天 00:00 執行本 skill --run」的系統排程(同一專案只會有一筆)
--schedule off 使用者 移除該專案的排程條目(只動自己那筆,不碰使用者其他排程)
--run 排程/使用者 A Git 同步(切到 develop,沒有就建立)→ B 讀 TARGET.md → C 逐項實作並勾選 → D 分類提交 → E push develop → F 對預設分支發 PR
不帶參數 使用者 只回報現況:排程裝了沒、下次執行時間、TARGET.md 還剩幾項未完成

--schedule--run 可同時帶(--schedule on --run = 裝好排程並立刻先跑一次)。


共用規範(shared plugin,必要前置)

執行本 skill 前,先以 Skill 工具載入下列共用規範並全程遵守;任一載入不到(shared plugin 未安裝)時,先詢問使用者是否安裝 shared pluginhttps://gitea.jsc.idv.tw/plugins/shared.git),使用者不安裝則直接中斷本 skill,不得只憑下方一行摘要繼續執行:

  • /jsc-shared:spec-output:繁體中文(台灣用語)、UTF-8(不含 BOM)無亂碼(含 TARGET.md 回寫、commit 訊息、PR 標題/描述)、表格呈現。
  • /jsc-shared:spec-execution:自動執行原則(必要決策才中斷)、不臆測/需人工確認。
  • /jsc-shared:spec-git-safety:不破壞既有工作(絕不 reset --hardclean)、pull --ff-only、保守解衝突、新分支不覆蓋既有分支。
  • /jsc-shared:spec-giteaGITEA_TOKEN 機密保護(不 echo、遮蔽 ***)、API body 以 UTF-8 JSON 檔帶入。
  • /jsc-shared:spec-time-logAsia/Taipei yyyy/MM/dd HH:mm:ss 時間格式、[時間][階段][等級]: 訊息 log 格式。

本 skill 特有補充:

  • 排程只動自己那一筆:安裝/移除都以固定標記比對,絕不覆寫整份 crontab、不刪別人的排程任務
  • 排程情境沒有人在旁邊--run 遇到必要決策時停下來並寫進 log,不得臆測後硬做;下次執行會再遇到同一個決策點,由使用者處理。
  • 必要決策(會中斷詢問):工作區有未提交變更、origin 無法解析、找不到遠端預設分支、TARGET.md 項目語意不明無法安全實作、push 憑證皆失敗、無法判斷目前是哪個助理(且未帶 --cli)。

參數

格式:[--schedule on|off] [--run] [--project-dir <專案根目錄>] [--cli <claude|codex|agy|opencode|copilot>] [--base <PR 目標分支>] [--no-pr] [--yes]

  • --schedule on|offon 建立/更新排程,off 移除排程。省略時不動排程。
  • --run:立即執行一次 TARGET.md(排程條目帶的就是這個)。
  • --project-dir <專案根目錄>:目標專案根目錄,省略時取目前工作目錄(會先 git rev-parse --show-toplevel 正規化成 repo 根)。TARGET.md 固定讀專案根目錄的那一份。
  • --cli <claude|codex|agy|opencode|copilot>:排程條目要用哪個助理的 headless 指令。省略時用目前正在執行本 skill 的助理;判斷不出來且未帶此參數 → 詢問,不猜測。
  • --base <PR 目標分支>PR 的目標分支。省略時自動取遠端預設分支(見 F1),取不到才詢問。
  • --no-pr:執行到 push 為止,不開 PR。
  • --yes:全自動,不做確認式詢問(必要決策仍會中斷)。

執行時間固定為每天 00:00(本機時區),不提供時間參數;要改時間請直接編輯排程條目。


TARGET.md 格式

專案根目錄的 TARGET.md,用 Markdown checklist 表示待辦:

# TARGET

- [ ] 補上使用者服務的單元測試
- [ ] 把 README 的安裝章節更新成新的 CLI 指令
  - [ ] 順便修掉裡面過期的截圖連結
- [x] 移除已停用的舊設定檔(2026/08/02 23:41:07 完成)
規則 說明
待辦 - [ ] 未勾選的項目,由上而下依序處理
已完成 - [x] 直接略過,不重做
子項目 縮排的 - [ ] 視為上層項目的子步驟,隨上層一起處理;子項目全部完成才勾選上層
標題/說明文字 原樣保留,只當作項目的背景脈絡,不改寫
檔案不存在 --run 視為「無待辦」正常結束(不建檔、不報錯);--schedule on 則提醒尚無 TARGET.md,非 --yes 時詢問是否仍要建立排程

完成一項後就地改成 - [x],並在該行行尾補上 <yyyy/MM/dd HH:mm:ss> 完成)Asia/Taipei)。無法安全完成的項目保持未勾選,並在該行下方以縮排補一行 > ⏭️ 待人工處理:<原因>(已有同樣註記則更新而非重複新增)。


階段 S:管理排程(--schedule on|off

S1. 判定 OS 與排程機制

uname -s   # Linux / Darwin / MINGW*|MSYS*|CYGWIN*(後者代表在 Windows 的 git bash
環境 機制 備註
Linux、WSL crontab WSL 的 cron 預設不會自動啟動,見 S5
macOS crontab 可用;若使用者偏好 launchd 需自行改寫,本 skill 不代為產生 plist
WindowsPowerShellcmd schtasks 每日任務

判斷不出環境時停止並回報,不臆測。

S2. 組出排程要執行的指令

proj="$(cd "<專案根目錄>" && git rev-parse --show-toplevel)"   # 絕對路徑
log="$HOME/.jsc/target-$(basename "$proj").log"

log 刻意放在專案外面:放進 repo 會讓每次執行都多出未追蹤檔,污染 D 階段的變更盤點。

各助理的 headless 指令(依 --cli):

--cli 指令
claude claude -p "/jsc-code:target --run --yes"
codex codex exec '$target --run --yes'(單引號,避免 $ 被 shell 展開)
agy agy -p "/jsc-code:target --run --yes"
opencode opencode run "執行專案根目錄 TARGET.md 的未完成項目,完成後分類提交、push develop 並對預設分支發 PR"
copilot copilot -p "執行專案根目錄 TARGET.md 的未完成項目,完成後分類提交、push develop 並對預設分支發 PR"

排程是非互動環境:助理若跳出工具權限詢問會直接卡住,排程等於沒跑。建立排程前要提醒使用者先在該專案預先授權(例如 Claude Code 於專案設定的 permissions.allow 列出所需工具,或在指令上加該助理的非互動旗標)。這牽涉安全取捨,由使用者決定,不代為加上略過權限的旗標

S3. 建立/更新排程(--schedule on

crontab(標記寫在行尾,一筆條目就是一行,安裝與移除都靠它比對):

marker="# jsc-code:target ${proj}"
entry="0 0 * * * cd '${proj}' && <headless 指令> >> '${log}' 2>&1 ${marker}"

mkdir -p "$(dirname "${log}")"
tmp="$(mktemp)"
crontab -l 2>/dev/null | grep -vF "${marker}" > "${tmp}"   # 先移除同專案的舊條目(更新用)
printf '%s\n' "${entry}" >> "${tmp}"
crontab "${tmp}"
rm -f "${tmp}"

crontab -l | grep -F "${marker}"                            # 驗證確實寫進去了
  • crontab -l 在「完全沒有排程」時會回非 0 並印錯誤,所以要 2>/dev/null不可因此把整份 crontab 當成空的覆寫——先確認 crontab -l 的失敗是「沒有排程」而不是權限問題。
  • 指令中若出現 %,crontab 會把它當換行,必須寫成 \%
  • 條目一律用絕對路徑cron 的 PATH 很精簡);若 command -v <cli> 得到的不是系統路徑,把 CLI 也寫成絕對路徑。

schtasksWindows):

$task = "jsc-code-target-<專案名>"    # 專案名重複時附加路徑短碼,確保唯一
schtasks /Create /TN "$task" /SC DAILY /ST 00:00 /F `
  /TR "cmd /c cd /d ""<專案絕對路徑>"" && <headless 指令> >> ""<log 絕對路徑>"" 2>&1"
schtasks /Query /TN "$task"          # 驗證

/F 只覆蓋同名任務(即本 skill 自己那筆),不影響其他排程。

S4. 移除排程(--schedule off

tmp="$(mktemp)"
crontab -l 2>/dev/null | grep -vF "# jsc-code:target ${proj}" > "${tmp}"
crontab "${tmp}"
rm -f "${tmp}"
crontab -l 2>/dev/null | grep -F "# jsc-code:target ${proj}" || echo "已移除"
schtasks /Delete /TN "jsc-code-target-<專案名>" /F
  • 找不到條目 → 回報「本來就沒有排程」,視為成功,不報錯。
  • 只刪自己標記的那一筆;其餘 crontab 內容原樣寫回。TARGET.md、log 檔、git 分支都不刪。

S5. 確認排程服務真的在跑(--schedule on 後必做)

排程條目寫進去 ≠ 會被執行。安裝後檢查:

pgrep -x cron >/dev/null || pgrep -x crond >/dev/null || echo "cron 服務未執行"
  • WSL 特別注意WSL 預設不啟動 cron,需要 sudo service cron start,且重開 WSL 後要再啟動一次(可寫進 /etc/wsl.confboot.command 或啟動腳本)。偵測到未執行時明確告知使用者這件事,不要只回報「排程已建立」。
  • Windowsschtasks /Query /TN "<任務名>" 能查到即可。

階段 AGit 同步(--run

A1. 盤點狀態

cd "<專案根目錄>"
git rev-parse --show-toplevel
git status --porcelain
git rev-parse --abbrev-ref HEAD
  • 工作區有未提交變更停止並回報(排程情境寫入 log)。理由:本 skill 結尾會分類提交所有變更,混入使用者未完成的工作會把它一起提交上去。依 /jsc-shared:spec-git-safety不得 stash、reset --hardclean 來清場。
  • detached HEAD → 停止並回報。

A2. Fetch 與判定遠端預設分支

git fetch --all --prune
git symbolic-ref --quiet refs/remotes/origin/HEAD    # → refs/remotes/origin/<預設分支>

取不到時退而用 git remote show origin(找 HEAD branch: 那行);--base 有帶則直接採用。兩者都不成立 → 停止並詢問,不臆測 mastermain

A3. 切到 develop(不存在就從預設分支建立)

if git rev-parse --verify --quiet origin/develop >/dev/null; then
  git switch develop 2>/dev/null || git switch -c develop --track origin/develop
  git pull --ff-only
else
  git switch -c develop "origin/<預設分支>"          # 遠端沒有 develop → 從預設分支開一條新的
fi
  • pull --ff-only 失敗(分岔)→ 停止並回報,交由使用者處理,不做 merge/rebase 猜測。
  • 本地已有 develop 但遠端沒有 → 沿用本地那條,不覆蓋、不重建;並在回報中說明它還沒推上遠端。
  • 新建 develop 屬不可忽略的狀態變更,必須在回報與 log 中明講「遠端沒有 develop,已從 <預設分支> 建立」。

階段 B:讀 TARGET.md 並盤點待辦

  1. <專案根目錄>/TARGET.md(UTF-8)。檔案不存在 → 回報「無 TARGET.md,無待辦」,正常結束(不進入 C~F、不 commit、不發 PR)。
  2. 解析出所有 - [ ] 未勾選項目(含子項目的從屬關係),依檔案由上而下的順序排定執行順序。
  3. 全部都是 - [x] → 回報「TARGET.md 已全部完成」,正常結束。
  4. 輸出待辦清單表,除非使用者要求確認,否則直接進入階段 C:
# 項目 子項目數 備註

階段 C:逐項實作並回寫 TARGET.md

依 B 的順序,一次做一項,做完一項就回寫 TARGET.md(中途失敗時已完成的進度不會遺失):

  1. 讀懂該項目要什麼;必要時讀相關程式碼與文件確認脈絡。
  2. 語意不明、範圍不清、或牽涉設計取捨無法安全決定 → 不硬做。保持未勾選、補上 > ⏭️ 待人工處理:<原因>,繼續下一項。
  3. 實作最小且合理的變更;能驗證的就驗證(該專案既有的 build/test 指令)。驗證失敗且無法安全修正 → 比照第 2 點標記待人工處理,並還原該項目造成的變更,不留半成品。
  4. 完成 → 把該行改成 - [x] 並於行尾補 <yyyy/MM/dd HH:mm:ss> 完成);有子項目則子項目全部完成後才勾選上層。
  5. 每項結束記錄結果( 完成 / ⏭️ 待人工處理+原因),供階段 G 總結。

TARGET.md 一律以 UTF-8(不含 BOM)寫回,結尾保留一個換行;只改動勾選狀態與完成時間/待人工註記,其餘內容原樣保留。


階段 D:分類提交

  1. 盤點所有變更(含未追蹤檔):

    git status --porcelain=v1 -uall
    
  2. 依實際異動內容歸入 conventional commit 類型(featfixdocsstylerefactorperftestchorerevert),每個 type 各一個 commit

  3. commit 訊息格式 type(範圍): 一句總結括號內是實際異動的功能/模組名,不是重述 type

    • feat(使用者服務): 補上帳號建立與停用的單元測試docs(README): 更新安裝章節的 CLI 指令
    • feat(新增功能)docs(文件)
    • TARGET.md 本身的勾選更新歸 chore,訊息用 chore(TARGET): 更新每日待辦完成狀態
  4. 逐組精準 git add -- <該組檔案...> 後 commit,不用 git add -A 一次混提。

  5. 無任何變更(例如所有項目都待人工處理,只有 TARGET.md 的註記異動)→ 仍照常提交 TARGET.md 的異動;連 TARGET.md 都沒變則跳過 D、E、F,直接進入總結。

分類與訊息規則與 /jsc-code:review-resolve 階段 C 一致,細節可參照該 skill。


階段 EPush develop

git log --oneline "origin/develop..develop" 2>/dev/null   # 領先遠端的 commit;遠端無 develop 時視為全部要推

無 commit 可推 → 跳過 push,直接進入階段 F(既有遠端分支仍可開 PR)。否則依序嘗試,前者失敗才換下一個:

  1. 認證管理器git push -u origin develop

  2. token:從環境變數帶入,指令與輸出全程遮蔽 token、不寫進 remote 設定

    git push "https://oauth2:${GITEA_TOKEN}@<host>/<owner>/<repo>.git" develop
    
  3. 都失敗 → 停止並回報失敗原因(先遮蔽 token)。排程情境寫入 log,等使用者處理,不猜測其他憑證。


階段 F:對預設分支發 PR--no-pr 時略過)

F1. 目標分支

--base 有帶則用它,否則用 A2 判定出的遠端預設分支。若預設分支就是 develop(等於 head=base)→ 不開 PR,回報原因即可。

F2. 先查有沒有現成的 open PR(每天跑,不可重複開)

curl -sS -H "Authorization: token ${GITEA_TOKEN}" \
  "https://<host>/api/v1/repos/<owner>/<repo>/pulls?state=open&base=<預設分支>"

已存在 head=developbase=<預設分支> 的 open PR → 沿用它(今天新推的 commit 會自動出現在該 PR),回報既有 PR 連結,並視情況在該 PR 補一則今日進度留言;不重複建立

F3. 建立 PR

repo 座標由 git remote get-url origin 解析(hostownerrepo)。body 以 UTF-8 JSON 檔帶入,換行用實際換行、不可送出字面 \n

curl -sS -X POST \
  -H "Authorization: token ${GITEA_TOKEN}" \
  -H "Content-Type: application/json" \
  "https://<host>/api/v1/repos/<owner>/<repo>/pulls" \
  --data @body.json
  • 標題chore(TARGET): <yyyy/MM/dd> 每日待辦(有明確主軸時可改成該主軸的一句總結)。
  • 描述:本次完成的項目清單(⏭️ 各自列出+待人工處理原因)、變更摘要與影響範圍、本次的 commit 一覽。
  • 失敗 → 回報 API 錯誤訊息(先遮蔽 token)。常見原因:目標分支不存在、已有相同 head→base 的 PR(回到 F2 沿用)、token 權限不足。

F4. 收尾

pushAPI 過程可能讓 token 殘留在對話內文;互動情境完成後提醒使用者清除對話(Claude Code 用 /clear)。排程情境只寫 log,不輸出 token。


總結

執行後輸出(排程情境同時以 [時間][階段][等級]: 訊息 寫入 log):

模式 要回報的內容
--schedule on 用了哪種機制(crontabschtasks)、條目內容、log 路徑、排程服務是否在跑(WSL 未啟動 cron 要明講)、下次執行時間
--schedule off 移除了哪一筆、其餘排程未受影響
--run 待辦總數/ 完成 N 項/⏭️ 待人工處理 K 項(逐項原因)、develop 是新建還是既有、建立了哪幾個 commit、push 結果與方式、PR 連結(新建或沿用既有)、或為何略過
無參數 排程狀態+下次執行時間、TARGET.md 是否存在與剩餘未完成項目數

呼叫方式

助理 呼叫
Claude Code / Antigravity /jsc-code:target --schedule on/jsc-code:target --schedule off/jsc-code:target --run --yes/jsc-code:target --schedule on --run --project-dir ~/work/app
Codex $target --schedule on$target --run --yes,或用 /skills 選單
OpenCode 描述需求(如「幫我把這個專案的 TARGET.md 排成每天 00:00 自動執行,做完分類提交、push develop 並對預設分支發 PR」)自動觸發