name: aibdd-pen-to-storybook
description: >
Adapter for Pencil .pen design files. Reads .pen → returns normalized
component_table + Tailwind 4 tokens. Pure read-only — does NOT write files.
Pencil-side adapter implementation of the cross-source design adapter contract;
future siblings (aibdd-figma-to-storybook, aibdd-penpot-to-storybook) follow
the same component_table + tokens return shape so downstream consumers
(/aibdd-form-story-spec, /aibdd-plan Phase 3 component-design merge,
/aibdd-green-execute Wave 1) stay design-source-agnostic.
metadata:
user-invocable: false
source: project-level dogfooding
aibdd-pen-to-storybook
Pencil .pen adapter skill。read-only:讀 .pen JSON,抽 design tokens、挑 single screen、做 component
candidate detection,回 component_table + tokens 給 caller。不寫任何檔、不建專案、不 npm install、不
build storybook。
被 /aibdd-form-story-spec Phase 1 的 design-source cross-check 與(未來)/aibdd-plan Phase 3 component-design
merge sub-phase DELEGATE。
只負責「把已 freeze 的 .pen 解析成 component_table + tokens 推理包」;不重新做設計、不替設計者做顆粒度判斷、 不對非 React 框架輸出、不寫 component / story / project files(那些是 form-story-spec 與 green-execute 的職責)。
Program-like SKILL.md — self-contained notation
3 verb classes (type auto-derived from verb name):
- D = Deterministic — no LLM judgment required; future scripting candidate
- S = Semantic — LLM reasoning required
- I = Interactive — yields turn to user
Yield discipline (executor 鐵律): ONLY
Iverbs yield turn to the user.DandSverbs MUST NOT pause for user reaction. In particular:
EMIT $x to useris fire-and-forget — continue immediately to the next step; do not wait for acknowledgment.WRITE/CREATE/DELETEare side effects, not phase boundaries — execution continues to the next sub-step.- Phase transitions (Phase N → Phase N+1) and sub-step transitions are non-yielding.
- Mid-SOP messages of the form 「要繼續嗎?」/「先 review 一下?」/「先 checkpoint?」/「先停下來確認?」/「want me to proceed?」/「should I continue?」are FORBIDDEN. The ONLY way to ask the user is an
[USER INTERACTION] $reply = ASK ...step.STOP/RETURNare terminations, not yields — no next step follows.SSA bindings:
$x = VERB args(productive steps name their output);$xis phase-local;$$xcrosses phases (declared in phase header's> produces:line).Side effect:
VERB target ← $payload—←arrow = "write into target".Control flow:
BRANCH $check ? then : else(binary) or indented arms (multi);GOTO #N.M= jump to Phase N step M (literal#phase.step).Canonical verb table (T = D / S / I):
Verb T Meaning READ D 讀檔 → bytes / text WRITE D 寫檔(內容已備好) CREATE D 建立目錄 / 空檔 DELETE D 刪檔(rollback) COMPUTE D 純運算 DERIVE D 從既定規則推算 PARSE D 字串 → in-memory 結構 RENDER D template + vars → string ASSERT D 斷言 invariant;fail-stop MATCH D regex / pattern 比對 TRIGGER D 啟動 process / subagent / tool / script;output 可 bind DELEGATE D 呼叫其他 skill MARK D 紀錄狀態(譬如 TodoWrite) BRANCH D 分支(吃 $check/$kindbinding)GOTO D 跳 #phase.stepliteralIF / ELSE / END IF D 條件 sub-step LOOP / END LOOP D 迴圈(必標 budget + exit) RETURN D 提前結束 phase STOP D 終止整個 skill EMIT D 輸出已生成資料(fire-and-forget;不 yield,continue 下一 step) WAIT D 等待已 spawn 的 process THINK S 內部判斷(不印 user) CLASSIFY S 多類別分類 → enum 之一 JUDGE S 二元語意判斷 DECIDE S 從 user reply / context 推結論 DRAFT S 生成 prose / 訊息 EDIT S LLM 推 patch 改既有檔 PARAPHRASE S 改寫 / 翻譯 prose CRITIQUE S 批評 / 建議 SUMMARIZE S 抽取重點 EXPLAIN S 對 user 解釋 why ASK I 問 user 等回應(仍配 [USER INTERACTION]tag);唯一允許 yield turn 給 user 的 verb。Planner-level skill 對 user 的提問必須DELEGATE /clarify-loop,不得直接ASK(其他角色的 skill 自決)。
§1 REFERENCES
references:
- path: references/role-and-contract.md
purpose: caller 入口契約 + 角色定位 + 不做事項(adapter-only)
- path: references/format-reference.md
purpose: '.pen v2.x JSON schema verbatim + Tailwind 4 token namespace 對照(component_table 給 caller 直接用)'
- path: references/dsl-best-practice.md
purpose: 'component_table 命名 / variant enum / Tailwind 4 token 慣例(caller 渲染 .tsx 時參考)'
- path: references/patterns/tokens-mapping.md
purpose: '.pen Document.variables → Tailwind 4 @theme namespace 對照'
- path: references/patterns/component-detection.md
purpose: '6 條 component candidate heuristics + 表格輸出契約'
- path: references/anti-patterns.md
purpose: '常見錯誤:framework 拼錯、Tailwind 4 syntax 走 v3、@layer 用錯等'
- path: references/fail-codes.md
purpose: 'Phase N dispatch — failure_kind → caller-return message'
§2 SOP
Phase 1 — ASSERT intake|驗證入口
produces:
$$pen_path,$$screen_id?
$contract= READreferences/role-and-contract.md$$pen_path= PARSE caller-provided.pen檔絕對路徑$$screen_id= PARSE optional 指定 screen ID(缺項則 Phase 4 由 caller 確認)$payload_ok= JUDGE$$pen_pathagainst$contract- ASSERT
$payload_ok - ASSERT path_exists(
$$pen_path) - ASSERT
$$pen_path副檔名 ==.pen
Phase 2 — VERIFY .pen 可解析
produces:
$$pen_doc,$$schema_version
$schema= READreferences/format-reference.md$file_kind= MATCHfile $$pen_path結果- ASSERT
$file_kind含UTF-8/ASCII text(拒收 binary、舊版 .pen) $$pen_doc= PARSEjq '.' $$pen_path$$schema_version= PARSE$$pen_doc.version- ASSERT
$$schema_versionmatches^2\.\d+$ - ASSERT
$$pen_doc.childrenis array && length > 0
Phase 3 — EXTRACT tokens|抽 Tailwind 4 tokens
produces:
$$tokens
$mapping= READreferences/patterns/tokens-mapping.md$variables= PARSEjq '.variables' $$pen_path$$tokens= DERIVE empty list- LOOP per
$var_name, $varin$variables4.1$ns= MATCH$var.typeagainst$mappingnamespace table -color→--color-<name>-string(font family) →--font-<role>-number含radius→--radius-<name>-number含spacing/gap→--spacing-<name>-number其他 →--<name>custom var -boolean→ SKIP(不入 Tailwind) 4.2$entry= DRAFT{ name: $var_name, namespace: $ns, value: $var.value }4.3$$tokens= DERIVE append$entryEND LOOP - ASSERT count(
$$tokens) >= 1(沒有任何 token 通常代表 .pen 沒設計過)
Phase 4 — MAP screen tree|挑選並讀取單一 screen
produces:
$$screen_node,$$node_tree_pretty
$top_level= PARSEjq '[.children[] | {id, name, type, w: .width, h: .height}]' $$pen_path- BRANCH
$$screen_idis set true: 2.1 ASSERT$$screen_id ∈ $top_level[].idfalse: 2.2 RETURN$top_levelto caller,請 caller 指定$$screen_id後重啟 Phase 4 2.3 STOP $$screen_node= PARSEjq '.children[] | select(.id=="$$screen_id")' $$pen_path$$node_tree_pretty= RENDER pretty-print of$$screen_node(縮排樹;節點顯示 type / id / name / size / fill / layout)- 用
$$node_tree_pretty作為 Phase 5 的 input;不要在多個 screen 上同時跑 component detection(會混淆抽象)
Phase 5 — DETECT component candidates|套用 heuristics
produces:
$$component_table
$rules= READreferences/patterns/component-detection.md$skip_list= PARSE$rules.always_inline(topBar / bottomBar / sidebar / hero…)$candidates= DERIVE empty list- APPLY
$rulesheuristics 1–6 順序對$$screen_node子樹掃描: 4.1reusable: true節點 → 強制 component 4.2 numeric-suffix 重複(tile1..N)→ 推導state/variantenum 4.3 prefix grouping(chipA0..A2 / chipB0..B3)→ 推導kind×count雙 enum 4.4 同 subtree 不同文案 →contentprop 4.5 同 subtree 不同 fill / text-color → enumstateprop 4.6comp/、Component/前綴 → 顯式 component intent $$component_table= DRAFT 表格 columns:Component | Source nodes | Detected props | Stories- LOOP per
$candidatein$candidates6.1 ASSERT$candidate.nameis PascalCase(小寫開頭強制改 PascalCase 寫進表格) 6.2 ASSERT$candidate.props至少含一個 prop(無差異 → 不抽,inline) 6.3$candidate.stories= DERIVE list of observed states (3–6 推薦上限) 6.4$$component_table= DERIVE append row END LOOP - ASSERT count(
$$component_table.rows) >= 1
Phase 6 — REPORT adapter
produces:
$$report
$$report= DRAFT { status: "completed", mode: "adapter", pen_path:$$pen_path, screen_id:$$screen_id, schema_version:$$schema_version, token_count: count($$tokens), tokens:$$tokens, component_count: count($$component_table.rows), component_table:$$component_table}- RETURN
$$reportto caller
Phase 7 — HANDLE dispatch
produces:
$$caller_msg
$failure_kind= CLASSIFY runtime failure into one of the kinds enumerated inreferences/fail-codes.md$$caller_msg= DERIVE caller-return message from$failure_kindperreferences/fail-codes.md- RETURN
$$caller_msg
§3 CROSS-REFERENCES
- 上游:Pencil GUI + MCP(探索期)— 設計者 freeze 後產出
.pen,再交給 caller skill 把本 adapter 的pen_path拼進 caller payload。 - 直接下游(DELEGATE caller):
/aibdd-form-story-specPhase 1 design-source cross-check — 比對 caller reasoning 之component.identifier/stories[].export_name是否在本 adapter 的component_table內,不一致時 warn(不 override)。/aibdd-planPhase 3(未來 component-design merge sub-phase)— 把本 adapter 的component_table + tokens與 features × activities 合成 enrichedboundary_delta.components,下游分流到 form-story-spec(寫 component + story)與 green-execute(補業務邏輯)。
- Sibling adapters(同 contract,不同設計來源):未來
aibdd-figma-to-storybook/aibdd-penpot-to-storybook等遵循同一 return shape(status / mode / token_count / tokens / component_count / component_table),讓下游不耦合任一設計來源。 - 不做:寫回 .pen、做視覺探索、選 design system 元件、做業務 BDD step 綁定、scaffold Next.js 專案、跑 npm install / tsc / build-storybook(這些已在歷史版本砍除;scaffold 屬
/aibdd-auto-starter,component / story 寫檔屬/aibdd-form-story-spec,業務邏輯屬/aibdd-green-execute)。 - 視覺回歸 baseline(optional companion,非本 skill SOP 內步驟):若
@pencil.dev/cli已安裝且已認證,user 可在 caller 流程結束後外部執行pencil interactive -i <pen_path> -o /dev/null <<< 'export_nodes({ nodeIds: ["SCREEN_ID"], outputDir: "./baseline" }); exit()'自行產 baseline 圖。本 skill 不主動觸發。
§4 ORPHANED REFERENCES (已棄用,未來清掃)
下列檔案是舊版 scaffold mode 殘留,SOP 已不再 LOAD,保留實體檔以利 git history / 未來考古:
references/patterns/project-scaffold.md— 舊版 Phase 6 scaffold project 用的 package.json / tsconfig / .storybook / app/ 模板。新流程下 scaffold 屬/aibdd-auto-starter的 template 職責。
未來清掃時整批刪除即可,不影響本 skill 行為。