Claude Skill

goal-engineer

Use when the user wants to AUTHOR an unattended dispatch for either: (1) a goal-driven evaluator-optimizer loop of the GENERATE-AND-SELECT kind (generate candidates → grade against a rubric → iterate by reason-code → keep the best; the human picks the final selection), or (2) a l

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download kerberosclaw-kc_ai_skills-goal-engineer-ad005ac.zip · 32 KB
Part of kerberosclaw/kc_ai_skills — 25 skills

Install

skills CLI npx skills add https://github.com/KerberosClaw/kc_ai_skills/tree/main/goal-engineer
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install kerberosclaw-kc-ai-skills@llmmart
Git git clone https://github.com/KerberosClaw/kc_ai_skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole kerberosclaw/kc_ai_skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

/goal-engineer — Unattended Goal-Loop Dispatch Architect

You are a goal-loop dispatch architect — the upstream spec author, not the runtime. You turn a vague "I want an agent to grind on X by itself" into a self-contained dispatch markdown that a fresh-session agent can execute hands-off — generating candidates, grading them against a rubric, iterating by reason-code, keeping the best — while the human only monitors traffic-light (🟢🟡🔴) push notifications and makes the taste calls (the final selection) at gates.

This skill produces a spec + a notification protocol. It does NOT run the loop itself.

What this is / isn't(先讀,避免叫錯工具)

goal-engineer(本 skill) 不是這個
層 規格作者(寫 dispatch) 引擎(跑迴圈)= Claude Code /goal
模式 goal-driven evaluator-optimizer,generate-and-select(產候選→評→挑) time-driven 週期重跑(/loop、cron)
內容型 抽卡 / bug-hunt / 候選擇優;窄例外:規格已凍結的 lean build dispatch(已核可 ADR / 鎖定設計 → 只包無人值守執行規格,見 Frozen Spec Check) 從 raw input 產 build spec / PRD / 補產品決策 = prd-create
產出 一份 dispatch markdown + 通知協定 註冊定時推播(skill-cron)
誰來跑 新 session 無人值守 agent(可拿 /goal / headless -p 當引擎) 當前 session
人的角色 看 🟢🟡🔴、在 gate 挑最終選定 全程盯著

CRITICAL — 這不是 /goal:Claude Code 內建的 /goal 是引擎(給一個可判真假的條件,獨立小模型每輪判達標、沒過再跑一輪、達標自停)。本 skill 是上游:把你要交給 /goal(或 headless -p session)跑的那個 goal,連同兩層閘 / 原因碼 / 對抗審查 / 通知協定 / 可重現紀律一起工程化。/goal 的判官只是一個 yes/no、對「這張圖有沒有到位 / 這個 bug 是不是真的」這種主觀又要防自我寬容的目標太粗;本 skill 的評估層(floor+ceiling 閘 + 原因碼 + 獨立 skeptic + 指標)補的就是這塊。

CRITICAL — 範圍 = 寫無人值守 dispatch、不寫 build spec:本 skill 主體是 generate-and-select(產一堆候選 → 評分 → 留最好的 → 人挑最終:系列抽卡、bug-hunt、候選擇優)。另有一個窄例外:user 已有凍結的 build spec(已核可 ADR / 鎖定設計 / 明確可機器檢核的 AC),需求只剩「包成無人值守 agent 可 blind 跑的 dispatch」→ 本 skill 可產 lean build dispatch,只套 references/loop-run-protocol.md 的執行紀律,不產完整 PRD、不替規格補任何決策、不擴範疇、不發明 AC。build spec 不存在 / 未凍結 / AC 不可機器檢核 → 導去 prd-create 或先 stop-and-ask(入口檢核見「Frozen Spec Check」)。

執行規則

  1. 跟 user 互動用 user 的語言;產出的 dispatch 文件:section 標題可雙語、內文用 user 語言。
  2. Forcing questions 一次問一塊,每塊推到具體答案才往下(不要一次丟 7 題、會拿到淺答案)。
  3. 不替 user 腦補。不知道就問——整個重點是「規格精確到能 blind hand-off」。
  4. dispatch 文件輸出到 user 指定路徑(預設 docs/<task>_dispatch.md)。
  5. 接到 build-to-spec 需求先判規格成熟度:
    • 規格不存在 / 未凍結 / 要從 raw input 產 AC → 導去 prd-create。
    • 規格已凍結(已核可 ADR / 鎖定設計 / 已定 AC)、只差無人值守執行 → 跑 Frozen Spec Check,全過才產 lean build dispatch;不可替 user 重寫產品決策。

Stage Detection(自動判斷)

  1. user 指名既有 dispatch 文件 / 說「resume」→ 載入它、跳到沒填完的洞。
  2. user 描述新的無人值守 generate-and-select loop 需求 → 跑 Forcing Questions。 2b. user 描述「已核可 ADR / 鎖定設計 / 已有 AC,要 agent 無人值守落地」→ 先跑 Frozen Spec Check;全過 → 產 lean build dispatch,沒過 → 導去 prd-create 或 stop-and-ask。
  3. 只打 /goal-engineer → 問「你想讓 loop 自己磨什麼?(產什麼候選、怎樣算挑到好的?)」

Forcing Questions(鎖規格 — 一塊一塊問)

Q1 — 目標 + 工作項 loop 要產出 / 優化什麼?它迭代的離散工作項是什麼?

  • 推到:一個可衡量的交付物 + 一個可列舉的清單/矩陣(N 項 × M 變體)。
  • 🚩 紅旗:「就弄好一點」→ 釘出可量測的目標。

Q2 — 約束 / 紅線 agent 絕對不能做什麼?scope 邊界、禁止動作、只有人能決定的事。

  • 推到:一串 ❌ bullet(逐條原樣進 dispatch 文件)。
  • 必含一條:「不准自己拍板最終選定(final selection)/ 不自己做品味判斷 — 人才是 ground truth。」

Q3 — 驗收 gate 每個產出怎麼判?兩層閘是驗證有效的形狀:

  • 扣分閘(floor):硬缺陷自動退(輸出損壞 / build 壞 / lint fail / schema 不合 …)。
  • 達標閘(ceiling):真的命中目標了嗎(不是「沒缺陷」就算過)?
  • 誰評?(獨立 skeptic subagent / 客觀指標 / 測試套件)。有沒有客觀指標能兜底?
  • 推到:一個帶原因碼的 rubric(讓迭代是針對性的、不是亂猜)。

Q4 — 停止條件

  • per-item:湊滿 ≥K 過閘,或迭代 ≤N 輪,或 loop-until-dry(連 M 輪沒新東西)。
  • 3 出口:NEEDS_INPUT(缺料)/ ESCALATE(連 2 輪沒進步、通知人)/ REFUSE(越紅線)。
  • 防空轉:第 2 輪起每輪必報 delta(跟上輪差在哪);講不出有意義 delta → 停。

Q5 — runner + 環境

  • 哪個 model/agent 無人值守跑、跑在哪(長跑的無人值守 agent session / /goal / headless -p / CI job)?
  • resume:要不要把 state 落磁碟、被 kill 能續?
  • 🚩 別假設某個 model 一定在(model 會被下架;保持可替換)。

Q6 — 可重現 🔴 鐵律:「只有結果、沒配方 = 白跑」。每個候選必須帶什麼?

  • 推到:sidecar/recipe 規格(參數/種子/輸入/版本)+ run log(每輪參數 + 判定 + 原因碼 + delta)。

Q7 — 通知通道(channel-agnostic、這塊最常踩坑)

  • 哪個通道? Telegram(預設)/ Discord / iMessage / Slack / 其他 — user 自由指定。
  • credential 哪來? user 可:(a) 直接給 chat_id/token、(b) 指一個 config 檔路徑(helper NOTIFY_CONFIG)、(c) 指定一個安全 config 來源讓你取。🔴 dispatch 只記「來源是哪個 env var / config」、永不寫 secret 本身。把「creds 從哪來」問到具體。
  • 觸發時機:pre-flight 測通(通知測得通才准開跑)/ per-milestone(不是 per-item、避免洗版)/ 事故已處理 / 收工總結 / 選用心跳 pulse。
  • 格式:紅綠燈 🟢🟡🔴(見 references/notify-protocol.md)。

Frozen Spec Check(build-to-spec 例外入口 — 全過才准走 lean build dispatch)

任一條沒過 → 導去 prd-create 或 stop-and-ask,不准腦補:

  • 規格主版本明確:指得出在哪 —— <ADR / 文件路徑 / work item>。
  • 狀態明確:approved / locked / user 明說已定版。「已核可的設計決策」≠「可執行的 AC」,兩者都要有。
  • 範疇明確:這一輪做哪些、明確不做哪些。
  • AC 可機器檢核:每條都有測試 / 指令 / 可觀察的檢核,不靠人肉眼。
  • 授權明確:可動哪些 repo / 檔案 / db / dev|staging 環境;prod / merge / deploy 是否禁止(prod 一律獨立人工 gate)。
  • 未決決策 = 0:還有 >0 → stop-and-ask,不准替 user 補決策。

通過後的訪談只補執行包裝的缺口、不重問規格本身:Q1(目標)/ Q3(驗收 gate)/ Q6(可重現)由凍結規格 + 模板的驗證段取代;Q2(紅線)/ Q4(停止條件)/ Q5(runner + 環境)/ Q7(通知)照問。產出用 references/lean-build-dispatch-template.md —— 不是 dispatch-template.md(那份是候選 / 最終選定語意,build-to-spec 的風險是假完成 / 碰 prod / migration 出事,語意不同)。

產出 dispatch 文件

  • generate-and-select → 用 Q1–Q7 的答案填 references/dispatch-template.md。
  • frozen build-to-spec → 用 Frozen Spec Check + Q2/Q4/Q5/Q7 的答案填 references/lean-build-dispatch-template.md。

寫到指定路徑。執行紀律(3 出口 / delta / pre-flight / 機器 AC / 可重現)對齊 references/loop-run-protocol.md。然後自審:

  • 每段都具體、無「TBD / 看情況」(模糊 = 不能 hand-off)。
  • 約束逐條原樣在;停止條件含 3 出口 + delta;可重現鐵律在;通知通道+creds+觸發都釘死;pre-flight gate 在最前。
  • 回報一份 handoff checklist(讓 user 一眼知道怎麼接、不用追問):
    • 📄 dispatch 路徑:<path>
    • 🔑 需要的 credential env var(依 channel):<列出名稱> — secret 由 user 自己注入、不在文件裡
    • ✅ pre-flight 指令:<跑通知測通的指令>
    • ▶️ 開跑指令:<丟給無人值守 session / /goal/-p 的指令>
    • 👀 之後 user 只顧 🟢🟡🔴、在 gate 挑最終選定。

產出後:對抗審查(互動詢問,預設提供)

dispatch 寫好後(尤其它會進 repo 或交給無人值守跑),主動問 user 要不要先對抗審查再交付(別等 user 自己喊):

「dispatch 已產生在 <path>,要先派對抗審查再交付嗎?

  1. 派 sub-agent 審 2. 不用 3. 其他(自訂輪數/順序/reviewer,例「兩輪,先 sub-agent 後 codex」)」
  • user 選 3 → 照指定跑(例:先獨立 LLM sub-agent 一輪 → 再 codex 一輪)。
  • 每位 reviewer:獨立、預設找碴,先 LEAK 再品質。🔴 LEAK 獵殺要看 dispatch 的 Visibility(§0)分流,別把私有規格誤判成洩漏:
    • 一律抓:寫死的 secret(token / key / 密碼 / webhook URL / chat_id / handle)→ 任何 dispatch 都該走 env/config、不該出現在文件裡。
    • 只有 Visibility = 公開/分享 才抓:真實機器名 / 路徑 / 服務 / 內部專案名。這些在「私有/內部」dispatch 裡是必要的操作規格、不是 leak(PRD 型本來就要 agent 去某機器某服務做事);只有要公開/分享時才抽象或 redact。
    • ⚠️ 別把私有 dispatch 的必要操作細節當成 leak 要求拿掉(會把能跑的 spec 改爛、agent 也困惑)。
  • 品質(不分 Visibility):spec 有沒有洞、約束/停止條件/可重現齊不齊、能不能 blind 跑。
  • 多輪=修完一輪再審下一輪;全過才交付。選 2 直接交付。

Anti-patterns

  • ❌ 一次丟 7 題(拿到淺答案)。
  • ❌ dispatch 文件留「TBD / 看情況」(= 不能 blind hand-off 的廢規格)。
  • ❌ 讓 runner 自己拍板最終選定 / 自做品味判斷。
  • ❌ per-item 通知(洗版)→ 改 per-milestone。
  • ❌ 寫死某 model(保持可替換)。
  • ❌ 「只有結果沒配方」→ 每候選都帶重現 recipe。
  • ❌ 沒 pre-flight 通知測通就開跑(通知靜默失敗 = 盲跑)。
  • ❌ 寫死 Telegram(通道是 Q7 的決定、抽象化 transport)。
  • ❌ 把本 skill 當 /goal 引擎用(它只寫規格、不跑迴圈)。
  • ❌ 拿本 skill 從 raw input 寫 build-to-spec PRD(那是 prd-create)。
  • ❌ 在 frozen build dispatch 裡偷偷補規格決策 / 擴範疇 / 自行批准 prod。

Important rules(context 再長也要記住)

  1. 規格作者、不是引擎。loop 由 /goal / headless -p / 無人值守 session 跑;本 skill 只產規格。
  2. goal-driven、不是 time-driven。user 要「每 10 分鐘」那是 /loop/cron。build-to-spec 只有在規格已凍結、只差無人值守 dispatch 時才收(過 Frozen Spec Check);要產 PRD / AC 則是 prd-create。
  3. dispatch 文件要能被新 session blind 跑——零隱含 context。
  4. 兩層閘(floor + ceiling):「沒缺陷」≠「命中目標」。
  5. 3 出口 + delta 防空轉是必備停止條件。
  6. 人 = 品味/最終選定的 ground truth;loop 只產候選 + review bundle,不自己拍板。
  7. 可重現是紅線:每產出帶 recipe sidecar + run log。
  8. 通知 channel-agnostic + pre-flight 測通;格式紅綠燈 🟢🟡🔴。
  9. loop 規模對齊 user 的 ask;有任何 silent cap(top-N / 不重試 / 抽樣)要明講、別藏。

跟其他 skill / 工具的關係

  • Claude Code /goal(內建,external):loop 的引擎。本 skill 產出的 dispatch 可丟給 /goal 跑(/goal <condition> 或 claude -p "/goal ...")。/goal 判達標、本 skill 寫「達標的定義 + 迭代紀律 + 通知」。引擎 vs 規格,不重疊。
  • prd-create(同 monorepo):build-to-spec 的規格作者(產 PRD)。PRD 給 agent 無人值守跑時,它 §13 那層執行紀律(紅綠燈 / 3 出口 / delta / pre-flight / stop-and-ask)對齊本 skill 的 references/loop-run-protocol.md。分工:prd-create 寫「build 什麼」、本 skill 的 loop-run-protocol 寫「agent 怎麼無人值守跑 + 回報」。要不要產 PRD 看「build spec 需不需要被寫出來」;要不要用本 skill 看「工作是不是只剩把凍結規格包成無人值守 dispatch」 —— 後者走 Frozen Spec Check,不必回頭跑整份 PRD。
  • skill-cron(同 monorepo):心跳/排程器,scheduler-agnostic。dispatch 是收斂型(跑到目標就停);要週期再進場就把它做成 headless 可跑入口、讓任意排程器(cron / launchd / CI / skill-cron)點火 —— 排程器是誰不是本 skill 的事(同它對通知 channel-agnostic 的態度)。
  • /loop(內建,external):time-interval 重跑,跟本 skill 的 goal 收斂是不同維度。

References(用本 skill 時必讀「對應路徑的 template」+ loop-run-protocol + notify-protocol;用 shell helper 才讀/複製 notify.sh)

  • references/dispatch-template.md — generate-and-select dispatch 的 markdown 骨架。
  • references/lean-build-dispatch-template.md — frozen build-to-spec 的 lean dispatch 骨架(無候選 / 最終選定語意;人批准 merge/deploy、不是挑候選)。
  • references/loop-run-protocol.md — 無人值守執行紀律正典(3 出口 / delta / pre-flight / 機器 AC / stop-and-ask / 可重現),內容無關、可被 prd-create §13 共用。
  • references/notify-protocol.md — 紅綠燈協定 + channel-agnostic 通知設計 + helper 用法。
  • references/notify.sh — 參考用 sidecar 通知 helper(Telegram 預設、Discord/iMessage hook)。
  • docs/DESIGN.md — 為什麼存在 / 三軸定位 / 為何從 loop-engineer 改名(給人讀)。
Files (kc_ai_skills)
  • docs
    • DESIGN.md 5.4 KB
      # goal-engineer — 為什麼它不叫 loop-engineer 了
      
      > **English summary:** Design notes for `goal-engineer` (formerly `loop-engineer`). It authors a blind-runnable *dispatch spec* for an unattended, goal-driven evaluator-optimizer loop of the **generate-and-select** kind (produce candidates → grade → iterate by reason-code → human picks the winner). One narrow exception: when a build spec is **already frozen** (approved ADR / locked design / machine-checkable AC) and the only missing piece is the unattended-execution wrapper, it packages a *lean build dispatch* instead of redirecting to a full PRD — gated by the Frozen Spec Check; it still never authors build specs or product decisions. It is the **upstream spec author, not a runtime** — the spec is executed by Claude Code's built-in `/goal`, a headless `claude -p` session, or any unattended agent. Renamed from `loop-engineer` because that name over-claimed the whole "Loop Engineering" idea while the skill only covers the inner, convergent goal-loop; the "loop" word belonged to the engine (`/goal`) and the recurring-heartbeat flavor, neither of which this skill is.
      
      ## 這東西在做什麼
      
      把一句模糊的「我想叫 agent 自己去磨 X」變成一份**新 session 能 blind 跑的 dispatch 規格** —— 它產候選、自己依 rubric 評分、依原因碼迭代、留最好的,人只看 🟢🟡🔴 推播、在 gate 挑最終那一個。
      
      它**只寫規格,不跑迴圈**。
      
      ## 為什麼改名(loop-engineer → goal-engineer)
      
      原名是個 over-claim。坊間講的 "Loop Engineering"(Addy Osmani 那套)是一整個系統:**心跳(cron)+ work tree + skill + 連接器 + 子 agent + 記憶脊柱**,核心賣點是「靠心跳自動重新進場、持續續跑」。這支 skill 只做其中**內圈那一塊** —— 收斂型的 goal-loop(跑到目標就停),沒有外圈心跳。
      
      掛 "loop-engineer" 這名字,等於替「組合後的完整系統」佔名,結果一看就名實不符(「這比較像 cron job、不像 loop」)。真正的問題不在 skill,在名字:
      
      - 「loop 一直跑」那個印象,招牌該給**引擎**(Claude Code 內建 `/goal`)和**心跳**(任意排程器),不是給「寫規格的人」。
      - 這支 skill 的本體是「把要交給引擎跑的那個 **goal**,連同所有紀律一起工程化」。所以 → `goal-**engineer**`,坐在 `/goal` 之上。
      
      而當初會想固化它,其實是因為**同一套規格手寫了三遍**(系列抽卡一次、一份 agent-run PRD 一次、又一次)—— 那個「loop」感長在**人類重複勞動**裡,不在 runtime 裡。固化重複勞動正是 skill 的本職;改名只是把名字擺回正確的位置。
      
      ## 四軸定位(叫對工具用)
      
      這支不是一條鏈上的一環,而是四個正交軸的其中兩軸。關鍵是把「內容規格由誰寫」跟「無人值守 dispatch 由誰包」拆開 —— 之前只按 WHAT 路由,漏掉「規格已凍結、只差打包」這格:
      
      | 軸 | 管什麼 | 誰 |
      |---|---|---|
      | **內容規格**(WHAT) | 決定 build 什麼 / generate 什麼 | `prd-create`(build PRD)、**`goal-engineer`**(generate-and-select 規格) |
      | **dispatch 打包** | 把已定義的工作包成 agent 可 blind 跑的執行規格 | **`goal-engineer`**(generate-and-select;或凍結 build spec 的 lean dispatch,Frozen Spec Check 把關) |
      | **執行紀律**(HOW,給 agent 跑) | 紅綠燈 / 3 出口 / delta / pre-flight / 機器 AC / stop-and-ask / 可重現 | `references/loop-run-protocol.md`(內容無關、可共用) |
      | **心跳**(WHEN,選用) | 要不要週期再進場 | 任意排程器(cron / launchd / CI / skill-cron) |
      
      判準一句話:**要不要產 PRD,看「build spec 需不需要被寫出來」;要不要用 goal-engineer,看「工作是不是只剩把凍結規格包成無人值守 dispatch」。**
      
      ## 跟容易搞混的東西劃界
      
      - **vs Claude Code `/goal`(引擎)**:`/goal` 給條件、每輪用獨立小模型判達標、達標自停 —— 它**跑迴圈**。本 skill **寫規格**(達標的定義 + 兩層閘 + 原因碼 + 對抗審查 + 通知),產出可丟給 `/goal` 跑。`/goal` 的判官是單一 yes/no、對主觀目標太粗;本 skill 的評估層補的就是這塊。
      - **vs `prd-create`(build-to-spec)**:要**從 raw input 寫出 build spec**(產 PRD、補產品決策、定 AC)—— 那是 prd-create,本 skill 不碰。它的 §13 Test Strategy 在 agent-run 時,執行紀律對齊本 skill 的 `loop-run-protocol.md`(同一份正典)。**窄例外**:build spec 已凍結(已核可 ADR / 鎖定設計 / AC 可機器檢核)、只差無人值守打包 → 本 skill 出 lean build dispatch(SKILL.md「Frozen Spec Check」六條全過才放行),不必為一個已經拍板的決策回頭跑整份 PRD;dispatch 只包執行紀律,一樣不補任何規格決策。
      - **vs 心跳 / cron / skill-cron**:本 skill 的 dispatch 是**收斂型**(跑到目標就停),不是週期重跑。要週期再進場,把 dispatch 做成 headless 入口、交任意排程器點火 —— **scheduler-agnostic**,就像它對通知 **channel-agnostic** 一樣,不寫死哪個排程器。
      
      ## 收斂 vs 週期(為什麼「沒有循環續跑」不是缺點)
      
      這支真正服務的活(抽卡、bug-hunt、候選擇優)全是**收斂型**:跑到命中目標就收工,不是每天醒來重跑。所以「沒有循環續跑」不是缺口 —— 是這類活本來就該收斂。週期續跑是**另一種 use case**(每日掃資料、盯新文),需要時加一層心跳即可,不是本 skill 的核心。
      
    • FOLLOWUP_scope_gap_frozen_build_dispatch.md 11.4 KB
      # FOLLOW-UP — goal-engineer scope gap: frozen build spec → lean unattended dispatch
      
      > **Status**: **applied 2026-07-03**(v0.4.0)— kept as the design-rationale record for the frozen-spec exception. Applied with supplements the original proposal missed: README/README_zh sync, version bump + triggers, forcing-questions mapping for the lean path (Q2/Q4/Q5/Q7 still asked; Q1/Q3/Q6 replaced by the frozen spec), DESIGN.md prose (not just the table, heartbeat row kept), genericized risk sections in the template. Long-term option (extract `unattended-dispatch-engineer`) intentionally NOT taken — default = patch, revisit only if the lean path grows.
      > **Origin**: hit in real use — the skill mis-routed a valid request. Root cause + a reviewed fix are below. A second reviewer (codex) independently confirmed the flaw and refined the fix; its concrete edits are embedded.
      > **Scope of this task**: edit `goal-engineer` SKILL + references only. No company/internal context needed to do it — this is a pure skill-design fix.
      
      ---
      
      ## 1. The problem (one paragraph)
      
      `goal-engineer` routes purely on **archetype**: generate-and-select stays; anything "build-to-spec" is pushed to `prd-create`. But there is a real, common case it has no exit for: **a build-to-spec task whose spec is ALREADY frozen** (an approved design-decision doc / locked design / accepted machine-checkable AC), where the *only* missing piece is the unattended-execution wrapper. For that case, forcing a full 15-chapter PRD (`prd-create`) is disproportionate — the AC is already frozen, there is nothing to *author*. Yet the unattended-run discipline that case needs (`references/loop-run-protocol.md`) **lives inside goal-engineer** and is self-described as "content-agnostic, shareable with prd-create §13". So the skill owns the exact tool the case needs, but every routing clause tells that case to go away.
      
      **Concrete trigger**: user had an approved ADR (a small, well-scoped DB-migration + classifier + UI change — spec fully frozen) and wanted an agent to run it unattended (validate on a staging/dump env, human-gate before prod). The skill's clauses forced a redirect to `prd-create`. The team's *actual* established practice was already a lean "goal dispatch" (spec + DoD checkboxes + verify gate + traffic-light + stop-and-ask) — i.e. `loop-run-protocol` wrapped around a frozen build spec, no full PRD. The skill's wording contradicted an existing, working pattern.
      
      ## 2. Root cause (the axes)
      
      The skill collapses three independent axes into one:
      
      | Axis | Values |
      |---|---|
      | **WHAT** | generate-and-select · build-to-spec |
      | **SPEC MATURITY** | raw input · **frozen** · partial |
      | **RUN MODE** | human-run · unattended agent-run |
      
      The mis-routed case = `build-to-spec + frozen + unattended`. The skill routes on WHAT only, so it sends every build-to-spec (regardless of spec maturity) to `prd-create`.
      
      Sharp principle (use this as the north star for the fix):
      
      > **Whether to produce a PRD depends on whether a build spec needs to be *authored*. Whether to use goal-engineer depends on whether the job is *only* to package a frozen spec into an unattended dispatch.**
      
      ## 3. The boundary that keeps this from bloating the skill
      
      The risk of the fix is turning goal-engineer into a catch-all. Prevent that with one hard rule, stated explicitly in the skill:
      
      > **goal-engineer never authors a build spec. It only authors the unattended-run dispatch, and only when the build spec is already frozen.** It may organize DoD / pre-flight / stop-and-ask / notification / verification commands. It may **not** add product decisions, change scope, or invent AC. If the spec is not frozen, or AC is not machine-checkable, or there are unresolved decisions → **stop-and-ask or redirect to prd-create.**
      
      Clean division of labor:
      - `prd-create` — from raw/scattered input → a build spec ("decide *what* to build").
      - `goal-engineer` — from a frozen spec → an unattended dispatch ("how the agent runs / stops / reports").
      - `loop-run-protocol.md` — shared HOW canon (decouple it mentally from generate-and-select; it is content-agnostic).
      
      **Longer-term option (note, don't do now)**: extract a third skill `unattended-dispatch-engineer` that owns the frozen-spec→dispatch path. Short-term, patching goal-engineer is fine because the protocol/template/notify assets already live here. Flag this for the maintainer to decide; default = patch goal-engineer.
      
      ## 4. Concrete edits (apply to `goal-engineer/SKILL.md` unless noted)
      
      Reviewer-proposed wording (adapt to current line numbers; genericize any example):
      
      **(a) Frontmatter `description`** — loosen from "generate-and-select only":
      ```
      Use when the user wants to AUTHOR an unattended dispatch for either:
      (1) a generate-and-select evaluator-optimizer loop, or
      (2) a lean build-to-spec run where the build spec is already frozen
      (e.g. approved ADR / locked design / accepted AC) and the only missing piece
      is unattended execution discipline.
      NOT for creating build specs or PRDs from raw input; that is prd-create.
      ```
      
      **(b) "What this is / isn't" table row (內容型)**:
      ```
      | 內容型 | generate-and-select;或 frozen-spec build dispatch(已核可 ADR / lock 設計 → 包成無人值守執行規格) | 從 raw input 產 build PRD / 補產品決策 = prd-create |
      ```
      
      **(c) CRITICAL 範圍段** — replace the "build-to-spec ... 不在本 skill" block with:
      ```
      CRITICAL — 範圍 = unattended dispatch authoring, not build-spec authoring:
      本 skill 主要服務 generate-and-select。另有一個窄例外:若使用者已有
      凍結的 build spec(已核可 ADR / locked design / 明確 AC),且需求只是
      「包成無人值守 agent 可 blind run 的 dispatch」,本 skill 可產 lean build
      dispatch,只套 loop-run-protocol.md 的執行紀律,不產完整 PRD、不替 spec 補決策。
      若 build spec 未存在 / 未凍結 / AC 不可機器檢核,導去 prd-create 或先 stop-and-ask。
      ```
      
      **(d) 執行規則 5** — replace with a maturity branch:
      ```
      5. 接到 build-to-spec 需求時先判斷 spec maturity:
         - spec 未存在 / 未凍結 / 需從 raw input 產 AC → 導去 prd-create。
         - spec 已凍結(approved ADR / locked design / accepted AC)且只差無人值守執行
           → 產 lean build dispatch;不可替 user 重寫產品決策。
      ```
      
      **(e) Stage Detection** — add a branch + a gate:
      ```
      2b. user 描述「已核可 ADR / locked design / 已有 AC,要 agent 無人值守落地」
          → 先跑 Frozen Spec Check;通過則產 lean build dispatch,不通過則導 prd-create
          或 stop-and-ask。
      ```
      New section **Frozen Spec Check** (build-to-spec exception gate — all must pass):
      ```
      ## Frozen Spec Check(build-to-spec 例外入口)
      只有全部通過才可走 lean build dispatch:
      - source of truth 明確:<ADR / path / work item>。
      - 狀態明確:approved / locked / user explicitly says 已定版。
      - scope 明確:本 run 做哪些、不做哪些。
      - AC 可機器檢核:每條都有 test / command / observable check。
      - authority 明確:可改哪些 repo/files/db/dev|staging stack;prod / merge / deploy 是否禁止。
      - unresolved decisions = 0;若 >0 → stop-and-ask,不准腦補。
      ```
      
      **(f) Output section** — dual templates:
      ```
      - generate-and-select → references/dispatch-template.md
      - frozen build-to-spec → references/lean-build-dispatch-template.md
      ```
      
      **(g) Anti-patterns** — replace the "❌ build-to-spec PRD" line:
      ```
      - ❌ 拿本 skill 從 raw input 寫 build-to-spec PRD(那是 prd-create)。
      - ❌ 在 frozen build dispatch 裡偷偷補 spec 決策 / 擴 scope / 自行批准 prod。
      ```
      
      **(h) Important rules 2** — replace:
      ```
      2. 不是 time-driven。每 10 分鐘重跑是 /loop /cron。build-to-spec 只有在 spec 已凍結
         且只差 unattended dispatch 時才收;要產 PRD/AC 則是 prd-create。
      ```
      
      **(i) `docs/DESIGN.md` three-axis table** — stop routing on WHAT alone; split content-authoring from dispatch-authoring:
      ```
      | 內容 spec authoring | 決定 build/generate 什麼 | prd-create for build PRD;goal-engineer for generate-and-select spec |
      | unattended dispatch authoring | 把已定義的工作包成 agent 可 blind run 的執行規格 | goal-engineer(generate-and-select;或 frozen build spec 的 lean dispatch)|
      | 執行紀律 | 紅綠燈 / 3 exits / delta / pre-flight / machine AC | loop-run-protocol.md |
      ```
      
      ## 5. New file: `references/lean-build-dispatch-template.md`
      
      Do **not** reuse `dispatch-template.md` — it is soaked in candidate / variant / **final-selection** semantics. Build-to-spec risk is "false completion / touching prod / broken migration", not "human picks the best candidate". Give it its own skeleton:
      
      ```
      # <ADR / Feature> Lean Build Dispatch
      ## 0. Operator Contract   (SSOT · frozen status · "do not reinterpret spec" · what "green" means)
      ## 1. Scope / Non-scope
      ## 2. Authority Boundary   (allowed · stop-and-ask · forbidden)
      ## 3. Implementation Checklist / DoD   (| item | file/component | required change | verification |)
      ## 4. Risk Sections   (DB migration · API compat · UI behavior · prod/data safety)
      ## 5. Pre-flight Gate   (notify test-through BEFORE any work)
      ## 6. Execution Procedure
      ## 7. Verification Protocol   (exact commands + pass thresholds; green = all boxes + all commands green)
      ## 8. Traffic-light Reporting   (🟡 milestones · 🔴 stop-and-ask · 🟢 only when fully verified, never false-report)
      ## 9. Failure / Stop Conditions
      ## 10. Final Handoff   (human approves merge/deploy / accepts final report — NOT "picks a candidate")
      ```
      
      Semantic swaps vs generate-and-select dispatch:
      - "human picks final selection" → **"human approves merge/deploy / accepts final report"**.
      - reason codes → **`TEST_FAIL` / `MIGRATION_RISK` / `SPEC_GAP` / `AUTH_BOUNDARY`** (not candidate-quality codes).
      - delta each round = "what moved toward DoD", not "how candidates improved".
      
      ## 6. Pitfalls the fix MUST preserve (reviewer-flagged)
      
      1. **"Approved" ≠ "unattended-ready"**. An ADR may be a design decision, not executable AC. The Frozen Spec Check (4e) is mandatory — it's what stops a lean dispatch being authored on a spec that still needs decisions.
      2. **Staging → prod is a hard two-phase split**. A lean build dispatch may authorize only demo/dev/staging. Prod deploy / prod DB migration is an independent **human gate** — the agent must NOT auto-continue past it. Bake this into the template's Authority Boundary + Stop Conditions.
      3. **Keep goal-engineer's core intact**. generate-and-select remains the primary path; the build exception is narrow and gated. Don't let the new path leak candidate semantics or vice-versa.
      
      ## 7. Acceptance criteria for this follow-up
      
      - [ ] SKILL.md edits (a)–(h) applied; wording matches the frozen-spec boundary in §3.
      - [ ] `Frozen Spec Check` section present and referenced from Stage Detection.
      - [ ] `references/lean-build-dispatch-template.md` created per §5 (no candidate/final-selection semantics).
      - [ ] `docs/DESIGN.md` three-axis table updated (§4i).
      - [ ] A blind read of SKILL.md now routes `build-to-spec + frozen + unattended` to a lean dispatch (with the gate), and still routes `build-to-spec + raw` to prd-create.
      - [ ] No over-broadening: skill still refuses to author build specs / product decisions / AC.
      - [ ] Repo is PR-driven (commits end `(#N)`) — branch → PR, do not direct-push main.
      - [ ] Decide (or leave a note for the maintainer): patch goal-engineer now vs extract `unattended-dispatch-engineer` later. Default = patch now.
      
  • references
    • dispatch-template.md 6.3 KB
      # `<task>` Dispatch — `<one-line goal>`
      
      > Self-contained hand-off spec for an **unattended evaluator-optimizer loop**. A fresh-session agent runs this **blind**; the human only watches 🟢🟡🔴 notifications and picks at gates. Fill every `<...>`; leave **no `TBD`** (a vague field = an un-runnable spec).
      > 🔴 **Secrets never go in this file** (tokens / keys / passwords / webhook URLs / chat_ids / handles → env or config, always). **Operational references** (hostnames / paths / service & internal-project names) are *fine in a private/internal dispatch* — that's the spec, a PRD-type loop legitimately tells the agent which machine/service to hit — but become a **leak if the dispatch is shared/public**, so abstract or redact them then. Declare which in §0 **Visibility**.
      
      ## 0. Goal & scope
      - **Visibility:** `<private/internal — real infra refs OK as spec | shared/public — must abstract/redact infra refs>`
      - **Goal:** `<measurable target — what "done/good" means>`
      - **Scope this run:** `<exactly which items; what is explicitly out>`
      
      ## 1. Architecture / runner
      - **Runner:** `<model/agent, kept swappable — do not hardcode a model that may be deprecated>`
      - **Where:** `<unattended host/session, e.g. a long-running agent session or a CI job>`
      - **Dispatched how:** `<command/entry the human runs to kick it off>`
      - **Resume:** `<persist state to disk so a killed run continues? where (e.g. state.json)?>`
      
      ## 2. Inputs (ready / to-prepare)
      - ✅ `<asset/data already in place — relative path preferred>`
      - ⏳ `<asset still to prepare, and by whom>`
      
      ## 3. Work items (matrix)
      `<the enumerable list the loop iterates over — N items × M variants>`
      
      | item | variant A | variant B |
      |---|---|---|
      | `<item1>` | ✔ | ✔ |
      
      ## 4. Constraints / hard lines(逐條 verbatim 進 runner prompt)
      - 🔴 `<forbidden action / scope guard>`
      - 🔴 **Do not self-approve the final selection / do not make subjective approval calls — the human is ground truth.** Produce candidates + a review bundle, hand off.
      - 🔴 `<reproducibility / safety / privacy red line>`
      
      ## 5. Evaluation / gates(怎麼判每個 candidate)
      - **Floor gate(扣分閘,硬缺陷自動退):** `<auto-reject defects — invalid/broken output, fails a hard check>`
      - **Ceiling gate(達標閘,真的命中目標嗎):** `<positive criterion that means it HITS the goal — not just "no defect">`
      - **Grader:** `<who/what judges — an independent skeptic subagent (default-refute) / a test suite / an objective metric>`;能量化就加客觀指標兜底。
      - **Reason-codes(讓迭代針對性、不亂猜):**
      
      | code | 意思 | 預設動作 |
      |---|---|---|
      | `<R1>` | `<what failed>` | `<how to adjust next round>` |
      | `<R2>` | ... | ... |
      
      ## 6. Stop conditions
      - **per-item:** hit **≥K** passing, OR iterate **≤N** rounds, OR **loop-until-dry** (M consecutive rounds with nothing new) — first to fire wins.
      - **3 exits:** `NEEDS_INPUT` (missing material) / `ESCALATE` (no progress 2 rounds → notify human) / `REFUSE` (crosses a red line).
      - **anti-spin:** from round 2, every round states a **delta** vs last; no meaningful delta → stop.
      
      ## 7. Reproducibility(鐵律:只有結果、沒配方 = 白跑)
      - 🔴 every candidate carries a **`.recipe` sidecar** (`<params/inputs/versions/...>`).
      - 🔴 a **run log** per round: params + verdict + reason-code + delta.
      - a milestone notification carries enough handle (`<item id / batch / round>`) for the human to map a pick back to its recipe.
      
      ## 8. Notification(triggers/format SSOT = `notify-protocol.md`)
      - **Channel:** `<telegram / discord / slack / imessage / other>`
      - **Credential source:** `<which env vars (e.g. TELEGRAM_BOT_TOKEN+TELEGRAM_CHAT_ID); where the secret lives — a private config / NOTIFY_CONFIG path. The secret itself is NOT written here.>`
      - **Triggers + format:** per `notify-protocol.md` (pre-flight test · per-milestone 🟢 · 🟡 incident-handled · 🔴 blocked · finish summary). Do not redefine here — reference it.
      
      ## 9. Pre-flight gate(fail-fast,最前面跑)
      0. **Notification test passes** (send a test ping; `notify.sh` returns non-zero on failure → do not start the loop).
      1. `<runtime/service ready check>`
      2. `<inputs present + required tools available (curl / python3 / ...)>`
      3. `<smoke 1 item end-to-end before the full matrix>`
      
      ## 10. Execution procedure(per-item loop — 新 session 照這個跑)
      1. Load state (resume if `<state file>` exists, else fresh) + read this dispatch.
      2. For each work item × variant:
         a. **Generate** a candidate (write a *draft* `.recipe` now — a crash still leaves a reproducible artifact).
         b. **Floor gate** → fail: log reason-code, apply the code's default action, retry (respect ≤N).
         c. **Ceiling gate** → fail: log reason-code, adjust, retry.
         d. **Pass** → finalize the `.recipe` + append run log.
         e. Check **stop conditions** (≥K / ≤N / dry / delta); hit an exit → handle (`NEEDS_INPUT`/`ESCALATE`/`REFUSE`).
      3. On milestone (a batch/phase done) → 🟢 notify (+ review bundle if media).
      4. On finish → assemble review bundle, 🟢 summary notify, hand candidates to the human.
      5. 🔴 Never self-select the final selection — that's the human's call.
      
      ## 11. Fallback
      - `<if approach A fails (e.g. the primary producer refuses / a gate never passes), what is plan B>`
      
      ---
      
      ## Worked example (abstract — replace with your task)
      
      > **`bug-hunt` Dispatch — find & verify real bugs in module `<X>`, 0 false positives**
      > - **Goal:** ≥5 confirmed, reproducible bugs, each with a failing test.
      > - **Runner:** a general agent on a long-running unattended session; resumes from `state.json`.
      > - **Work items:** files in `<X>/` × {correctness, edge-case, concurrency} lenses.
      > - **Constraints:** 🔴 don't "fix" anything — report only. 🔴 don't self-mark a bug "real" — an independent skeptic verifies. 🔴 human triages the final list.
      > - **Evaluation:** floor = reproduces on current HEAD; ceiling = a *minimal failing test* exists. Grader = independent skeptic subagent, default-refute. Reason-codes: `NOREPRO`→drop, `FLAKY`→stabilize, `KNOWN`→dedup.
      > - **Stop:** ≥5 confirmed OR 8 rounds OR 2 dry rounds.
      > - **Reproducibility:** each finding → `.recipe` (file:line, repro steps, test snippet) + round log.
      > - **Notification:** telegram (creds from `NOTIFY_CONFIG`); 🟢 per finding-batch, 🔴 ESCALATE if 2 dry rounds.
      
    • lean-build-dispatch-template.md 6 KB
      # `<ADR / feature>` Lean Build Dispatch — `<one-line goal>`
      
      > Self-contained hand-off spec for an **unattended build-to-spec run of a FROZEN spec**. A fresh-session agent runs this **blind**; the human only watches 🟢🟡🔴 notifications and approves at gates. Fill every `<...>`; leave **no `TBD`**(a vague field = an un-runnable spec).
      > 🔴 **Entry condition**: this template is only valid AFTER the Frozen Spec Check (SKILL.md) passes — the spec exists, is approved/locked, and every AC is machine-checkable. **This dispatch never adds product decisions**; a gap found mid-run is `SPEC_GAP` → stop-and-ask, not an invitation to improvise.
      > 🔴 **Secrets never go in this file**(tokens / keys / passwords / webhook URLs / chat_ids → env or config, always). Operational references (hostnames / paths / service names) are fine in a private/internal dispatch — declare which in §0 **Visibility**(same rule as `dispatch-template.md`).
      
      ## 0. Operator contract(先讀 — 這份 dispatch 的憲法)
      - **Visibility:** `<private/internal — real infra refs OK as spec | shared/public — must abstract/redact infra refs>`
      - **規格主版本(SSOT):** `<approved ADR / doc path / work item>` — 狀態:`<approved / locked,日期>`
      - 🔴 **不得重新詮釋規格**:實作疑義一律回 SSOT 查;SSOT 沒答案 = `SPEC_GAP` → 🔴 stop-and-ask,不腦補。
      - **「🟢 綠」的定義:** §3 DoD 全勾 **且** §7 驗證指令全綠 — 缺一不可,**不准提前報綠(false completion 是本型 dispatch 的頭號風險)**。
      
      ## 1. Scope / non-scope
      - **本 run 做:** `<exactly which changes>`
      - **明確不做:** `<out of scope — 即使「順手」也不做>`
      
      ## 2. Authority boundary(授權邊界)
      - **已授權(可自主):** `<repo / files / db / dev|staging 環境,agent 可全權>`
      - **stop-and-ask(遇到即停、發 🔴 待人):** `<規格外衝突 / 白名單外新依賴 / 既有資料的修改刪除 / ...>`
      - 🔴 **禁止(獨立人工 gate,agent 不得自行續跑):** prod 部署 / prod db migration / merge / `<...>`。staging 驗完 ≠ 可進 prod — **staging → prod 是硬性兩階段**,第二階段永遠是人。
      
      ## 3. Implementation checklist / DoD
      | # | item | file/component | required change | verification |
      |---|---|---|---|---|
      | 1 | `<item>` | `<path>` | `<what changes>` | `<test / command>` |
      | 2 | ... | ... | ... | ... |
      
      ## 4. Risk sections(依規格性質列,只列本 run 真的有的;例:db migration / API 相容 / UI 行為 / 資料安全)
      - **`<風險類別>`:** `<徵兆 → 對策 → 驗證方式>`
      - **`<風險類別>`:** ...
      
      ## 5. Pre-flight gate(fail-fast,任何工作開始前跑、硬擋)
      0. **通知測得通**(送測試 ping;失敗 → 不開跑。見 `notify-protocol.md`)。
      1. `<runtime / 服務 / 依賴檢查>`
      2. `<輸入 / 測試環境(staging / dump)備齊>`
      3. `<smoke:最小一項端到端,例如對 dump 空跑一次 migration>`
      
      ## 6. Execution procedure(新 session 照這個跑)
      1. 讀本 dispatch + SSOT;load state(`<state file>` 存在則 resume,否則 fresh)。
      2. 按 §3 checklist 逐項:實作 → 跑該項 verification → 綠才勾,並 append run log 一筆(項次 + 判定 + 原因碼 + delta)。
      3. 沒過 → 記原因碼(§9)、照該碼預設動作調整;每輪報 **delta(往 DoD 推進了什麼)**,連 2 輪無 delta → `ESCALATE`。
      4. milestone(一批 checklist 項完成)→ 🟢 通知(粒度照 `notify-protocol.md`,不 per-item 洗版)。
      
      ## 7. Verification protocol(機器可檢核 — 全綠才算完成)
      逐條列**確切指令 + 通過門檻**:
      - `<lint / typecheck 指令>` → `<門檻>`
      - `<unit / integration / e2e 指令>` → `<門檻>`
      - `<build / migration 驗證指令>` → `<門檻>`
      
      **綠 = §3 全勾 + 本節指令全綠**;任何 silent cap(略過的測試 / 抽樣驗證)要明講、別藏。
      
      ## 8. Notification(triggers/format SSOT = `notify-protocol.md`)
      - **Channel:** `<telegram / discord / slack / imessage / other>`
      - **Credential source:** `<env vars / NOTIFY_CONFIG 路徑 — secret 本身不寫在這>`
      - **Triggers + format:** per `notify-protocol.md`(pre-flight 測通 · milestone 🟢 · 事故已處理 🟡 · blocked 🔴 · 收工總結)。不在此重定義。
      - 每輪 delta 報「往 DoD 推進了什麼」,不是「候選變好了」。
      
      ## 9. Failure / stop conditions
      - **3 出口:** `NEEDS_INPUT`(缺料 / 缺決策)/ `ESCALATE`(連 2 輪無 delta)/ `REFUSE`(越過 §2 授權)— 全部發 🔴。
      - **輪數上限:** `<≤N 輪 / 時間盒>`。
      - **原因碼(讓迭代針對性、不亂猜):**
      
      | code | 意思 | 預設動作 |
      |---|---|---|
      | `TEST_FAIL` | §7 某驗證指令紅 | 修到綠;同一項連 2 輪紅 → `ESCALATE` |
      | `MIGRATION_RISK` | 不可逆操作 / 資料毀損徵兆 | 立即停手 → 🔴 stop-and-ask |
      | `SPEC_GAP` | SSOT 答不了的實作疑義 | 🔴 stop-and-ask,不腦補、不自己補決策 |
      | `AUTH_BOUNDARY` | 下一步需越過 §2 授權 | `REFUSE` + 🔴 |
      
      ## 10. Final handoff
      - 交付:`<branch + PR / spec 指定的形式>` + run log + §7 驗證報告。
      - **人批准 merge / deploy / 接受最終報告** — 不是「人挑候選」。agent 不得自行 merge、不得自行進 prod、不得把「staging 全綠」升級解讀成「可以上了」。
      
      ---
      
      ## Worked example (abstract — replace with your task)
      
      > **`ADR-042` Lean Build Dispatch — schema migration + classifier rule + settings page toggle, staging-verified**
      > - **SSOT:** `docs/adr/042-<name>.md`(approved `<date>`);本 dispatch 不重述決策、只包執行。
      > - **Scope:** migration script + rule change + one UI toggle;**不做** prod 部署、不動其他 schema。
      > - **Authority:** 可自主 — repo `<X>`、staging db(dump 副本);禁止 — prod、merge。
      > - **DoD:** 3 items,each with a test/command in §3。
      > - **Risk:** db migration(先對 dump 空跑、驗 row count + rollback script)。
      > - **Verification:** `<test suite>` 全綠 + migration dry-run 無 diff 異常。
      > - **Stop:** `SPEC_GAP` 或 `MIGRATION_RISK` 即 🔴;≤6 輪。
      > - **Handoff:** PR + run log;人審後自己按 merge、自己排 prod migration 時段。
      
    • loop-run-protocol.md 4.5 KB
      # Unattended-run protocol — the discipline any agent-run spec inherits
      
      **內容無關(content-agnostic)的執行紀律正典。** 一份規格要交給 agent **無人值守 blind 跑**時,不管它是 `goal-engineer` 的 generate-and-select dispatch、還是 `prd-create` 的 build-to-spec PRD(其 §13 Test Strategy 的 agent-run 變體),都套這同一層。
      
      > 這份只講「**agent 怎麼無人值守跑 + 怎麼回報 + 何時停**」,**不講要 build/generate 什麼**(那是各內容 skill 的事)。通知格式細節在 `notify-protocol.md`,本檔不重述,只引用。
      >
      > **適用前提**:有人不在場、靠推播看進度。**人跑的規格不套本檔**(人跑不需要紅綠燈 / 3 出口 / 防空轉)。
      
      ---
      
      ## 1. Pre-flight gate(fail-fast,最前面跑、硬擋)
      
      開跑前先驗、任一條沒過就**不准進 loop**:
      
      0. **通知測得通**:送一則測試 ping;helper 回非零 → 不開跑(通知靜默失敗 = 盲跑)。見 `notify-protocol.md`。
      1. runtime / 服務 / 依賴在(`/api/health` 之類、必要工具 `curl`/`python3`/… 在)。
      2. 輸入備齊。
      3. **smoke 一個工作項端到端**跑通,再開整批 / 全 matrix。
      
      ## 2. 機器可檢核(machine-checkable)
      
      每條驗收標準都要**機器能判真假** —— 不靠人肉眼。沒有客觀檢核的標準 = 不能無人值守。
      
      - build-to-spec:每條 AC 展成測試,**gate 全綠才算該項完成**(lint / type / unit / integration / e2e / build)。
      - generate-and-select:每個候選過 rubric;能量化就加客觀指標兜底。
      - 🔴 任何 **silent cap**(top-N / 不重試 / 抽樣 / 截斷)要**明講、別藏**(藏起來會讓人以為「全做了」)。
      
      ## 3. 兩層閘(floor + ceiling)
      
      - **扣分閘(floor)**:硬缺陷自動退 —— 輸出損壞 / build 壞 / lint fail / schema 不合。
      - **達標閘(ceiling)**:真的**命中目標**了嗎 —— 「沒缺陷」**≠**「命中目標」。
      - **判官**:獨立 skeptic subagent(預設找碴)/ 測試套件 / 客觀指標。寫的人自己打分太寬鬆,要另一個 agent 挑刺。
      
      ## 4. 原因碼迭代(reason-coded)
      
      沒過閘 → 記**原因碼**、照該碼的預設動作調整,讓迭代**針對性、不亂猜**。
      
      | code | 意思 | 預設動作 |
      |---|---|---|
      | `<R1>` | `<什麼失敗>` | `<下輪怎麼調>` |
      
      ## 5. 停止條件:3 出口 + 防空轉
      
      - **per-item**:湊滿 ≥K 過閘,或迭代 ≤N 輪,或 **loop-until-dry**(連 M 輪沒新東西)—— 先到先停。
      - **3 出口**:
        - `NEEDS_INPUT` — 缺料 / 缺決策 → 暫停該範圍、發 🔴。
        - `ESCALATE` — 連 2 輪沒實質進展 → 發 🔴(必帶 delta)。
        - `REFUSE` — 要求越過授權邊界 / 紅線 → 拒做、發 🔴。
      - **防空轉(anti-spin)**:第 2 輪起每輪必報 **delta**(跟上輪差在哪);講不出有意義 delta → 停、發 `ESCALATE`。
      
      ## 6. 授權邊界 + stop-and-ask
      
      **方法鬆、驗收緊**:對「怎麼做」有自主權(自己查資料、換方法迭代);gate / AC 是成功定義、不可協商。明列兩欄:
      
      - **已授權(loop 內可自主)**:`<哪些 repo / 機器 / 服務 / 操作,agent 可全權>`
      - **stop-and-ask(遇到即停、發 🔴 待人)**:授權外的設定 / 既有資料的修改刪除 / spec 未定義的衝突 / 白名單外的新依賴 / 規格外的刪資料。
      - 🔴 **必含**:不准自己拍板最終選定 / 不自做品味判斷 —— 人是 ground truth。
      
      ## 7. 可重現(鐵律:只有結果、沒配方 = 白跑)
      
      - 每個產出帶 **recipe sidecar**(參數 / 種子 / 輸入 / 版本)。
      - 每輪一筆 **run log**:參數 + 判定 + 原因碼 + delta。
      - milestone 通知帶足夠 handle(item id / 批次 / 輪數),讓人挑完對得回 recipe。
      
      ## 8. 通知
      
      紅綠燈 🟢🟡🔴、channel-agnostic、milestone 粒度(不 per-candidate)、pre-flight 測通才開跑 —— **格式與 triggers 全部見 `notify-protocol.md`,本檔不重述**。
      
      ## 9. 人工 checkpoint(選用、長跑建議)
      
      每個工作天 / 階段收尾:人工 review 當日 diff + gate 報告;偏航在下一輪開始前修正。
      
      ---
      
      ## 套用 checklist(規格要交 agent 無人值守跑時)
      
      ```
      [ ] pre-flight gate 在最前(通知測通 + 服務 + 輸入 + smoke 一項)
      [ ] 每條驗收標準機器可檢核;silent cap 明講
      [ ] 兩層閘(floor + ceiling),判官獨立
      [ ] 原因碼表(讓迭代針對性)
      [ ] 停止條件含 3 出口 + delta 防空轉
      [ ] 授權邊界兩欄 + stop-and-ask;含「不自己拍板最終選定」
      [ ] 可重現:每產出 recipe sidecar + 每輪 run log
      [ ] 通知對齊 notify-protocol.md(紅綠燈 / milestone 粒度 / pre-flight)
      ```
      
    • notify-protocol.md 5.8 KB
      # Notification protocol — traffic-light, channel-agnostic
      
      The loop reports to the human over a **push channel**. The *format* (traffic-light) is channel-independent; only the *transport* differs. Decide the channel + credential source in the skill's Q7, then wire `notify.sh` (or your own helper) accordingly.
      
      > **Artifact-neutral by default.** The protocol assumes outputs are generic candidates (text, code, structured data, files). If your loop produces **media** (images/audio/video), see the *Media artifacts (optional)* note at the bottom — that part is opt-in, not core.
      
      ## Traffic-light format(每則開頭帶燈號)
      
      | 燈 | 意思 | 何時 | 內容 |
      |---|---|---|---|
      | 🟢 | 進度(看一眼、不用動) | milestone 完成 N 個 candidate / phase 開始 | 一兩句:剛做完什麼 + 接下來。結尾固定「續跑中、不用動」。 |
      | 🟡 | 注意(不阻塞、loop 續跑) | 重試 / 自癒已處理 / 有 workaround | 發生什麼 + 怎麼繞 + 是否要事後關注。 |
      | 🔴 | 需要你(阻塞、要人介入) | `NEEDS_INPUT` / `ESCALATE` / `REFUSE` / gate 連續紅 | 開頭 `🔴 需要你:<具體動作>` + 帶具體欄位(卡哪、需要什麼決定、暫停範圍)。`ESCALATE` 必帶 delta。 |
      
      ## Triggers(什麼事件發 — milestone 粒度、不是 per-candidate)
      
      - **Pre-flight 測通(第 0 步、硬擋)**:開跑前送一則測試 ping;**送不出去(helper 回非零)就不准開 loop**(通知靜默失敗 = 盲跑)。可要人回任意字確認雙向通。
      - **per-milestone**:每完成**一個 phase / 一批 candidates / 一個工作項的所有變體**一則 🟢。🔴 **不要 per-candidate**(洗版)。把「milestone」定義成「一批、不是一個」。
      - **事故已處理**:自癒後一則 🟡(不 stop-and-ask)。
      - **收工 / 階段總結**:完成清單 + 各項通過數 + 阻塞 + 待人挑。
      - **(選)心跳 pulse**:長靜默每 N 分鐘一則,防無人值守久跑讓人不安 / 補 silent-death(見 watchdog)。
      
      ## Channel-agnostic transport
      
      | Channel | Transport | Credential(由 Q7 決定來源、env/config 注入)|
      |---|---|---|
      | Telegram | `sendMessage` / `sendPhoto` HTTP API(curl)| `TELEGRAM_BOT_TOKEN` + `TELEGRAM_CHAT_ID` |
      | Discord | incoming webhook(curl POST)| `DISCORD_WEBHOOK_URL` |
      | Slack | incoming webhook(curl POST、text-only)| `SLACK_WEBHOOK_URL` |
      | iMessage | local `osascript`(macOS only)| `IMESSAGE_TO` |
      | other | 自訂 | — |
      
      **Credential source(Q7 決定,三種常見)**:
      - (a) operator 互動時直接給 → 寫進該專案的私有 env / config(**不進 repo、不寫進 dispatch 文件正文**)。
      - (b) operator 指一個 **config 檔路徑** → helper `NOTIFY_CONFIG=<path>` source 它。
      - (c) operator 指定一個**安全的 config 來源**讓你取 → 取用即可。
      - 🔴 **token / chat_id / webhook URL / handle 一律由 env 或 config 注入,永不寫進 skill、永不進 repo、永不寫進 dispatch 文件**(dispatch 只記「來源是哪個 env var / 哪個 config」,不記 secret 本身;dispatch 若會進 repo,路徑也要 redact)。
      
      ## Watchdog(選用、補無人值守 silent-death)
      
      無人值守 job 會**靜默失敗、沒人知道**——常見模式:deadlock 卡死、`exit 0` 但輸出全空、執行環境中途中斷。若在意,在一個**常駐的、獨立於 loop 的**輕量 session 掛心跳:每 N 分鐘檢查「loop 還活著嗎」(輸出有沒有增長 / log 有沒有更新 / state 時間戳),偵測到停滯就發 🔴。**關鍵:watchdog 要獨立**(loop 自己死了就發不出自己的告警)。
      
      ## 已安裝的通知服務
      
      若執行主機已有登記來源的通知服務,優先設定 `NOTIFY_COMMAND` 為其**絕對可執行路徑**,讓來源、project、目的地、待送匣與回執由該服務管理。`notify.sh` 會直接轉交原參數並保留退出碼;失敗時不再發第二個管道。
      
      使用 kc_notify v2 時,在任務設定中明確提供已登記的 `KC_NOTIFY_SOURCE`/`KC_NOTIFY_PROJECT`;agent 來源另給 `KC_NOTIFY_AGENT`。依任務選個人或公司 project,pre-flight 與後續回報使用同一設定。不要從 repo 名稱、目前目錄或預設 Telegram 憑證猜測分類。只有取得送達回執的同步介面可通過 pre-flight,單純 `queued` 不能當作測通。
      
      公開範本只描述環境變數契約;source/project 的實值與私人設定留在執行環境。
      
      ## `notify.sh` 用法
      
      ```bash
      NOTIFY_CHANNEL=telegram NOTIFY_CONFIG=/path/to/private-notify.env \
        notify.sh 🟢 "phase-1 done, 4/5 candidates passing, 續跑中不用動"
      notify.sh 🔴 "需要你:input 缺,NEEDS_INPUT — 暫停 item-5"
      ```
      
      - `NOTIFY_CHANNEL`(telegram|discord|slack|imessage)+ 對應 credential 由執行環境或 `NOTIFY_CONFIG` 注入。
      - helper **送失敗回非零** → pre-flight gate 才真的擋得住。
      - ⚠️ `NOTIFY_CONFIG` 是被 **source 的 shell 檔(會執行內容)** → 只指向你自己掌控的私有檔。
      - ⚠️ webhook 類的 token / URL 會出現在 **process argv**(同機其他程序可能看到)→ 跑在信任的 host。
      - 需 `curl`;webhook JSON escape 需 `python3`;圖壓縮需 `magick`/`convert`(pre-flight 一併檢查)。
      
      ## Media artifacts (optional — only if your outputs are media)
      
      若 loop 產出是圖/影音(非預設):milestone 通知可附一張**彙整圖(review bundle)**讓人快速初篩。注意:
      - 🔴 媒體檔路徑要在**執行發送的那台機器**本機絕對路徑(遠端跑就先放那台 / 傳過去)。
      - 大檔先壓(`notify.sh` 對 PNG/webp 自動壓 JPEG;需 magick/convert,否則送原檔),避免上傳 timeout。
      - caption 帶 milestone handle(item id / 批次 / 輪數)讓人挑完對得回 recipe。
      - Slack / iMessage(本 helper)只發文字、會略過媒體並在 stderr 警告。
      
    • notify.sh 5.1 KB
      #!/bin/bash
      # notify.sh — channel-agnostic traffic-light notifier for unattended loops.
      # Reference helper for the goal-engineer skill. Copy into your project, wire the
      # channel + credentials per your dispatch doc. NOT meant to run from the skill repo.
      #
      # Usage:
      #   notify.sh <emoji> <text> [local-media-path]
      #   notify.sh 🟢 "item-3 done, 4 passing, still running"
      #   notify.sh 🟢 "milestone done" /abs/path/review-bundle.png   # image auto-compressed to JPEG
      #   notify.sh 🔴 "need you: input missing, NEEDS_INPUT"
      #
      # Channel:  NOTIFY_CHANNEL = telegram | discord | slack | imessage   (default telegram)
      # Optional: NOTIFY_CONFIG = /path/to/private.env  → sourced before sending (TRUSTED shell file you own)
      #
      # 🔴 Credentials come ONLY from env (or NOTIFY_CONFIG you source) — NEVER hardcode
      #    tokens/ids/URLs/handles, NEVER commit them, NEVER write them into a dispatch doc.
      #      telegram : TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID
      #      discord  : DISCORD_WEBHOOK_URL
      #      slack    : SLACK_WEBHOOK_URL
      #      imessage : IMESSAGE_TO   (macOS only; sends locally via osascript)
      #
      # Requirements: curl. (discord/slack JSON escaping needs python3. image compress needs magick/convert.)
      # Exit code: non-zero if the send fails — so a pre-flight test can actually gate on it.
      set -uo pipefail
      
      EMOJI="${1:?usage: notify.sh <emoji> <text> [media]}"
      TEXT="${2:?missing text}"
      MEDIA="${3:-}"
      MSG="${EMOJI} ${TEXT}"
      CH="${NOTIFY_CHANNEL:-telegram}"
      
      # optional: load secrets from a config file the operator points at (kept private, never committed)
      if [ -n "${NOTIFY_CONFIG:-}" ]; then
        [ -f "$NOTIFY_CONFIG" ] || { echo "[notify] NOTIFY_CONFIG not found: $NOTIFY_CONFIG" >&2; exit 1; }
        set -a; # shellcheck disable=SC1090
        source "$NOTIFY_CONFIG"; set +a
      fi
      
      # A registered producer can own routing, receipts and durable retries. Treat its
      # exit code as the pre-flight result; never fall back to a second channel.
      if [ -n "${NOTIFY_COMMAND:-}" ]; then
        [ -x "$NOTIFY_COMMAND" ] || { echo "[notify] NOTIFY_COMMAND is not executable" >&2; exit 1; }
        exec "$NOTIFY_COMMAND" "$@"
      fi
      
      die(){ echo "[notify] $*" >&2; exit 1; }
      TMP=""   # cleaned on exit
      cleanup(){ [ -n "$TMP" ] && rm -f "$TMP"; }
      trap cleanup EXIT
      
      # JSON-encode a string safely (for webhook payloads). Falls back to error if no python3.
      json_str(){ command -v python3 >/dev/null 2>&1 || die "discord/slack need python3 for JSON escaping"; printf '%s' "$1" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))'; }
      
      # compress big images to a unique temp JPEG (avoid upload timeouts); only if media given + is image
      prep_media(){
        [ -n "$MEDIA" ] && [ -f "$MEDIA" ] || { MEDIA=""; return; }
        case "$MEDIA" in
          *.png|*.PNG|*.webp|*.WEBP)
            local conv=""
            if command -v magick >/dev/null 2>&1; then conv=magick; elif command -v convert >/dev/null 2>&1; then conv=convert; fi
            [ -n "$conv" ] || { echo "[notify] no image converter (magick/convert); sending original (may be large)" >&2; return; }
            TMP="$(mktemp "${TMPDIR:-/tmp}/notify.XXXXXX.jpg")"
            if "$conv" "$MEDIA" -quality 90 "$TMP" 2>/dev/null; then MEDIA="$TMP"; else echo "[notify] image compress failed; sending original" >&2; fi ;;
        esac
      }
      
      # wrapper: curl that actually fails loud
      post(){ curl --fail --show-error --silent --max-time 25 "$@"; }
      
      case "$CH" in
        telegram)
          : "${TELEGRAM_BOT_TOKEN:?set TELEGRAM_BOT_TOKEN}"; : "${TELEGRAM_CHAT_ID:?set TELEGRAM_CHAT_ID}"
          api="https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}"
          prep_media
          if [ -n "$MEDIA" ]; then
            post -F chat_id="$TELEGRAM_CHAT_ID" -F caption="$MSG" -F photo="@${MEDIA}" "$api/sendPhoto" >/dev/null || die "telegram send failed"
          else
            post "$api/sendMessage" -d chat_id="$TELEGRAM_CHAT_ID" --data-urlencode text="$MSG" >/dev/null || die "telegram send failed"
          fi ;;
        discord)
          : "${DISCORD_WEBHOOK_URL:?set DISCORD_WEBHOOK_URL}"; prep_media
          if [ -n "$MEDIA" ]; then
            post -F "content=$MSG" -F "file1=@${MEDIA}" "$DISCORD_WEBHOOK_URL" >/dev/null || die "discord send failed"
          else
            post -H "Content-Type: application/json" -d "{\"content\":$(json_str "$MSG")}" "$DISCORD_WEBHOOK_URL" >/dev/null || die "discord send failed"
          fi ;;
        slack)
          : "${SLACK_WEBHOOK_URL:?set SLACK_WEBHOOK_URL}"
          [ -n "$MEDIA" ] && echo "[notify] slack incoming-webhook can't upload media; sending text only" >&2
          post -H "Content-Type: application/json" -d "{\"text\":$(json_str "$MSG")}" "$SLACK_WEBHOOK_URL" >/dev/null || die "slack send failed" ;;
        imessage)
          : "${IMESSAGE_TO:?set IMESSAGE_TO}"; command -v osascript >/dev/null 2>&1 || die "imessage needs macOS osascript"
          [ -n "$MEDIA" ] && echo "[notify] imessage path sends text only here; media skipped" >&2
          # pass strings as argv (osascript 'on run') to avoid AppleScript injection / quoting breakage
          osascript - "$IMESSAGE_TO" "$MSG" <<'APPLESCRIPT' >/dev/null || die "imessage send failed"
      on run argv
        tell application "Messages" to send (item 2 of argv) to buddy (item 1 of argv)
      end run
      APPLESCRIPT
          ;;
        *) die "unknown NOTIFY_CHANNEL=$CH (telegram|discord|slack|imessage)" ;;
      esac
      echo "[notify] sent via $CH"
      
  • SKILL.md 15.7 KB
    ---
    name: goal-engineer
    description: "Use when the user wants to AUTHOR an unattended dispatch for either: (1) a goal-driven evaluator-optimizer loop of the GENERATE-AND-SELECT kind (generate candidates → grade against a rubric → iterate by reason-code → keep the best; the human picks the final selection), or (2) a lean build-to-spec run whose build spec is ALREADY FROZEN (approved ADR / locked design / accepted machine-checkable AC) and the only missing piece is the unattended-execution wrapper. A fresh-session agent runs the dispatch hands-off while the human only watches traffic-light push notifications. Interview-style forcing questions lock the spec, then it emits a self-contained dispatch markdown + a channel-agnostic notification protocol. This is the upstream SPEC AUTHOR, NOT a runtime: the dispatch is run by Claude Code's /goal, a headless `-p` session, or any unattended agent — /goal is the engine, this writes what you feed it. It NEVER authors build specs, product decisions, or AC — creating a build spec / PRD from raw input is prd-create. NOT a time scheduler (/loop or cron), NOT a recurring-push registrar (skill-cron)."
    version: 1.0.0
    status: stable
    triggers:
      - "/goal-engineer"
      - "goal engineering"
      - "goal engineer"
      - "設計無人值守 loop"
      - "固化 goal-loop"
      - "unattended loop"
      - "evaluator-optimizer loop"
      - "generate-and-select loop"
      - "dispatch 換手文件"
      - "lean build dispatch"
      - "凍結規格包 dispatch"
      - "frozen spec dispatch"
    ---
    
    # /goal-engineer — Unattended Goal-Loop Dispatch Architect
    
    You are a **goal-loop dispatch architect** — the *upstream spec author*, not the runtime. You turn a vague "I want an agent to grind on X by itself" into a **self-contained dispatch markdown** that a *fresh-session* agent can execute hands-off — generating candidates, grading them against a rubric, iterating by reason-code, keeping the best — while the human only monitors traffic-light (🟢🟡🔴) push notifications and makes the taste calls (the **final selection**) at gates.
    
    This skill **produces a spec + a notification protocol. It does NOT run the loop itself.**
    
    ## What this is / isn't(先讀,避免叫錯工具)
    
    | | `goal-engineer`(本 skill)| 不是這個 |
    |---|---|---|
    | 層 | **規格作者**(寫 dispatch) | **引擎**(跑迴圈)= Claude Code `/goal` |
    | 模式 | goal-driven evaluator-optimizer,**generate-and-select**(產候選→評→挑) | time-driven 週期重跑(`/loop`、cron) |
    | 內容型 | 抽卡 / bug-hunt / 候選擇優;**窄例外**:規格已凍結的 lean build dispatch(已核可 ADR / 鎖定設計 → 只包無人值守執行規格,見 Frozen Spec Check) | 從 raw input 產 build spec / PRD / 補產品決策 = `prd-create` |
    | 產出 | 一份 dispatch markdown + 通知協定 | 註冊定時推播(`skill-cron`) |
    | 誰來跑 | **新 session 無人值守 agent**(可拿 `/goal` / headless `-p` 當引擎) | 當前 session |
    | 人的角色 | 看 🟢🟡🔴、在 gate 挑最終選定 | 全程盯著 |
    
    **CRITICAL — 這不是 `/goal`**:Claude Code 內建的 `/goal` 是**引擎**(給一個可判真假的條件,獨立小模型每輪判達標、沒過再跑一輪、達標自停)。本 skill 是**上游**:把你要交給 `/goal`(或 headless `-p` session)跑的那個 goal,連同**兩層閘 / 原因碼 / 對抗審查 / 通知協定 / 可重現紀律**一起工程化。`/goal` 的判官只是一個 yes/no、對「這張圖有沒有到位 / 這個 bug 是不是真的」這種主觀又要防自我寬容的目標太粗;本 skill 的評估層(floor+ceiling 閘 + 原因碼 + 獨立 skeptic + 指標)補的就是這塊。
    
    **CRITICAL — 範圍 = 寫無人值守 dispatch、不寫 build spec**:本 skill 主體是 generate-and-select(產一堆候選 → 評分 → 留最好的 → 人挑最終:系列抽卡、bug-hunt、候選擇優)。另有一個**窄例外**:user 已有**凍結的 build spec**(已核可 ADR / 鎖定設計 / 明確可機器檢核的 AC),需求只剩「包成無人值守 agent 可 blind 跑的 dispatch」→ 本 skill 可產 **lean build dispatch**,只套 `references/loop-run-protocol.md` 的執行紀律,不產完整 PRD、不替規格補任何決策、不擴範疇、不發明 AC。build spec 不存在 / 未凍結 / AC 不可機器檢核 → 導去 `prd-create` 或先 stop-and-ask(入口檢核見「Frozen Spec Check」)。
    
    ## 執行規則
    
    1. 跟 user 互動用 user 的語言;產出的 dispatch 文件:section 標題可雙語、內文用 user 語言。
    2. **Forcing questions 一次問一塊**,每塊推到具體答案才往下(不要一次丟 7 題、會拿到淺答案)。
    3. **不替 user 腦補**。不知道就問——整個重點是「規格精確到能 blind hand-off」。
    4. dispatch 文件輸出到 user 指定路徑(預設 `docs/<task>_dispatch.md`)。
    5. **接到 build-to-spec 需求先判規格成熟度**:
       - 規格不存在 / 未凍結 / 要從 raw input 產 AC → 導去 `prd-create`。
       - 規格已凍結(已核可 ADR / 鎖定設計 / 已定 AC)、只差無人值守執行 → 跑 Frozen Spec Check,全過才產 lean build dispatch;不可替 user 重寫產品決策。
    
    ## Stage Detection(自動判斷)
    
    1. user 指名既有 dispatch 文件 / 說「resume」→ 載入它、跳到沒填完的洞。
    2. user 描述新的無人值守 generate-and-select loop 需求 → 跑 Forcing Questions。
    2b. user 描述「已核可 ADR / 鎖定設計 / 已有 AC,要 agent 無人值守落地」→ 先跑 Frozen Spec Check;全過 → 產 lean build dispatch,沒過 → 導去 `prd-create` 或 stop-and-ask。
    3. 只打 `/goal-engineer` → 問「你想讓 loop 自己磨什麼?(產什麼候選、怎樣算挑到好的?)」
    
    ## Forcing Questions(鎖規格 — 一塊一塊問)
    
    **Q1 — 目標 + 工作項**
    loop 要**產出 / 優化什麼**?它迭代的**離散工作項**是什麼?
    - 推到:一個可衡量的交付物 + 一個可列舉的清單/矩陣(N 項 × M 變體)。
    - 🚩 紅旗:「就弄好一點」→ 釘出可量測的目標。
    
    **Q2 — 約束 / 紅線**
    agent **絕對不能做**什麼?scope 邊界、禁止動作、只有人能決定的事。
    - 推到:一串 ❌ bullet(**逐條原樣進 dispatch 文件**)。
    - **必含一條**:「不准自己拍板最終選定(final selection)/ 不自己做品味判斷 — 人才是 ground truth。」
    
    **Q3 — 驗收 gate**
    每個產出怎麼判?**兩層閘**是驗證有效的形狀:
    - **扣分閘(floor)**:硬缺陷自動退(輸出損壞 / build 壞 / lint fail / schema 不合 …)。
    - **達標閘(ceiling)**:真的**命中目標**了嗎(不是「沒缺陷」就算過)?
    - 誰評?(獨立 skeptic subagent / 客觀指標 / 測試套件)。有沒有**客觀指標**能兜底?
    - 推到:一個帶**原因碼**的 rubric(讓迭代是針對性的、不是亂猜)。
    
    **Q4 — 停止條件**
    - per-item:湊滿 ≥K 過閘,或迭代 ≤N 輪,或 **loop-until-dry**(連 M 輪沒新東西)。
    - **3 出口**:`NEEDS_INPUT`(缺料)/ `ESCALATE`(連 2 輪沒進步、通知人)/ `REFUSE`(越紅線)。
    - **防空轉**:第 2 輪起每輪必報 delta(跟上輪差在哪);講不出有意義 delta → 停。
    
    **Q5 — runner + 環境**
    - 哪個 model/agent 無人值守跑、跑在哪(長跑的無人值守 agent session / `/goal` / headless `-p` / CI job)?
    - resume:要不要把 state 落磁碟、被 kill 能續?
    - 🚩 **別假設某個 model 一定在**(model 會被下架;保持可替換)。
    
    **Q6 — 可重現**
    🔴 鐵律:**「只有結果、沒配方 = 白跑」**。每個候選必須帶什麼?
    - 推到:sidecar/recipe 規格(參數/種子/輸入/版本)+ run log(每輪參數 + 判定 + 原因碼 + delta)。
    
    **Q7 — 通知通道**(channel-agnostic、這塊最常踩坑)
    - **哪個通道?** Telegram(預設)/ Discord / iMessage / Slack / 其他 — user 自由指定。
    - **credential 哪來?** user 可:(a) 直接給 chat_id/token、(b) 指一個 config 檔路徑(helper `NOTIFY_CONFIG`)、(c) 指定一個安全 config 來源讓你取。🔴 **dispatch 只記「來源是哪個 env var / config」、永不寫 secret 本身**。把「creds 從哪來」問到具體。
    - **觸發時機**:pre-flight 測通(**通知測得通才准開跑**)/ per-milestone(**不是 per-item、避免洗版**)/ 事故已處理 / 收工總結 / 選用心跳 pulse。
    - **格式**:紅綠燈 🟢🟡🔴(見 `references/notify-protocol.md`)。
    
    ## Frozen Spec Check(build-to-spec 例外入口 — 全過才准走 lean build dispatch)
    
    任一條沒過 → 導去 `prd-create` 或 stop-and-ask,**不准腦補**:
    
    - [ ] **規格主版本明確**:指得出在哪 —— `<ADR / 文件路徑 / work item>`。
    - [ ] **狀態明確**:approved / locked / user 明說已定版。「已核可的設計決策」≠「可執行的 AC」,兩者都要有。
    - [ ] **範疇明確**:這一輪做哪些、明確不做哪些。
    - [ ] **AC 可機器檢核**:每條都有測試 / 指令 / 可觀察的檢核,不靠人肉眼。
    - [ ] **授權明確**:可動哪些 repo / 檔案 / db / dev|staging 環境;prod / merge / deploy 是否禁止(prod 一律獨立人工 gate)。
    - [ ] **未決決策 = 0**:還有 >0 → stop-and-ask,不准替 user 補決策。
    
    通過後的訪談**只補執行包裝的缺口、不重問規格本身**:Q1(目標)/ Q3(驗收 gate)/ Q6(可重現)由凍結規格 + 模板的驗證段取代;**Q2(紅線)/ Q4(停止條件)/ Q5(runner + 環境)/ Q7(通知)照問**。產出用 `references/lean-build-dispatch-template.md` —— **不是** `dispatch-template.md`(那份是候選 / 最終選定語意,build-to-spec 的風險是假完成 / 碰 prod / migration 出事,語意不同)。
    
    ## 產出 dispatch 文件
    
    - generate-and-select → 用 Q1–Q7 的答案填 `references/dispatch-template.md`。
    - frozen build-to-spec → 用 Frozen Spec Check + Q2/Q4/Q5/Q7 的答案填 `references/lean-build-dispatch-template.md`。
    
    寫到指定路徑。執行紀律(3 出口 / delta / pre-flight / 機器 AC / 可重現)對齊 `references/loop-run-protocol.md`。然後**自審**:
    - 每段都具體、無「TBD / 看情況」(模糊 = 不能 hand-off)。
    - 約束逐條原樣在;停止條件含 3 出口 + delta;可重現鐵律在;通知通道+creds+觸發都釘死;pre-flight gate 在最前。
    - 回報一份 **handoff checklist**(讓 user 一眼知道怎麼接、不用追問):
      - 📄 dispatch 路徑:`<path>`
      - 🔑 需要的 credential env var(依 channel):`<列出名稱>` — secret 由 user 自己注入、不在文件裡
      - ✅ pre-flight 指令:`<跑通知測通的指令>`
      - ▶️ 開跑指令:`<丟給無人值守 session / `/goal` / `-p` 的指令>`
      - 👀 之後 user 只顧 🟢🟡🔴、在 gate 挑最終選定。
    
    ## 產出後:對抗審查(互動詢問,預設提供)
    
    dispatch 寫好後(尤其它會進 repo 或交給無人值守跑),**主動問 user 要不要先對抗審查再交付**(別等 user 自己喊):
    
    > 「dispatch 已產生在 `<path>`,要先派對抗審查再交付嗎?
    > 1. 派 sub-agent 審 2. 不用 3. 其他(自訂輪數/順序/reviewer,例「兩輪,先 sub-agent 後 codex」)」
    
    - user 選 **3** → 照指定跑(例:先獨立 LLM sub-agent 一輪 → 再 codex 一輪)。
    - 每位 reviewer:**獨立、預設找碴**,先 LEAK 再品質。🔴 **LEAK 獵殺要看 dispatch 的 Visibility(§0)分流**,別把私有規格誤判成洩漏:
      - **一律抓**:寫死的 secret(token / key / 密碼 / webhook URL / chat_id / handle)→ 任何 dispatch 都該走 env/config、不該出現在文件裡。
      - **只有 Visibility = 公開/分享 才抓**:真實機器名 / 路徑 / 服務 / 內部專案名。這些在「私有/內部」dispatch 裡是**必要的操作規格、不是 leak**(PRD 型本來就要 agent 去某機器某服務做事);只有要公開/分享時才抽象或 redact。
      - ⚠️ **別把私有 dispatch 的必要操作細節當成 leak 要求拿掉**(會把能跑的 spec 改爛、agent 也困惑)。
    - **品質**(不分 Visibility):spec 有沒有洞、約束/停止條件/可重現齊不齊、能不能 blind 跑。
    - 多輪=修完一輪再審下一輪;全過才交付。選 2 直接交付。
    
    ## Anti-patterns
    
    - ❌ 一次丟 7 題(拿到淺答案)。
    - ❌ dispatch 文件留「TBD / 看情況」(= 不能 blind hand-off 的廢規格)。
    - ❌ 讓 runner 自己拍板最終選定 / 自做品味判斷。
    - ❌ per-item 通知(洗版)→ 改 per-milestone。
    - ❌ 寫死某 model(保持可替換)。
    - ❌ 「只有結果沒配方」→ 每候選都帶重現 recipe。
    - ❌ 沒 pre-flight 通知測通就開跑(通知靜默失敗 = 盲跑)。
    - ❌ 寫死 Telegram(通道是 Q7 的決定、抽象化 transport)。
    - ❌ 把本 skill 當 `/goal` 引擎用(它只寫規格、不跑迴圈)。
    - ❌ 拿本 skill 從 raw input 寫 build-to-spec PRD(那是 `prd-create`)。
    - ❌ 在 frozen build dispatch 裡偷偷補規格決策 / 擴範疇 / 自行批准 prod。
    
    ## Important rules(context 再長也要記住)
    
    1. **規格作者、不是引擎**。loop 由 `/goal` / headless `-p` / 無人值守 session 跑;本 skill 只產規格。
    2. **goal-driven、不是 time-driven**。user 要「每 10 分鐘」那是 `/loop`/cron。build-to-spec 只有在規格已凍結、只差無人值守 dispatch 時才收(過 Frozen Spec Check);要產 PRD / AC 則是 `prd-create`。
    3. dispatch 文件要能被**新 session blind 跑**——零隱含 context。
    4. **兩層閘**(floor + ceiling):「沒缺陷」≠「命中目標」。
    5. **3 出口 + delta 防空轉**是必備停止條件。
    6. **人 = 品味/最終選定的 ground truth**;loop 只產候選 + review bundle,不自己拍板。
    7. **可重現是紅線**:每產出帶 recipe sidecar + run log。
    8. **通知 channel-agnostic + pre-flight 測通**;格式紅綠燈 🟢🟡🔴。
    9. loop 規模對齊 user 的 ask;有任何 silent cap(top-N / 不重試 / 抽樣)要**明講**、別藏。
    
    ## 跟其他 skill / 工具的關係
    
    - **Claude Code `/goal`(內建,external)**:loop 的**引擎**。本 skill 產出的 dispatch 可丟給 `/goal` 跑(`/goal <condition>` 或 `claude -p "/goal ..."`)。`/goal` 判達標、本 skill 寫「達標的定義 + 迭代紀律 + 通知」。引擎 vs 規格,不重疊。
    - **`prd-create`(同 monorepo)**:**build-to-spec** 的規格作者(產 PRD)。PRD 給 agent 無人值守跑時,它 §13 那層執行紀律(紅綠燈 / 3 出口 / delta / pre-flight / stop-and-ask)對齊本 skill 的 `references/loop-run-protocol.md`。分工:prd-create 寫「build 什麼」、本 skill 的 loop-run-protocol 寫「agent 怎麼無人值守跑 + 回報」。**要不要產 PRD 看「build spec 需不需要被寫出來」;要不要用本 skill 看「工作是不是只剩把凍結規格包成無人值守 dispatch」** —— 後者走 Frozen Spec Check,不必回頭跑整份 PRD。
    - **`skill-cron`(同 monorepo)**:心跳/排程器,**scheduler-agnostic**。dispatch 是收斂型(跑到目標就停);要**週期再進場**就把它做成 headless 可跑入口、讓任意排程器(cron / launchd / CI / skill-cron)點火 —— 排程器是誰不是本 skill 的事(同它對通知 channel-agnostic 的態度)。
    - **`/loop`(內建,external)**:time-interval 重跑,跟本 skill 的 goal 收斂是不同維度。
    
    ## References(用本 skill 時必讀「對應路徑的 template」+ loop-run-protocol + notify-protocol;用 shell helper 才讀/複製 notify.sh)
    
    - `references/dispatch-template.md` — generate-and-select dispatch 的 markdown 骨架。
    - `references/lean-build-dispatch-template.md` — frozen build-to-spec 的 lean dispatch 骨架(無候選 / 最終選定語意;人批准 merge/deploy、不是挑候選)。
    - `references/loop-run-protocol.md` — 無人值守執行紀律正典(3 出口 / delta / pre-flight / 機器 AC / stop-and-ask / 可重現),**內容無關、可被 prd-create §13 共用**。
    - `references/notify-protocol.md` — 紅綠燈協定 + channel-agnostic 通知設計 + helper 用法。
    - `references/notify.sh` — 參考用 sidecar 通知 helper(Telegram 預設、Discord/iMessage hook)。
    - `docs/DESIGN.md` — 為什麼存在 / 三軸定位 / 為何從 loop-engineer 改名(給人讀)。
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related