Skip to content

lens 貢獻:zz-brand-new - #38

Closed
kiki830621 wants to merge 10 commits into
mainfrom
contrib/zz-brand-new
Closed

lens 貢獻:zz-brand-new#38
kiki830621 wants to merge 10 commits into
mainfrom
contrib/zz-brand-new

Conversation

@kiki830621

Copy link
Copy Markdown
Member

貢獻的 lens

  • code / zz-brand-new — 來源:本機 /tmp/paitest/ul2/code.csv;純新增

目標層:② lens pack(plugins/pai-lenses/lenses/

/parallel-ai-agents:ensemble-contribute-lenses 產生。

BananaBay69 and others added 10 commits August 2, 2026 07:54
三層 lens 疊加的層 ②。裝了這個 plugin,ensemble 審閱的 lens 集合會自動疊上
lenses/<profile>.csv。

初版只帶一條 code lens(docs-vs-code:註解與文件相對於它所描述的程式碼是否
仍然為真)。刻意不預先塞滿 —— lens 是量測儀器,該由使用它的人依需求增補,
而這個 repo 的價值正是讓增補的成本降到「改一個 CSV」。

刻意不建立空的 academic.csv / lecture.csv:存在卻解析出 0 條的檔案會讓
consumer 發出警告(那是刻意設計的防安靜失敗),缺席才是靜默的正確狀態。

CI 守兩件事:plugin.json 必須有 semver version(缺了 cache 目錄名會是
unknown、consumer 定位不到,pack 等同沒裝),以及每個 CSV 必須解析出
至少一條 lens。
官方文件(code.claude.com/docs/en/plugin-marketplaces)寫的 fallback 是
git commit SHA,不只是 unknown —— unknown 是實測在 claude-plugins-official
幾個 plugin 上看到的另一種情況。兩者都不是 semver,結論不變(定位不到),
但敘述要準。

順帶補上「版本沒變使用者不會收到更新」這個同源後果。
首個 CI run 直接紅在「workflow file issue」:run: | 是 YAML block scalar,
每一行都必須保持縮排,而 heredoc 的 body 照慣例寫在第 0 欄 —— 兩個規則直接
衝突,YAML 從那裡起就不再屬於這個 block。

改成獨立的 scripts/validate.py,順帶得到一個 contributor 可以在本地跑
一模一樣的檢查的入口。

雙向驗證過:拿掉 version → exit 1;把 header 改成 keys → exit 1;還原 → exit 0。
…3713b76c8e'

git-subtree-dir: plugins/pai-lenses
git-subtree-mainline: 6fc6883
git-subtree-split: dc32e24
pai-lenses 原為獨立 repo,理由是「讓第三方各自發 pack」。但
bin/pai-collect-lens-layers 的 PACK_PLUGIN 寫死單一 pack 名、find_pack_dir
只 glob */pai-lenses —— 架構只認一個官方 pack,該理由不成立。經裁示定位為
官方增補層,故併回本 repo。

- git subtree add 保留 pai-lenses 的 3 個 commit history
- marketplace.json 的 source 由 github 改為 ./plugins/pai-lenses,與主 plugin 一致
- 其 validate.yml 併入本 repo test.yml 為獨立 job(working-directory 各自分離);
  併入後落在 plugins/ 下的 workflow 不會被 GitHub 執行,故移除以免誤導
- scripts/validate.py 不動,貢獻者仍可本機跑同一支

已驗證 collector 讀的是 plugin cache 路徑(~/.claude/plugins/cache/*/pai-lenses/<semver>/),
與 marketplace source 宣告為 github 或相對路徑無關,故併回不影響 lens 解析。
三層疊加建立了「怎麼疊」,但層 ③(user)原是單向終點:寫在
~/.claude/pai-lenses/<profile>.csv 的 lens 只有本機吃得到。本 skill 是它的出口。

判準核心是「能不能只用一條 lens 表達」:lens pack 的 CSV 描述得了 lens,
描述不了 profile 級的 title / daFocus / codexDefault。故新 profile 必須進層 ①,
且缺的欄位一律向使用者索取、不代填(那是設計決定不是格式轉換)。

override 標記預設不送:它會替所有使用者移除一條調校過的 lens,而且傷害是靜默的
(被取代者不會收到通知)。要送須確認、須理由、須 --include-override。

配套文件:
- lens-layers.md 開頭加「我想加 lens,該去哪」決策表,四種情況直接對到動作
- regen 腳本的檔頭改為 GENERATED FILE — DO NOT EDIT,因實測有人(含本 session)
  第一次就誤以為 builtin-lenses.csv 可編輯
6-AI ensemble 對 PR #34 回報 15 個 HIGH。它們不是 15 個獨立缺陷,是本 PR 的
核心承諾(讓 user 層 lens 有回流路徑)在兩處斷掉:

A. skill 沒有起點也沒有終點
   - 新增 Phase 0 定位可修改的 repo(在 repo 內/有 push 權 clone/外部貢獻者 fork),
     全流程路徑改以 $REPO_ROOT 為唯一基準
   - Phase 6 補上 git switch/add/commit/push + gh pr create
   先前所有路徑默默假設 cwd 是本 repo 的 clone,但這個 skill 鎖定的使用者手上
   只有 plugin cache —— 那不是 git checkout,不能 commit。

B. bump 只做一半
   層 ①② 的指令、決策表、lens-layers.md、pack README 全部改成兩處
   (plugin.json + marketplace.json entry)。只改一處時 merge 後使用者收不到
   新版且無任何錯誤訊息,正好是這個 skill 想達成的相反面。

另外三個判定錯誤:
- 比對改用 pai-parse-lens-csv 不用 grep(focus 是可含換行的 quoted prose,
  grep 拿到的是實體行不是欄位值;且 key/profile 來自使用者輸入,插進
  grep -E 是 regex/option 注入)
- profile 存在性改查真源(新增 bin/pai-list-profiles)—— builtin-lenses.csv
  由 lens 產生,lenses: [] 的 custom 在投影裡一列都沒有,拿它問存在性必定
  答錯並在 PROFILES 產生重複 key 靜默蓋掉既有 profile
- Phase 6 的 catalog 檢查改驗冪等 —— 原本的 git diff --exit-code 會把
  層 ① 的正常流程(Phase 5 已 regen)判成失敗

機械閘門(先前只寫在散文裡):
- validate.py 加 check_marketplace_sync / check_profiles / 註解列偵測
- 整合錨點 bats:用真實 plugins/pai-lenses 內容驗併回後的 cache 解析
- root CLAUDE.md 不再宣告「唯一的 plugin」,版本同步改逐 plugin 表格

三道新閘門與整合錨點皆雙向驗過(正常通過 / 破壞後轉紅)。
bats 86/86、node 45/45、shellcheck、py_compile、catalog 無 drift。
R2(6-AI ensemble)回報 18 個 HIGH,其中 8 個指向同一件事:這個流程不可能以
「文件裡的一串 bash 區塊」的形式運作。AI 逐個 fenced block 呼叫 Bash 時每次
都是新 shell(REPO_ROOT/USER_DIR 到下一個 block 全空)、profile 從未被賦值、
沒有 set -e 所以 validate.py 不是閘門(失敗後仍照常 commit/push/開 PR)。

R1 補齊了缺的段落,但沒有讓它能跑。這是形式問題不是內容問題。

- 新增 bin/pai-contribute-lenses:整條流程一支腳本,SKILL.md 退回薄封裝。
  不代填設計決定(新 profile 缺欄位/override 缺理由 → exit 3 交回 skill 問)。
  驗證是真閘門:未過 exit 1 且保證尚未有任何 git 寫入。bats 10 條 + 3 處 mutation。
- 與 built-in 逐字相同的 lens 判 SKIP 而非 MODIFY(builtin 的 focus 先前是 dead code)
- catalog 檢查改無條件比對 —— 用「catalog 有沒有被改」當 proxy 時,
  「改了 PROFILES 卻忘了 regen」正好讓檢查整段被跳過
- profile 查詢區分「失敗」與「查無」—— 壓成同一個 exit code 會把 node 缺席
  讀成新 profile,在 PROFILES 產生重複 key 靜默蓋掉既有 profile
- check_marketplace_sync 改查所有相對路徑 plugin(主 plugin 先前完全沒閘門)
- 新增 check_bumped:改了 lens 就必須 bump,不只「兩處一致」。
  CI 帶 --base 且改 fetch-depth: 0(shallow clone 會讓這檢查安靜地不存在)
- CSV 範本複製的偵測改對目標:真正的危害是欄位錯位不是 # 註解列
- README 補 pai-lenses 安裝路徑 —— 舊 repo 封存後那是唯一的入口,先前沒寫
- bump pai-lenses 0.1.0 → 0.2.0(本 PR 改了它卻沒 bump,自己違反自己的規則)

bats 96/96、node 45/45、shellcheck、py_compile 全綠。
@kiki830621

Copy link
Copy Markdown
Member Author

誤觸:ensemble verify 過程中在暫存 clone 上實跑 pai-contribute-lenses 導致意外開 PR,立即關閉。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants