Skip to content

feat: config-protocol 加入 residual clause — 未列舉事項依「事務性質」歸屬,取代機械 cwd fallback(憲法第111條均權制度) #301

Description

@kiki830621

Blocked by #302 — residual clause 的性質判準需要 #302 的 repo 地圖才能執行(判準決定「該歸哪一層」,地圖決定「那一層是否存在」)。

Problem

idd-issue(以及所有共用 config-protocol 的 idd-* skill)沒有能力判斷「這件事在性質上該歸哪個 repo」。現行 target resolution 只有兩條路:機械地依 cwd walk-up 找最近的 config,或依賴有人事先寫好 title_matches 之類的 predicate。兩者都不適用時,issue 就開在「碰巧所在目錄」對應的 repo,而不是「這件事該歸屬」的 repo。

Original text(使用者,2026-08-12 對話逐字):

「我在想issue的分派應該要這樣:general的放在general, project的放在project,你把這個寫進CLAUDE.md跟.claude/rules 如何」

「我覺得這是idd-issue的責任,他應該要有能力判斷issue要開在哪。我覺得可以參考中華民國憲法」

「我的意思就是要更新idd的repo」

「我是要修改plugin的protocal唷」

使用者最初打算把分派規則寫進自己 workspace 的 CLAUDE.md / .claude/rules,隨即自己改判:這不該是每個 workspace 各抄一份的慣例,而是 IDD protocol 本身的責任

現場演示:本 issue 自己就是案例

這個 issue 誕生時,cwd 在一個 lab workspace repo(其 config 指向該 lab 的 tracker),但 issue 的性質是 IDD plugin 的功能需求。機械 walk-up 會把它開到 lab tracker。實際是靠使用者補一句「我的意思就是要更新 idd 的 repo」才導正——那句話就是這個缺口的證據

已造成的實際分散

一條連續的資料 pipeline 工作線,issue 落在兩個 tracker:前兩案在上層 lab repo,後續案在中途被 extract 出去的 project repo。成因是時序(project 中途獨立成 repo,walk-up 的結果隨之改變),但沒有任何機制在當下察覺「這條線的歸屬已經改變」。事後查全貌必須兩邊都翻,且要先知道有兩邊。


Type

feature

Priority

P1(本週)


設計參考:中華民國憲法第十章「中央與地方之權限」

使用者指名的參考。憲法解的正是同一個問題——哪些事歸中央、哪些歸地方——其解法是均權制度,既非中央集權亦非地方分權:

憲法 對應到 IDD 現況
第 107–110 條:列舉中央 / 省 / 縣各自的事項 candidates[].when / groups[].when predicates(Mechanism 3) 已有
第 111 條前段:「除…列舉事項外,如有未列舉事項發生時,其事務有全國一致之性質者屬於中央,有全省一致之性質者屬於省,有一縣之性質者屬於縣」 未列舉時,依事務性質歸屬 ——直接落到 cwd walk-up
第 111 條後段:「遇有爭議時,由立法院解決之」 判不出來時 AskUserQuestion 交使用者裁決 部分——Step 2.5 只在 predicate 命中且與預設不同時才問

三個可直接搬用的設計要點:

  1. 列舉在前,性質在後。 憲法不是只寫總括判準(那會在沒想到的邊界自己長出答案),也不是只做列舉(那會遺漏)。它先窮盡列舉,未列舉者才用判準兜底。IDD 已有列舉(predicates),缺的正是兜底那一層。這也與本 repo 既有的「能列舉的就列舉」紀律相容——判準是列舉的補集,不是列舉的替代品。

  2. 判準寫進本文,不留給慣例。 第 111 條把「全國一致之性質」直接寫在憲法裡,不靠事後釋憲累積。對應:性質判準要寫進 references/config-protocol.md,而不是每個 workspace 的 CLAUDE.md 各寫一份——後者正是使用者一開始的想法,且被他自己否決。

  3. 判準看「性質」不看「名義」。 一件事名義上掛某 project,性質上卻是跨 project 的行政事務,就該歸上層。實例:某 project 的差旅費核銷 issue,名義屬該 project,性質是機構行政 → 正確歸屬是機構層 tracker。目前這個判斷完全靠人腦臨場補,沒有成文規則,換 session 未必判得一樣。


Expected

references/config-protocol.md 新增一個機制(暫稱 residual clause),位置在 Mechanism 3(predicates)之後、Mechanism 4(walk-up)之前:

  • predicates 全部未命中時,先做性質判斷,而不是直接 fall through 到 walk-up
  • 判準方向(細節留 diagnose 展開):這件事的性質是「跨 project 一致」還是「單一 project 專屬」
    • 跨 project 一致(工具鏈、機構行政、跨專案 infra)→ 上層 / general repo
    • 單一 project 專屬(該 project 的 bug / feature / 資料)→ 該 project repo
  • 判不出來或低信心 → AskUserQuestion 交使用者裁決,不靜默猜(對應第 111 條後段的爭議解決)
  • 寫在 protocol 層 → 所有 idd-* skill(issue / diagnose / implement / verify)共用同一把尺(使用者明示:「我是要修改plugin的protocal唷」)

Actual

references/config-protocol.md 現有六機制 + Mechanism 3.5:

  1. --target flag(per-invocation override)
  2. candidates + ask_each_time(選單)
  3. predicate-based auto-selection(需事先寫好 when clause
  4. cascading config walk-up(機械,純依 cwd
  5. git remote fallback(bootstrap 用)
  6. groups(正交,跨 repo cross-link)

predicates 沒寫或沒命中 → 直接 fall through 到 walk-up 的 github_repo沒有任何一步問「這件事在性質上屬於誰」

Impact

  • 跨 repo 工作線斷裂:同一條線的 issue 依 cwd 散落到不同 tracker,事後查不到全貌,且要先知道有幾邊
  • 性質跨層判錯:名義掛 project、性質屬機構層的 issue 開錯層
  • 判斷不可重複:靠當下人腦補判,換 session / 換人未必一致
  • 作用範圍:改 protocol → 所有 idd-* skill 受惠;只改 idd-issue 則 diagnose / implement 仍用舊尺,同一條線兩把尺

Out-of-scope

  • 既有已分散 issue 的回收 / 搬遷(另議)
  • Mechanism 6 groups 的跨 repo cross-link 機制(正交,不動)
  • 各 workspace 自己的 CLAUDE.md / .claude/rules 寫法(本 issue 的結論正是不走那條路

相關

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions