① 文章 → 網頁

複製後貼進 Claude,再接著貼上文章。

幫我把這篇文章做成一頁式網頁,輸出成單一個 index.html,照這些規則:
開始前先決定輸出資料夾:
- 先檢查目前專案裡,是否已有同一篇文章,或同一對話中近期建立、修改的文章資料夾。有一個明確候選就直接沿用,不要另開新資料夾。
- 判斷順序是文章來源或標題、現有內容,最後才參考建立或修改時間。時間相近不能單獨當成同一篇文章。
- 如果有多個合理候選、無法確定,先問我要沿用哪一個。
- 完全找不到才根據文章標題建立一個新的文章資料夾。
- 確定後,只在該資料夾輸出單一個 index.html;不要放在專案第一層,也不要再建立第二個文章資料夾。

網頁規則:
1. 不要改寫、刪減或自行增加文字,只能重新排版我的內容。
2. 桌機版與手機版都要清楚好讀;桌機有適當的內容寬度與留白,手機在 360px 寬度不可水平捲動。
3. 文字層級、留白、對比與按鈕都要清楚可讀;小標題做成明顯區塊,重點句可以加粗或放大。
4. 視覺風格可以自行決定,但整頁的配色、字體與間距必須一致。
5. 開頭做標題區:文章標題放大,副標只能從我的原文挑選,不能自己編。

做完後自我檢查:是否沿用或建立了正確的文章資料夾、是否只輸出一個 index.html、我的文字是否被改動,以及桌機與 360px 手機畫面是否都正常。

把今天的自動化帶回家

下載 Skill 後交給 Claude,即可開始使用。

文章 → IG 輪播

下載 content-to-carousel.skill
查看 content-to-carousel 完整內容

---
name: content-to-carousel
description: 把一段文章、網頁或講義內容變成一組可以直接發的 IG 輪播貼文圖(多張 1080×1350 直式卡片)。當用戶說「做成 IG 輪播」「把這篇變成能發 IG 的圖」「轉成 IG 圖文」「做一組貼文圖」「把這篇拆成幾張卡」,或想把一段內容變成手機上一張張滑、字夠大的直式圖時,務必使用這個 skill。輸出是一組可以直接發的 PNG 圖檔(每張 1080×1350),不是影片、不是一份要用戶自己截圖的 HTML——有出圖能力時(Claude Code/能跑 headless 瀏覽器)就把每張卡截成 PNG 直接交付。用戶可以附一張「風格參考圖」定義視覺,只學它的配色/字體/間距氣質、不搬文字內容。想把網頁做成「影片/Reels」請改用 web-to-reels。
---

# 做一組 IG 輪播貼文圖

把用戶已經寫好的內容,變成一組能發 IG 的直式輪播圖。**做完的定義=交出一組 PNG 圖檔**(每張 `1080×1350`),不是丟一份 HTML 叫用戶自己截圖。

> 內容是用戶的,你的工作是**拆重點+排版+出圖**,不是重寫他的字。

## 開工前先問齊(不要留占位、不要事後補)

動手前先主動把這三件事問清楚——**不要先做好、把 handle 留成 `@你的帳號` 占位再叫用戶補**:

- **你的 IG 帳號(handle)是什麼?** 每張卡右下角都要放,問到才開工。
- **要幾張?** 預設一組輪播(封面+內容+收尾,約 4–6 張);用戶明講只要單張才做單張。
- **有沒有風格參考圖?** 有就請他附一張(只學氣質、不搬內容);沒有就用乾淨預設,不用卡在這。

問齊再動手,一次到位。

## 先沿用同篇內容的輸出資料夾

出圖前先確定一個文章層級的絕對路徑 `OUTPUT_DIR`,後續所有媒體 Skill 都沿用它。不要直接把成果散在寬泛的專案根目錄,也不要讓輪播與 Reels 各自建立文章資料夾。

依下列順序判定:

1. 先確認來源身分:本機檔案用 canonical path+內容 fingerprint,公開網頁用 final URL+文章標題,直接貼上的文字用標題或首段萃取穩定 slug。
2. 先沿用同一對話中已建立或已使用的文章資料夾;跨對話時,掃描來源檔案附近與目前專案下近期建立/修改的子資料夾。
3. 判斷候選時,依序看:是否有相同來源的 `.creator-output.json`、是否包含同一篇文章的 HTML/Markdown/caption/輪播/Reels、資料夾名是否符合文章標題或 slug。建立/修改時間只用來輔助排序,不能單獨認定,避免同時處理兩篇文章時放錯。
4. 來源本來就在明確的文章專屬資料夾時,直接沿用該資料夾。只有一個明確候選時直接沿用;有多個合理候選且無法排除時,在寫檔前只問使用者要沿用哪一個。
5. 完全找不到候選時,才在目前專案的輸出根目錄建立 `<article-slug>/`。slug 使用小寫英數與連字號;沒有可靠標題才詢問,不使用 `untitled`、`output` 等模糊名稱。
6. 確定後,在 `OUTPUT_DIR/.creator-output.json` 記錄 `schema: creator-output/v1`、canonical source、title、fingerprint(可取得時)與 `output_dir` 絕對路徑。後續再次處理同一來源時,內容相符的這份標記優先於時間判斷。

本 Skill 的工作檔與成品一律放在 `CAROUSEL_DIR="${OUTPUT_DIR}/carousel"`;來源 HTML/文章留在原位,不擅自搬移。確定路徑後整次任務固定使用,不得中途另開第二個文章資料夾。

## 四步

### 1. 收內容、拆卡

拿用戶給的文章/段落,拆成一組卡片:

- **封面(第 1 張)**:一句抓人的主標,講「這組在講什麼/看完得到什麼」,不要把答案講完——讓人想滑下去。
- **內容(中間 3–5 張)**:**一張一個重點**,用他自己的話濃縮,不改寫核心用字、不自己編新內容。
- **收尾(最後 1 張,可選)**:一句總結或行動呼籲+handle。
- **總數預設 4–6 張**(含封面)。太長就挑最抓人的幾點,寧可少;一張讀得完比塞滿有用。IG 輪播最多 10 張。

### 2. 定風格,每張一致

- 附了**風格參考圖**:只學它的**配色、字體感覺、間距、邊框氣質**,套到每張卡;**不搬圖裡的文字或內容**。學氣質、不搬成品。
- 沒附圖:用乾淨預設——淺底(白/米)+一個強調色標重點+大標+條列。
- **一致性是輪播的命**:所有卡片同一組顏色、同一個字體、同樣的邊界與 handle 位置,只有內容在變;右上角放頁碼(`01 / 05`)。

### 3. 出圖:先做 HTML,再截成 PNG(這步是「做完」的關鍵)

**做法(一卡一檔,最不會出錯):**

1. 在 `CAROUSEL_DIR` 為每張卡各做一個**獨立、自包含的 HTML 檔**(`card-01.html`…`card-0N.html`),每個檔的 `<body>` 就是一張正好 `1080×1350` 的卡,CSS 全內嵌、不連任何外部字體/圖片/CDN。卡片容器記得 `box-sizing: border-box`,避免 padding 把內容擠出 1080×1350 畫布。
2. 對每個檔各截一張圖,尺寸鎖死 1080×1350:
   ```
   <chrome> --headless --window-size=1080,1350 --screenshot=carousel-01.png --default-background-color=FFFFFFFF card-01.html
   ```
   `<chrome>` =本機的 `chrome-headless-shell`(見下方環境注意)。一張卡一個檔、一次指令,依序命名 `carousel-01.png`…`carousel-0N.png`。
   - ⚠️ **不要**把 N 張卡堆在同一個 HTML 裡再連截 N 次——同一份檔連截只會得到 N 張「第 1 張卡」。要嘛一卡一檔(推薦),要嘛截一張 `1080×(1350×N)` 的長圖再依 1350px 切開,例如第 N 張:`sips -c 1350 1080 --cropOffset $((($N-1)*1350)) 0 long.png --out carousel-0N.png`(或 ImageMagick `convert long.png -crop 1080x1350+0+$(((N-1)*1350)) carousel-0N.png`)。
3. 想給用戶一眼看全貌,可把 N 張 PNG 併成一張 contact sheet(橫向並排)附上。

**交付前必驗(三項,缺一不可):**

- 尺寸每張都是 `1080×1350`(`sips -g pixelWidth -g pixelHeight carousel-0X.png` 核對)。
- N 張內容**各不相同**(不是連截出的重複圖)。
- **中文沒有變成豆腐字**(□□□)——headless 環境若缺 CJK 字型會這樣,看一眼 PNG 或 contact sheet 確認。

**環境注意**:`chrome-headless-shell` 常**不在 PATH** 上(HyperFrames 會裝在 `~/.cache/hyperframes/chrome/…` 底下);先找到它的實際路徑再用,或 `npx hyperframes doctor` 確認 Chrome 那項是綠的。若明明路徑對了還是 `permission denied`,先確認指到的是執行檔不是資料夾,必要時 `xattr -d com.apple.quarantine <路徑>` 解除 macOS Gatekeeper 封鎖。若截出來中文是方塊字,代表這個環境缺中文字型,改用系統瀏覽器截圖或先裝字型。

**fallback(只有純網頁環境、完全沒出圖能力時)**:才退回「交一份自包含 HTML+告訴用戶每張卡各自截圖」。這是退路,不是預設。

### 4. 給發文文字(caption)

順手附一段可貼在 IG 貼文框的說明文字+幾個 hashtag,用戶複製即用。

## 版面規範(照這個出來的圖才合 IG、手機才讀得清)

- **尺寸**:每張卡固定 `1080×1350`(IG 4:5 直式),用一個固定尺寸外框 `<div>` 鎖住截圖範圍。
- **安全邊界**:內容左右各留 ≥ 64px、上下各留 ≥ 72px,重要的字不貼邊(IG 會裁、手機殼會擋)。
- **字要大**:封面主標約 **72–96px**;內頁重點標 **56–72px**、說明 **32–40px**。寧可大到「有點誇張」,縮到手機剛好。
- **一張一個重點**:內頁別把三件事塞一張。
- **對比要夠**:深字淺底或淺字深底,不要灰底灰字。
- **一致性**:顏色/字體/邊界/handle 位置每張相同,右上放頁碼。

## 例子

**用戶輸入**:一篇「GA4 用超商解釋 Event / Session / User」的文章 + 一張暖色調、等寬字、有邊框感的風格參考圖 + handle `@例子帳號`。

**你要做的(5 張)**:
1. 封面:`用超商,一次搞懂 GA4 的三個詞`,關鍵詞上強調色,不劇透。
2. Event:`在店裡做的每一件事`——結帳、取貨、買咖啡。
3. Session:`從進店到離店這段時間`——閒置 30 分再回來算新的。
4. User:`與其說「人」,更像「裝置」`——除非全程登入又有 user_id。
5. 收尾:`換健身房也一樣通` + `@例子帳號` + 一句收藏呼籲。

每張同一套暖色+等寬字、右上頁碼 `0X / 05`、右下 handle,文字全用這篇文章的。

**輸出**:在 `OUTPUT_DIR/carousel/` 內把 `card-01.html`…`card-05.html` 各截成 `carousel-01.png`…`carousel-05.png`(每張 1080×1350、內容不重複、中文正常)+一段 caption,**直接交付給用戶**(可再附一張 contact sheet 看全貌)。

## 提醒

- 出 PNG 用本機的 `chrome-headless-shell`(HyperFrames 已裝的那個),不需要 Bun、Playwright 或 API token;找不到路徑或截出豆腐字時見上方「環境注意」。
- 用戶只要**單張**時,照同規範做**一張封面式的圖**即可;預設做一組輪播。
- 這個 skill 出的是**圖**;要把網頁做成**影片/Reels** 請改用 `web-to-reels`。

網頁 → Reels 短影片

下載 web-to-reels.skill
查看 web-to-reels 完整內容

---
name: web-to-reels
description: 把已存在的單檔 HTML、本機網頁或公開網址,直接做成經檢查、預覽確認、可發布到 IG/Reels 的 1080×1920 直式 MP4。使用者說「把網頁變影片」「做成 Reels」「轉直式短片」「網頁變 IG 影片」或要把已完成的網頁延伸成短影片時,應使用本 skill。它會在目前 sandbox 續跑既有進度,只補做缺少或過期的 BRIEF、capture、分鏡、composition、preview、render;不適用於網頁捲動錄影,也不適用於貼文圖/輪播。
---

# 把網頁變成一支直式短影片

輸入是一個已經存在的網頁;輸出是一支可播放、經視覺檢查的 `1080×1920` MP4,以及一段可貼到 IG/Reels 的 caption。

這是一條獨立而窄的 Reels 流程。直接使用已安裝的 HyperFrames CLI 與需要的共用 domain skill;**不得要求、安裝或呼叫 `product-launch-video` skill**,也不要在本 skill 複製它的完整產品影片流程。

## 固定原則

- 預設直接在目前 sandbox 完成,不先問 sandbox 或本機二選一。
- 不提供 `fast`/`full` 模式,也不讓使用者選模式。品質關卡固定;只有已有效完成的步驟可省略。
- 本機 HTML 直接用 loopback HTTP 服務 capture,不必公開部署。
- 不把網頁錄成捲動影片。capture 用來取得內容與設計依據;composition 才是成片來源。
- 正式 render 永遠綁定目前 preview 的明確授權;「幫我做成影片」不等於已核准尚未看過的 preview。
- 只更新這次任務真正需要的檔案,不覆蓋來源 HTML。

## 先確認輸入

來源只有兩種:

- 對話裡已有單檔 HTML 或本機網頁:沿用確切檔案/服務位址。
- 對話裡沒有:只問一題,請使用者提供 HTML 路徑或公開網址。不要自行編網址。

從網頁與對話萃取 message、受眾、CTA 與片長。只有會明顯改變內容方向且無法可靠判斷的缺口才問;不要詢問流程模式。

預設無旁白、無配樂。只有使用者明確要求音訊時,才確認音訊素材與所需能力;沒有音訊需求時,完全跳過 auth、語音、配樂與音訊服務檢查。

## 先沿用同篇內容的輸出資料夾

開始 HyperFrames 工作前先確定一個文章層級的絕對路徑 `OUTPUT_DIR`,讓網頁、輪播與 Reels 共用同一篇文章的資料夾。不要直接把成品散在寬泛的專案根目錄,也不要為 Reels 再建另一個文章資料夾。

依下列順序判定:

1. 先確認來源身分:本機檔案用 canonical path+內容 fingerprint,公開網頁用 final URL+文章標題。
2. 先沿用同一對話中已建立或已使用的文章資料夾;跨對話時,掃描來源檔案附近與目前專案下近期建立/修改的子資料夾。
3. 判斷候選時,依序看:是否有相同來源的 `.creator-output.json`、是否包含同一篇文章的 HTML/Markdown/caption/輪播/Reels/`RUN-STATE.json`、資料夾名是否符合文章標題或 slug。建立/修改時間只用來輔助排序,不能單獨認定,避免同時處理兩篇文章時放錯。
4. 來源本來就在明確的文章專屬資料夾時,直接沿用該資料夾。只有一個明確候選時直接沿用;有多個合理候選且無法排除時,在寫檔前只問使用者要沿用哪一個。
5. 完全找不到候選時,才在目前專案的輸出根目錄建立 `<article-slug>/`。slug 使用小寫英數與連字號;沒有可靠標題才詢問,不使用 `untitled`、`output` 等模糊名稱。
6. 確定後,在 `OUTPUT_DIR/.creator-output.json` 記錄 `schema: creator-output/v1`、canonical source、title、fingerprint(可取得時)與 `output_dir` 絕對路徑。後續再次處理同一來源時,內容相符的這份標記優先於時間判斷。

本 Skill 的最終成品一律放在 `REELS_DIR="${OUTPUT_DIR}/reels"`;來源 HTML 留在原位,不擅自搬移。確定路徑後整次任務固定使用,不得中途另開第二個文章資料夾。

## 先掃狀態,再決定下一步

優先續跑與目前來源及 `OUTPUT_DIR` 相符的既有 HyperFrames 專案;舊版專案即使不在新路徑,只要 `RUN-STATE.json` 能證明來源一致也可沿用。沒有專案才建立 `OUTPUT_DIR/reels/project`。先讀,不要因看見檔名就假設它有效:

- `RUN-STATE.json`
- `BRIEF.md`
- capture 產物
- `STORYBOARD.md`
- `compositions/frames/*.html` 與專案根目錄的 `index.html`
- snapshots/contact sheet
- final preview 狀態
- `out.mp4`

### 用雜湊維持產物血緣

用 `RUN-STATE.json` 記錄每一層的輸入雜湊與輸出雜湊。至少包含:

- output:`OUTPUT_DIR` 與 `REELS_DIR` 的絕對路徑
- source:來源種類、canonical path/final URL、內容 fingerprint、capture 時間
- brief:`BRIEF.md` 雜湊與對應的 source fingerprint
- capture:實際 capture 位址、source fingerprint、capture 產物雜湊
- storyboard:`BRIEF.md` 與 capture 雜湊
- composition:storyboard、capture 與 composition 檔案雜湊
- preview:composition 雜湊、最近一次通過的 check、snapshot/preview 證據
- render:獲准的 preview/composition 雜湊、MP4 雜湊與 `ffprobe` 結果

本機單檔 HTML 的 fingerprint 至少包含 canonical path 與檔案 SHA-256;若它引用本機 CSS、JS 或媒體,也納入雜湊。無法完整列出依賴時視為不確定,不跨任務重用 capture。

公開網址的 fingerprint 至少包含 final URL、主文件內容雜湊,以及可取得的 `ETag`/`Last-Modified`。若伺服器沒有可信的變更依據,capture 只在本次任務內可重用;下次任務重新 capture,避免拿舊頁面配新文案。

沒有 `RUN-STATE.json` 時,不以「檔案存在」當成新鮮證據。只有能從檔案內容與實際檢查無歧義重建血緣時才沿用;其餘從最早的不確定步驟重做。

### 有效性與失效傳遞

| 產物 | 有效條件 | 失效時連帶作廢 |
|---|---|---|
| `BRIEF.md` | 必要欄位齊全,source fingerprint 與目前來源一致 | storyboard、composition、preview、MP4 |
| capture | 對應目前來源 fingerprint,命令成功,必要內容/token/素材非空且可讀 | storyboard、composition、preview、MP4 |
| `STORYBOARD.md` | 對應目前 brief+capture 雜湊,5–7 段、時間與文案完整 | composition、preview、MP4 |
| composition | 對應目前 storyboard+capture,frame 與 index 可掛載,`check` 通過 | preview、MP4 |
| preview | 對應目前 composition,midpoint snapshots 已逐張目視,final preview 可正常播放 | MP4 |
| MP4 | 對應已核准的 preview/composition,檔案非空,`ffprobe` 尺寸、片長、串流符合需求 | 無 |

上游內容或雜湊一變,下游即使檔案還在也算過期。不要刪除舊產物來假裝狀態乾淨;更新血緣後再產新版。

### 從最接近交付的位置續跑

依序套用第一個符合的狀態:

1. MP4 有效:只重跑輕量的存在性與 `ffprobe` 驗證後交付。
2. preview 有效且已獲目前版本 render 授權:直接 render、驗 MP4。
3. composition 有效:做 snapshots/contact sheet、final preview、取得授權。
4. storyboard 有效:補 composition,接著 check 與視覺關卡。
5. capture 有效:補 storyboard 與其後步驟。
6. brief 有效:補 capture 與其後步驟。
7. 沒有有效專案:init、寫 brief,再往下做。

## 專案與 Skill 初始化

新專案只 init 一次:

```bash
HYPERFRAMES_SKIP_SKILLS=1 npx hyperframes init "<OUTPUT_DIR>/reels/project" --non-interactive --example=blank
```

`<OUTPUT_DIR>` 必須換成前一步確定的真實絕對路徑。可以先建立父層 `REELS_DIR`,但 `project` 目標目錄交給 `init` 建立;先 `init`,再在專案內寫 `BRIEF.md`、`RUN-STATE.json` 或執行紀錄,不要先在 `project` 目標目錄放入任何檔案。`HYPERFRAMES_SKIP_SKILLS=1` 是必要設定,避免 CLI 初始化時額外安裝本流程沒有依賴的 skill。

每次任務至多執行一次 `hyperframes skills update`。它不是固定開場步驟;只有必要 domain skill 缺少或 CLI 明確要求更新時才執行。若本次已跑 `init`,由 init 處理共用 skill refresh,不再另跑 update,避免同一件事做兩次。

依工作需要載入共用能力:

- composition 結構、時間軸、可重現性:`hyperframes-core`
- 動態與 seek-safe 動畫:`hyperframes-animation`/`hyperframes-keyframes`
- capture、check、snapshot、preview、render:`hyperframes-cli`
- 只有使用者提供媒體或要求音訊時:`media-use`

domain skill 提供規則與能力,不接管這條 end-to-end 流程。

## `BRIEF.md`

至少寫入:

```yaml
---
workflow: web-to-reels
aspect: 1080x1920
narration: no
language: zh-Hant-TW
duration: 20-35s
---
```

內文包含:

- 確切素材來源與 source fingerprint
- 一句核心 message
- 受眾與 CTA
- 5–7 段、20–35 秒
- 鉤子 → 痛點 → 轉折 → 機制 → 成果 → CTA 的敘事方向
- 視覺依 capture 的設計 token,不搬網頁截圖、不自行加外部圖片
- 預設 `music: none`、無旁白;使用者另有明確要求才改

只要 brief 的內容方向改變,就更新 brief 雜湊並讓 storyboard 以下失效。

## Capture

本機 HTML 在其所在資料夾啟動 loopback 服務:

```bash
python3 -m http.server <port> --bind 127.0.0.1
```

確認實際頁面可讀後,在專案內 capture:

```bash
npx hyperframes capture "<實際網址或本機服務位址>" -o ./capture --timeout 120000
```

`<...>` 必須換成真實位址。本機 capture 完成後停止 HTTP 服務,不留背景程序,也不要求公開部署。

先嘗試這個最接近目標的 capture;不要固定先跑完整 doctor。

## 分鏡與 composition

`STORYBOARD.md` 排 5–7 段,每段只講一個重點、約 3–5 秒;全片約 20–35 秒。最後一段保留穩定的 CTA hold。

簡單、共用同一套設計系統的多個畫面,由主代理一次或分批製作,共用 token、版型與動態語言。只有畫面本身複雜而且彼此獨立,且目前 runtime 已獲准使用 subagent 時,才可按一組獨立畫面委派;禁止固定一個 frame 派一個 agent。

寫 composition 前讀 `hyperframes-core`;需要動畫時再讀相應 domain skill。每段要有真正可掛載的 `compositions/frames/NN-*.html`,由專案根目錄的 `index.html` 組成完整時間軸;不可只交文字分鏡。

子 composition 內的素材路徑一律以 HyperFrames 專案根目錄為基準,例如 `assets/logo.png`、`capture/screenshot.png`;禁止使用 `../` 或 `../../`。這些畫面由專案根目錄提供服務,向上跳層會讓 Studio 與正式輸出找不到素材。

### Reels 版面規範

- 畫布固定 `1080×1920`(9:16)。
- 重要文字與 CTA 避開最上 12% 與最下 17%。
- 全片沿用 capture 的配色、字體、間距與圖形語言;色面以兩個為上限。
- 不搬網頁截圖,不自行加外部圖片、漸層或陰影。
- 主字在手機上要能讀,對比足夠;一段只留一個視覺焦點。
- 動態需 deterministic、可 seek;採長尾緩動,讓重點停留到讀得完。
- 轉場服務敘事,不為了炫技讓每段換風格。

## 固定品質關卡

步驟可因有效產物而省略,但以下關卡不可降級:

1. composition 完成後執行:

   ```bash
   npx hyperframes check --snapshots
   ```

   `check` 必須通過。不要再先跑一個重複的 standalone lint。

2. 以每段 midpoint 產 snapshot/contact sheet:

   ```bash
   npx hyperframes snapshot --at <各段 midpoint,以逗號分隔>
   ```

   必須逐張實際看圖,確認沒有黑畫面、空白畫面、裁切、溢位、過小文字、錯誤色彩或安全區遮擋;看不到就不得判定通過。

3. 開 final composition preview:

   ```bash
   npx hyperframes preview
   ```

   交付可開啟的 preview 位置,請使用者針對目前版本選擇修改或核准 render。核准要記錄 composition/preview 雜湊;composition 之後若改動,舊核准立即失效。

4. 只有取得目前 preview 的明確核准後才 render:

   ```bash
   npx hyperframes render --quality high --output out.mp4
   ```

5. 驗證成品:

   ```bash
   test -s out.mp4
   ffprobe -v error -show_streams -show_format out.mp4
   ```

   回源確認影片為 `1080×1920`、duration 合理、可解碼;預期無音訊時不得意外帶音軌,明確要求音訊時要確認音軌存在。不要只因檔案存在就說完成。

驗證通過後,把最終 MP4、snapshot/contact sheet 與 caption 放到 `REELS_DIR`;不要只留在內部 `project` 目錄。建議固定命名為 `reel.mp4`、`contact-sheet.jpg` 與 `caption.md`。最後交付這些檔案的絕對路徑與實際片長。

## 環境錯誤才啟動修復

不要以完整 doctor 當固定前置成本。先執行狀態所需、最接近交付的命令:現成 MP4 就先 `ffprobe`,現成 composition 就先 `check`,缺 capture 才先 capture。

只有命令出現瀏覽器/Chrome/Chromium/共享函式庫相關錯誤時,才讀 `references/sandbox-recovery.md`,並依固定順序處理:

1. 保留失敗命令、工作目錄/位址,以及能指出根因的最短完整錯誤片段。
2. 跑 `npx hyperframes doctor --json`,讀 `.ok` 與失敗項,不能只看 exit code。
3. 跑 `npx hyperframes browser path`;搜尋系統與既有 Playwright/Puppeteer Chromium。
4. 找到候選執行檔後先用 `<path> --version` 測試,再設定 `HYPERFRAMES_BROWSER_PATH`。
5. 沒有可用瀏覽器才跑 `npx hyperframes browser ensure`,再取一次 path。
6. 仍失敗才安裝 Playwright Chromium,設定 path。
7. 重跑 doctor,再重試最初失敗的 capture/check;doctor 變綠本身不算管線成功。

只有錯誤明確符合 Linux ARM64、`libXdamage.so.1` 或其他 reference 條件時,才套用相應修復。禁止:

- 編譯假的共享函式庫
- 偽造安裝成功或檢查結果
- 下載 x64 瀏覽器冒充 ARM64
- 建立高風險系統級 symlink
- 用未驗證的繞過方式掩蓋錯誤

Node、`npx`、FFmpeg 或 `ffprobe` 缺失時,只修復目前階段真正需要的能力。需要權限時只詢問必要權限,不把任務改問成 sandbox/本機二選一。

### 必要能力與安全降級

必要能力包括:讀取來源、capture、composition、check、snapshot/preview、經授權 render、MP4 驗證。使用者明確要求的音訊也屬必要需求。必要能力經規定順序修復仍失敗時停止,不交假成品。

未被要求的音訊、額外媒體、進階特效或非核心整合屬非必要能力;失敗時可省略並清楚說明降級內容,不得讓它阻擋無聲 Reels。

Capture 最終仍失敗時,回報可操作的最短說明:

- 失敗的實際命令與來源位址
- 根因錯誤行
- 已完成的修復順序
- 下一個仍可行的動作;若已無 sandbox 修復方式,再詢問是否改在使用者電腦執行

尚未執行的步驟要標「未執行」與原因,不能列成已嘗試。