| 47 | Tailwind utility registry compliance(對齊 Atlassian @atlaskit/tokens / Carbon / Ant / Polaris token-first) | check_opacity_token_usage.sh(讀 packages/design-system/src/tokens/utility-registry.json SSOT;原計畫 rename → check_tailwind_token_registry.sh 未實作,功能已在 check_opacity_token_usage.sh)。檢 leading-N / tracking-* / `gap-px |
| 48 | Unused / orphan token detector(2026-05-21 升級:跑 scripts/audit-orphan-tokens.mjs --check SSOT,不用 raw grep var() — 漏 Tailwind @theme inline bridge + @utility body + class-name match + JS literal mirror,N 條合法消費路徑 false-positive)。Script 內建 structural-keep 分類器(palette tier 1-10 / mask alpha / chart reserved / state variants / neutral / SOP 5-piece / JS literal mirror)per tokens/orphan-tokens.spec.md SSOT。真 retire 候選 = comprehensive scan 後仍 0 consumer + 不落任何 structural-keep 類別。0 真孤兒 = PASS;有真孤兒 → user 拍板 retire OR 補 structural-keep 新類別 | |
| 49 | a11y axe-core 自動跑 + contrast ratio(Storybook a11y addon + Carbon AVT + Atlassian linters) | Per *.stories.tsx 跑 axe-core via Storybook a11y addon;WCAG AA contrast ≥ 4.5:1(text)/ 3:1(large text / UI)。Carbon 每 PR 跑 AVT,Atlassian 季度 audit + linter integration。本 dim 缺 = a11y 漏在 spec.md 寫了但無自動驗 |
| 50 | Bundle size budget per component(Material UI size-limit / Material Web public tracking / Ant tree-shake) | Per component gzip size 上限(eg. Button ≤ 5KB / DataTable ≤ 50KB);CI fail if regress > 10%。對齊 size-limit pkg + Carbon export audit。需建 package.json size-limit 段 + per-component manifest |
| 51 | Theme / density visual matrix(Material 3 dynamic color / Apple HIG Dynamic Type) | Deep mode 每 core story 跑 light/dark/high-contrast/density-md/density-lg/RTL 6-cell matrix screenshot diff;baseline drift > Δ% → flag。對齊 Polaris visual regression / Carbon dark token matrix |
| 52 | Header canonical cross-family invariants(W1-W6,2026-05-17 ship per M31 codex 共識,對齊 GitHub Primer + Ant + Material v1) | Per chrome / overlay header tsx 跑:(W1) 含 Tabs child 必有 withTabs prop(border auto-suppress) (W2) tabs padding = header padding(--layout-space-loose) (W3) --tab-height-lg == --chrome-header-height(md/lg 對等) (W4) header + tabs flush stack 無 negative margin (W5) tabs default = sm 已 land + md 標 future tier (W6) cva default 已從 md 改 sm。Hook 3:check_tab_lg_chrome_header_equal.sh(W3) / check_header_with_tabs_border.sh(W1) / check_chrome_header_handcraft.sh(Layer 3 ChromeHeader consumption) |
| 53 | Code-to-spec reverse drift check(2026-05-17 user 抓 Phase 1 漏抓 FileViewer h-14 spec drift,新加 dim) | 對每 component grep packages/design-system/src/components/<X>/<X>.tsx 的 className 硬寫 utility(h-14 / w-80 / px-loose 類)→ 反向掃對應 <X>.spec.md 是否仍寫「固定 h-NN」「寫死」keyword 但 code 已 migrate to token = drift。互補既有 forward Dim 15/20(spec → code)。Hook check_spec_class_drift.sh write-time soft P1 warn,本 dim batch verify 既有 60+ 元件 spec.md。錨例:2026-05-17 Phase 1 我 file-viewer.spec.md L103 寫「Known drift:h-14 硬寫不消費 token」但 file-viewer.tsx:333 已 h-[var(--chrome-header-height)],3+ 次 /design-system-audit --deep 都沒抓到反向 drift |
| 54 | M35 Nearest same-purpose canonical compliance(2026-05-20 codify per codex Layer B D4) | 對每 *.stories.tsx wrap 既有 primitive(Sidebar / DataTable / ChromeHeader / Dialog / Sheet / Popover)的 file 跑:(a) 檔頭含 @story-baseline: cite marker?(b) .claude/references/story-baseline-registry.json 內 primitive 的 requiredHelpers 全 import?(c) antiPatterns regex 任一 match → fail?(d) variantRules button variant + size + iconOnly + pressed 全 satisfy?Hook check_story_invariants.sh R8 write-time soft warn,本 dim batch verify。錨例:2026-05-20 AppShell stories 連 5 round drift 後 codex Layer B 抓 root cause = SSOT 消費被當引用儀式 |
| 55 | Token cross-namespace mapping integrity(2026-05-20 codify per user 抓 red→deep-orange bug 100+ audit 沒發現) | tokens/color/semantic.css 每 hue interaction token(--blue-hover / --red-hover / ...)必指向同名primitive(--red-hover: var(--color-red-N)),禁跨 hue 混(--red-hover: var(--color-deep-orange-N) 違反)。Primitive 12 hue 全該有對應 interaction(blue/red/deep-orange/orange/amber/yellow/lime/green/turquoise/indigo/purple/magenta)。Status semantic(--error-hover 等)直指 primitive,不透過 hue layer。錨例:2026-05-20 semantic.css:246 --red-hover: var(--color-deep-orange-5) cross-namespace bug,100+ audit 沒發現 = audit 沒檢 token mapping integrity |
| 56 | AppShell primary-header consistency(2026-05-21 codify per user 抓「primary-header = primary-sidebar + 一條 global header」+「globalHeader 存在時 sidebar 內 header 該拿掉」) | 對每 consumer .tsx(stories / app code)grep layout="primary-header",verify:(a) 同 file 含 globalHeader= prop(否則邏輯矛盾)/(b) 同 file 不含 <SidebarHeader>(WorkspaceBrand 該在 globalHeader,不重複)。World-class cite:GitHub repo sidebar 無 header(org/repo 在 global breadcrumb)+ Gmail / Figma file editor sidebar 無 header(brand 在 global top bar)。Hook check_app_shell_primary_header_consistency.sh write-time block(P1 warn,可 escape // @app-shell-primary-header-allow:)。對應 app-shell.spec.md「WorkspaceBrand 放置 SSOT」段 |
| 57 | M29 DS Anchor Preflight enforcement coverage(2026-05-26 codify per user verbatim「該程式化的都沒程式化」) | 對每 *.tsx(production code,非 stories / test)grep wrap DS primitive(<Sidebar> / <AppShell> / <DataTable> 等)→ verify 過去 30 turns transcript 含 Grep/Read tool call hit packages/design-system/src/**/*.spec.md 或 *.stories.tsx,OR 檔頭含 @story-baseline: marker 或 inline 3-column owner table。Hook check_ds_anchor_preflight.sh write-time soft BLOCKER。對應 meta-patterns.md M29 + self-verify.md Pre-edit phase。錨例:2026-05-26 App.tsx 漏 SidebarTrigger / collapsible / startIcon mock-drift = M29 hook 不存在使 infra 沒攔 |
| 58 | Fork-user plugin install enforcement(2026-05-26 codify per user「我們做那麼多 plugin 不就是要避免這件事?」) | SessionStart hook check_fork_user_plugin_install.sh 偵測:(a) cwd 不是 DS repo(無 packages/design-system/src)/(b) package.json 含 @qijenchen/design-system dep /(c) ~/.claude/plugins/design-system/ OR .claude/plugins/design-system/ 不存在 → 三題 YES 印強制提示。互補 product-workspace scripts/check-plugin-installed.mjs npm postinstall layer。+ 2026-05-30 fork-committed bootstrap 層(補 chicken-egg:plugin 硬 hook 隨 plugin 才裝,沒裝前無 mechanical 防線):fork 自帶 template/ds-product-template/.claude/hooks/check_plugin_bootstrap.sh(SessionStart 每 session 提醒,fail-open)+ block_production_edit_without_plugin.sh(PreToolUse 硬攔 apps/** production .tsx/.ts/.css edit,沒裝 plugin → exit 2 BLOCK,escape CLAUDE_BYPASS_PLUGIN_BOOTSTRAP=1)+ .claude/settings.json hooks 註冊;不依賴 plugin(committed in fork),mirror allowlist .claude ship 給 published fork。對應 product-workspace/CLAUDE.md「第 −1 步」段 |
| 59 | Approval preflight scope coverage(2026-05-26 extend per user「未來其他人 fork 用其他元件也偏移」) | check_substantive_edit_approval_preflight.sh scope 從 packages/design-system/src/** 擴大到 apps/**.{tsx,ts,css} + node_modules/@qijenchen/design-system/**。Audit verify hook regex 涵蓋三 scope + allowlist *.stories.tsx/*.test.*/scripts/*。對應 memory/feedback_ship_then_revert_anti_pattern.md SSOT |
| 60 | M26 propose-without-benchmark enforcement(2026-05-26 backfill) | UserPromptSubmit hook check_propose_without_benchmark.sh 偵測 user prompt 含 propose / 建議 / 方案 / 看法 / visual / behavior keyword + 過去 20 turns transcript 中 WebFetch/WebSearch tool_use count < 2 → soft inject 提醒「propose 前必跑 ≥3 source benchmark」。對應 meta-patterns.md M26 + propose-options/SKILL.md。錨例:2026-05-05 user 反覆糾「為什麼每次都沒 webfetch 只憑印象」 |
| 61 | M16 item-list gap + M23(c) DataTable framework prop conflict enforcement(2026-05-26 backfill) | PreToolUse hooks 兩 invariant:(a) check_item_list_gap.sh — 2+ <FileItem> / <MenuItem variant="rich"> 在同 NEW content 且無 gap-N / space-y-N parent → warn(M16);(b) check_data_table_size_num_to_meta_width.sh — ColumnDef 上下文出現 size: <number> 但無 meta: { width: ... } → warn TanStack size:px vs DS size:density 框架 prop 衝突(M23(c))。對應 meta-patterns.md M16 + M23(c) + item-anatomy.spec.md + data-table.spec.md |
| 62 | Fork-user Netlify onboarding canonical(2026-05-26 codify;2026-06-05 二修 → 免費密碼 = Edge Function Basic Auth,SSOT memory/feedback_netlify_basic_password_canonical_2026_05_29.md Rule 1) | Audit product-workspace + fork repos:(a) netlify.toml 含 access control:X-Robots-Tag noindex header + [[edge_functions]] path="/*" function="basic-auth" wire + comment 指向 edge function 免費機制(不寫「Basic Password 免費 / _headers 免費」= drift); (b) netlify/edge-functions/basic-auth.ts 存在且讀 STORYBOOK_BASIC_AUTH env var 做 HTTP Basic Auth(讀 Authorization → 比對 → 缺/錯回 401 + WWW-Authenticate);.storybook/manager-head.html 不 含 Netlify Identity widget script(我們用 edge-function Basic Auth,client-side Identity widget 不需要;若仍含 widget = 殘留 drift); (c) scripts/setup-netlify-access.mjs 含「沒 Netlify 帳號」前置 explainer + gh auth pre-check + 最後印 dashboard URL 教 user 在 Environment variables 設 STORYBOOK_BASIC_AUTH = user:password(不教「點 Basic Password radio」= 舊 flow drift); (d) package.json 有 setup:netlify npm script; (e) CLAUDE.md Access control 段含「Claude 引導使用者 Netlify onboarding」≥6 條話術(解釋 Netlify / GitHub 1-click OAuth / 免費 = edge-function Basic Auth 設 env var 30 秒 / SEO header 已 ship / deploy 驗證 / GitHub CLI 未 login / Codespaces cloud-dev path)+ 真實斷點清單(plugin install + OAuth + env var 設 + password 分享 4 斷點)+ 禁寫「_headers/Dashboard Basic Password 免費」「Identity 已 deprecated」(皆 2026-06-05 官方 docs 證實為錯)段。錨例:2026-05-26 user「Claude 會知道引導 user 完成環境建置嗎?」+ 2026-06-05 user「仔細查查研究」抓出免費密碼 = Edge Function(Dashboard + _headers 都 Pro $20/mo;Identity 2026-02 撤回 deprecate 但是 full-login 不適合 simple gate) |
| 63 | Deploy URL auto-reply infra(2026-05-26 codify per user verbatim「完成部署之後都應該自動回吐部署的連結,每次必定自動回,不論是現在這個 session 還是其他的」) | Audit product-workspace + fork repos:(a) scripts/deploy-url.mjs 存在 + executable + 輸出 production 或 preview URL JSON;(b) package.json 有 deploy-url script wired;(c) DS-side hook .claude/hooks/inject_deploy_url_after_push.sh 偵測 git push origin <branch> PostToolUse Bash → auto inject deploy URL into AI context;(d) hook scope skip push --delete(branch cleanup 非 deploy);(e) hook silent skip if no .netlify/state.json 或 scripts/deploy-url.mjs(DS repo 自身 + 非 Netlify-wired repos 不誤觸發)。Cross-session benefit:hook ship via plugin → 任何 fork user /plugin install 後自動受惠 |
| 64 | Post-main-push SSOT propagation canonical(2026-05-26 user correction「不是只要一 knowledge audit deep 之後就要,是等我 push main 後才要」) | Audit:(a) CLAUDE.md # Git solo-work canonical 有 Step 5.5 SSOT propagation 段;(b) Hook check_post_main_ssot_propagate.sh 存在 + 註冊在 PostToolUse Bash matcher;(c) hook 偵測 git push origin main + diff HEAD~..HEAD 含 SSOT-affecting paths(packages/design-system/src + packages/storybook-config/{addons,addons-preset.ts,preview.tsx}(無 src/)+ .claude/{rules,hooks,skills,commands,references} + .claude-plugin/*.json + hooks/hooks.json + CLAUDE.md)→ inject 提議 bump beta.N+1;(d) cross-repo SSOT sync 統一由 CLAUDE.md Step 5.5 + check_post_main_ssot_propagate.sh canonical trigger(push-main-based;不需 skill-specific Phase Z,/knowledge-prune + /deep-audit-cross-codex 不複製,DRY);(e) 整鏈 cover 任何 SSOT-affecting 來源(/knowledge-prune / /deep-audit-cross-codex / 一般 dev / 新元件 / bug fix)。對應「一次更新所有 DS repo 增刪改,不需手動 1 個 1 個」directive |
| 65 | Chrome header avatar canonical(2026-05-27 codex Step 4 cite battle + user 抓 UserFooter vertical stack drift) | 對每 production tsx + DS sidebar.stories.tsx / anatomy / principles 跑:<SidebarHeader> block 內偵測 <ItemAvatar> → 違反 chrome-header canonical(per header-canonical.spec.md:57-72 / sidebar.spec.md:241-247 / item-anatomy.spec.md:513-537「chrome header 不是 row context」)。正確 pattern = raw <Avatar size={24}>。Hook check_chrome_header_avatar_canonical.sh PreToolUse Edit/Write 用 python multiline regex 對 <SidebarHeader>...<ItemAvatar>...</SidebarHeader> block 偵測;SidebarFooter / SidebarMenuButton row context 不攔(footer IS row context per spec)。錨例 2026-05-27 product-workspace App.tsx + DS 3 sidebar stories 連動 fix |
| 66 | Immediate cross-repo dispatch + visual parity gate(2026-05-27 codex collab Q3 共識) | Audit:(a) DS .github/workflows/release.yml 含「Dispatch product-workspace sync」step 用 repository_dispatch event_type=ds-published 立即 trigger;(b) product-workspace .github/workflows/sync-design-system.yml 接 repository_dispatch event 自動 bump deps + PR(取代 Renovate weekly);(c) consumer fixture gate:packed DS install to product-workspace,build storybook,DS canonical story vs product story masked screenshot diff;(d) visual-assertions.json coverage manifest 每 component .spec.md ↔ ≥1 visual scenario(目前 AppShell/BulkActionBar/FieldControlGroup pending — 列 TBD per release gate scope);(e) npm pack ships(scripts/visual-audit.mjs deferred per files allowlist 範疇,plugin SKILL.md 取代) |
| 67 | SidebarMenuButton implicit-wrap canonical(2026-05-27 codify per user 抓 UserFooter 垂直 stack root cause) | 對每 production tsx grep:<SidebarMenuButton> 無 asChild 但 children 含 <ItemAvatar> 或 <Avatar> → 違反(SidebarMenuButton 沒 asChild 時把 children 全塞進 ItemLabel 單 span → Avatar+text 同 span 垂直 stack)。Hook check_sidebar_menu_button_implicit_wrap.sh PreToolUse Edit/Write 用 python multiline regex 攔。正確 pattern:asChild + <div role="group"> + <span data-sidebar="menu-label" className="min-w-0 flex-1 truncate"> per sidebar.stories.tsx#UserFooter。錨例 2026-05-27 product-workspace App.tsx UserFooter Avatar 跟 label 垂直堆疊 |
| 68 | Stories-vs-spec canonical drift(2026-05-27 codify per user「DS 自己 stories 教錯 = consumer 抄 stories 抄錯」root cause) | 對每 component *.stories.tsx + *.anatomy.stories.tsx + *.principles.stories.tsx grep:含 <SidebarHeader> 內 <ItemAvatar> / 同類 spec 明文禁止的 pattern → 違反(DS 教 consumer 錯 pattern,類似 2026-05-27 sidebar 3 stories 在 WorkspaceBrand 用 ItemAvatar 違反 chrome header canonical)。Action:DS canonical stories 加 // @canonical-pattern: <pattern-name> marker 標哪 helper 是 consumer 應抄的正確 reference;反 spec stories block 必加 // @anti-pattern: <pattern-name> 警示。配 Dim 53(spec-vs-code)+ 本 dim(spec-vs-stories)雙向 drift verify。對應 hook 預留 — 目前由 check_chrome_header_avatar_canonical.sh + check_sidebar_menu_button_implicit_wrap.sh 攔具體錨例;系統性 stories drift audit run via design-system-audit Dim 68 batch sweep |
| 69 | Consumer no-DS-catalog enforcement(2026-05-27 M31 codex synthesis per user「眼不見為淨」+「做產品真的能使用跟 ds repo 一模一樣的元件做產品嗎?」) | 對 consumer apps/**/*.stories.tsx grep:basename 為 EveryDsComponent / AllDsComponents / catalog naming + Object.keys(DS).map iterate-render + mass hand-mock(≥5 distinct <DS.X> 單 file)→ 違反(DS catalog 是 DS Storybook 唯一 SSOT,consumer 重寫必 drift,2026-05-27 錨例 7 bug)。Hook check_consumer_no_ds_catalog.sh PostToolUse Write/Edit BLOCKER,escape // @consumer-catalog-allow:。允許 portal proxy(iframe to DS Storybook) |
| 70 | Consumer @story-baseline enforcement(2026-05-27 M31 codex synthesis) | 對 consumer apps/**/*.stories.tsx grep:用高風險 DS primitive(DataTable / Dialog / Sheet / Popover / DropdownMenu / Tooltip / HoverCard / LinkInput / RadioGroup / CircularProgress / AppShell / Sidebar)但無 // @story-baseline: <DS-story-path>#<exportName> marker → 違反(consumer 必 reference DS canonical story 才 enable visual diff CI)。Hook check_consumer_story_baseline.sh PostToolUse BLOCKER,escape // @story-baseline-allow:。SSOT mapping → ds-story-manifest.json(DS package ship) |
| 71 | Consumer DS primitive misuse anti-pattern(2026-05-27 per user「做產品真的要能使用跟 ds repo 一模一樣的元件」) | 對 consumer apps/**/*.{tsx,ts} production + stories grep:<CircularProgress size={N}> literal number 覆蓋 default 24 / <RadioGroupItem> 無 <SelectionItem control={...}> wrap / <DataTable columns={[single-col]}> minimal / <LinkInput placeholder=...> 無 value prop / <Empty title=...> 無 icon AND 無 description / Overlay story 無 defaultOpen 視覺 snapshot 看不到 content / 硬寫色值-字級-shadow 繞 token(bg-[#hex] / text-[14px] / shadow-md,2026-06-02 Pattern 8,CF conformance-model 主防線)。Hook check_consumer_ds_primitive_misuse.sh BLOCKER。Per-violation cite spec.md file:line。Escape // @ds-misuse-allow: |
| 72 | DS API surface tightening(2026-05-27 — 治標 vs 治本) | Hook 71 偵測 anti-pattern 是 lint 層攔截;治本要 DS API design 強到 misuse 即 fail tsc。Audit:逐 component review API surface — size?: number 該改 'sm'|'md'|'lg' enum / columns: Column[] 該加 min length runtime check / title + description 該有 type-level XOR / Overlay primitive defaultOpen 該 require explicit。配套 codify in tightening-roadmap.md(per-component列 anti-pattern + tight API proposal),分 quarter ship。對應 Dim 71 是攔當前 misuse,本 dim 是消除未來 misuse 可能 |
| 73 | Full-story visual+interaction sweep enforce(2026-05-27 codex M31 P0 finding) | Audit report JSON storyResults.length === manifest.totalStories(916)。Sample < 916 = reject(per user「不准抽樣」)。Hook check_full_story_visual_interaction_sweep.sh PostToolUse audit-report.json BLOCKER。Escape "_sampling_allowed": "<rationale>"(極罕見) |
| 74 | Overlay open/focus/Escape probe(2026-05-27 codex M31 P0 finding + user 7-bug 錨點「overlay 沒彈出」) | Consumer story 用 Tooltip / Popover / Dialog / Sheet / DropdownMenu / HoverCard Trigger 必含 defaultOpen OR open={true} OR play() interaction click。Trigger-only catalog = reject(visual snapshot 看不到 content)。Hook check_overlay_open_focus_escape_probe.sh BLOCKER。HoverCard exception via @story-trait-allow: missing-opensnapshot per codex |
| 75 | Plugin freshness session-start prompt(2026-05-27 chain-C ship + user「主動引導」directive) | Fork user session_start hook check_plugin_freshness.sh reads local installed plugin.json version → fetch GitHub raw marketplace.json → diff version → if stale prompt run npm run sync-all. Sync-all 1-command 整合 npm update + claude plugin marketplace update + claude plugin update + restart prompt(per user 2026-05-27「不需要獨立命令兩次」) |
| 76 | Escape marker abuse cap(2026-05-27 per user「不亂加 escape markers」) | Consumer file 10 escape markers 累計 ≥3 distinct types OR ≥5 total → BLOCK。修法 3 選 1:重構走 DS canonical / 拆 file / env override CLAUDE_BYPASS_ESCAPE_MARKER_AUDIT。Hook check_escape_marker_abuse.sh enforces escape philosophy「rare per-line documented exception,非 daily tool」 |
| 77 | Composition-fidelity:conformance-primary,pixel-identity opt-in(2026-05-27 ship / 2026-06-02 model 修正) | Consumer 對 DS 用法正確性主要由靜態 conformance 驗(dim 71 含 Pattern 8 + check_layout_space_magic_numbers + R7/R8),對齊世界級 static lint(Polaris stylelint-polaris / Atlassian eslint-plugin-design-system / Carbon stylelint-plugin-carbon-tokens;WebFetch verified)。scripts/composition-fidelity-visual-diff.mjs 的 pixel/DOM identity diff 改明確 opt-in:只比標 @composition-fidelity-mode 的 mapping(忠實複製 replica / same-story 跨版本回歸,對齊 Chromatic/Storybook same-story baseline);單獨 @story-baseline = conformance 不做 identity diff;0 opt-in → exit 0。禁 拿產品範本(內容刻意不同)pixel 比 DS showcase(world-class 公認反 pattern)。SSOT composition-fidelity.md。CI .github/workflows/composition-fidelity.yml |
| 78 | Codex brief 禁列檔 invariant(2026-05-27 codify per codex v1+v2 token-burn 2× anchor) | check_codex_brief_invariants.sh 4th invariant check:codex CLI brief 必含「禁列檔 / 禁 rg --files / 只讀 N file / 直接出 verdict」keyword,否則 codex 自動跑 rg --files 列 1300+ files 燒光 reasoning,無法產出 Step 5 Verdict(M31 Step 4.5 last-verdict gate fail)。Hook PreToolUse Bash codex exec/review 偵測 → BLOCKER。Escape // @codex-brief-invariant-skip: |
| 79 | Tailwind v4 wildcard pattern in docs(2026-05-28 codify per beta.27 6+ CI iteration anchor) | check_tailwind_wildcard_in_docs.sh P0 BLOCKER:.md/.spec.md/.sh 文件範例 var(--X-*) / var(--X-A/B/C) 寫法被 Tailwind v4 vite plugin scanner 當 literal class string 抓 → 產 invalid CSS(CSS 變數名禁 * /)→ Storybook build 死。改用 math notation var(--X-N) N∈{a,b,c}。Escape // @tailwind-wildcard-allow:。Anchor:beta.27 release CI iterations 1-6 死於此 |
| 80 | Addon subdir ship completeness(2026-05-28 codify per beta.27 7th iteration anchor) | check_addon_subdir_ship.sh P0 BLOCKER:addon 主檔(.storybook/addons/*/ + packages/storybook-config/addons/*/)import ./utils/* 等 relative subdir 但對應 dir 沒一起 ship → Rollup Could not resolve → CSF parse error cascade → build 死。修方向:(1) Copy 缺漏 dir(2) 跑 local build verify(3) commit。Escape // @addon-subdir-skip:。Anchor:beta.27 ds-devmode 搬 npm 包漏帶 utils/ 6 files |
| 81 | Storybook addon preset 必 .cjs extension(2026-05-28 codify per beta.27-.31 5 連敗 anchor) | check_storybook_addon_preset_cjs.sh P0 BLOCKER:addons/*/preset.ts 在 "type":"module" package 內含 createRequire / require.resolve / fileURLToPath(import.meta.url) → Node ESM scope vs esbuild-register CJS-transpile 衝突 → require not defined runtime fail。改 hand-written preset.cjs(.cjs override package type → 強制 CJS) + path.join(__dirname, ...) 返 absolute fs path。SSOT: memory/feedback_storybook_addon_preset_must_be_cjs.md。Escape // @preset-cjs-skip:。Anchor:2026-05-28 beta.27/.28/.29/.30/.31 5 連敗,beta.32 用 .cjs 才修 |
| 82 | Consumer app story title Apps/<app-name>/... namespace(2026-05-28 codify per template create-app duplicate-id anchor) | check_consumer_app_story_title.sh P0 BLOCKER:consumer apps apps/<name>/**/*.stories.{tsx,ts,mdx} 的 title: field 必開頭 Apps/<app-kebab-name>/...(per .claude/rules/story-rules.md 「Title 命名 2-namespace canonical」)。錯 prefix → Storybook glob 撈到 2 個同 id story → build duplicate warning + 只顯第一個 → 新 app 在 sidebar 不可見。Hook 從 file path 自動推 expected prefix。DS-internal stories(packages/design-system/**)走 Design System/... 另條 canonical,out of scope。Escape // @app-story-title-skip:。Anchor:2026-05-28 npm run create-app verify-flow-test e2e 抓 4 collisions,scripts/create-app.mjs:patchStoryTitles() 修生成 + hook 防手動 edit |
| 83 | Fork-context runtime + naming SSOT(2026-05-29 codify per user「fork 後 fork user 在自己獨立環境下仍能如預期運行」;net-new vs dim 62/63/64) | Net-new aspects 不在 dim 62/63/64:(a) Hook fire integrity in fork cwd — verify check_fork_user_plugin_install.sh(SessionStart)+ inject_deploy_url_after_push.sh(PostToolUse Bash)+ approval-preflight scope apps/**/*.tsx 在 fork cwd 正確 fire,plugin install 後 ${CLAUDE_PLUGIN_ROOT} 變數正確 resolve;(b) CLAUDE.md cross-load chain — fork CLAUDE.md Step 0 指向 node_modules/@qijenchen/design-system/CLAUDE.md + ds-canonical/rules/meta-patterns.md 真可讀(npm package files allowlist 含 ds-canonical);(c) Naming SSOT 3 層 — DS-internal source dir(template/ds-product-template/)≠ published GitHub Template Repository(ajenchen/ds-product-template)≠ fork user new repo 名(self-chosen)清楚 documented in template/README.md「命名 SSOT」段;(d) 跨 repo 交付 canary(2026-05-29 加,補 source→live 盲點) — node scripts/verify-published-deploy.mjs:L1 mirror workflow 最近 run 必 success(否則 published scaffold stale)+ L2 published .storybook/main.ts === 本地 template(mirror 真送達)+ L3 --live(給 NETLIFY_PREVIEW_PASSWORD)playwright 帶密碼 render 部署故事斷言非空白。Why net-new:dim 66 只驗 local fixture build,dim 83(a)-(c)只驗 source — 都沒驗「mirror 有沒有真把 source 送達 live netlify 部署」。Anchor:2026-05-29 mirror 從 5/26 默默失敗(PAT 無 workflow scope)→ published stale → netlify 空白,稽核數週沒抓到因無此 canary。Skill chain:/deep-audit-cross-codex Phase 0 cwd detection 切 ds-repo / fork-user-repo 2-mode 跑此 dim(2026-05-29 簡化 from 3-mode per 「避免原則無限膨脹」)。Anchor:2026-05-29 dir name vs published repo name SSOT confusion + ds-canonical mirror drift + mirror-deliver-to-live gap |