Back to skills
SKILL.md
Check Before
ASecurity交付前對「使用者指定的一份文件」做易讀性自檢:跑十一項機械掃描(編號連續、未定義代號與代號先用後定義、術語首次出現沒說明、 交叉引用、重複、異動紀錄用語、樣式一致、表格欄寬、內部推導痕跡、公文式敬稱、目錄頁碼),並擋 AI 工具名稱再加五條人工判斷, 回報要改的地方;pptx/docx/pdf 另做視覺檢查(用 PowerPoint/Word 實際排版,抓疊字、字跑出方塊、 超出頁面、字太小,每頁輸出圖片逐張看過);docx/pptx/xlsx/pdf 另查文件屬性(標題、作者留著產生工具預設值)。 可選擇對照客戶最新來信、與上一版比對合約條款(票期、付款、金額)。 支援 .docx / .pptx / .xlsx / .md / .txt / .pdf,Windows/macOS/Linux 都能跑。 **需要使用者給檔案路徑或檔名**,沒給就先問。 當使用者說「check-before」「交付前檢查這份」「幫我自檢 XXX.docx」「這份文件可以交了嗎」 「掃一下這份文件的易讀性」「簡報有沒有疊字」「檢查投影片跑版」時觸發。 只檢查、不改檔;要改由使用者確認後另外做。要寫交...
- 2 stars
- 0 votes
- 0 copies
- 1 view
- Added September 29, 2026
Works with
Security analysis
92/100- Installs packages at runtime which could introduce malicious dependencies
Pro scans all 3 files and shows the line behind each finding
npx -y skills add abs1294/fulin-claude-plugins --skill check-before --agent claude-codeAre you the author of Check Before?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/abs1294-check-before)---
name: check-before
description: >
交付前對「使用者指定的一份文件」做易讀性自檢:跑十一項機械掃描(編號連續、未定義代號與代號先用後定義、術語首次出現沒說明、
交叉引用、重複、異動紀錄用語、樣式一致、表格欄寬、內部推導痕跡、公文式敬稱、目錄頁碼),並擋 AI 工具名稱再加五條人工判斷,
回報要改的地方;pptx/docx/pdf 另做視覺檢查(用 PowerPoint/Word 實際排版,抓疊字、字跑出方塊、
超出頁面、字太小,每頁輸出圖片逐張看過);docx/pptx/xlsx/pdf 另查文件屬性(標題、作者留著產生工具預設值)。
可選擇對照客戶最新來信、與上一版比對合約條款(票期、付款、金額)。
支援 .docx / .pptx / .xlsx / .md / .txt / .pdf,Windows/macOS/Linux 都能跑。
**需要使用者給檔案路徑或檔名**,沒給就先問。
當使用者說「check-before」「交付前檢查這份」「幫我自檢 XXX.docx」「這份文件可以交了嗎」
「掃一下這份文件的易讀性」「簡報有沒有疊字」「檢查投影片跑版」時觸發。
只檢查、不改檔;要改由使用者確認後另外做。要寫交付訊息走 deliver-report,要產確認清單走 to-checklist。
---
# check-before:交付文件自檢
對使用者點名的一份文件,照 `../../references/document-readability.md` 的鐵則做交付前檢查。
判準與 Stop hook(`hooks/doc-readability-gate.js`)是**同一份程式**(`hooks/lib/readability-scan.core.js`),
所以這裡過了,交付時的自動閘也會過。差別:這裡由使用者點名、任何格式(docx/pptx/xlsx/md/txt/pdf)都能查,
且對 docx 多跑三項(重複偵測、內部推導痕跡、Markdown 標題編號)——Stop hook 掃 docx 時不跑這三項,避免交付時多出判不準的提醒。
文件屬性、客戶來信對照、合約條款比對也只在這裡跑,Stop hook 不跑。
其他 subskill 已經把這支腳本接進自己的腳本裡,會自動跑:to-checklist 在 `md_to_pdf.py` 轉檔前、test-report-docx 在 `report_gate.verify_docx()`(閘三)、daily-report 在寄送前置流程(`send_common.prepare_send`)與 MCP 建草稿前(PreToolUse hook `daily-draft-gate.js`)。deliver-report 沒有產檔腳本,由 Stop hook 掃本回合提到或寫過的交付檔(任何位置與格式,含 docx 目錄頁碼)。
## 流程
1. **確定檢查哪一份**:使用者給了路徑或檔名就用;沒給就問「要檢查哪一份檔案?給路徑或檔名都可以」,**不要自己猜最近改過的檔**。
2. **先問兩件可選的附帶資料**(使用者已經給了、或文件顯然用不到就不問):
- 文件裡有「待確認/待客戶確認/TBD」時:「有沒有這個客戶的最新來信要對照?」有的話用 Gmail 工具(`search_threads`→`get_thread`)找出信件串,
把每封的寄件人、日期與內文存成**暫存資料夾裡的純文字檔**,交給 `--thread`。不要存進專案目錄,信件內容是客戶原文。
- 報價單、合約、提案這類有付款與條款的文件:「有沒有上一版要比對條款?」有的話把舊版路徑交給 `--prev`。
- 沒有就照樣跑:docx/pptx/xlsx/pdf 腳本會把這兩項列在「這次沒檢查到的」;md/txt 腳本不列,回報時自己寫進「這次沒檢查到的」。
3. **跑機械掃描+視覺檢查**:
```
node "${CLAUDE_PLUGIN_ROOT}/skills/check-before/scripts/check_doc.js" "<路徑或檔名>" --visual [--thread <信件串.txt>] [--prev <上一版>]
```
- 只給檔名時,腳本從目前目錄往下找(最多 6 層);檔名可省略副檔名。
- `--visual` 讓 docx/pdf 也跑視覺檢查(pptx 不加也會跑);md/txt 沒有版面,不跑。
- **exit 2**=找不到、有多份同名候選、讀不到內容,或**要跑視覺檢查卻沒有排版軟體**。把腳本訊息原樣給使用者,不可回報「通過」。
- 本機沒有 Python(或 pdf 缺 pypdf、視覺檢查缺 PyMuPDF/Pillow)**不是 exit 2**:xlsx/pdf 的內容、各格式的文件屬性、視覺檢查跑不了,腳本把它們列進「這次沒檢查到的」並附安裝方式,內容沒讀時硬缺陷那行寫「0 項——但文件內容沒有讀取」、--thread/--prev 也不比對;--json 的 pass 為 false。回報時照列、轉告使用者要裝什麼,不可說已通過。
- **exit 1**=有硬缺陷;**exit 0**=硬缺陷 0(可能仍有提醒)。
- 以「視覺」開頭的項目來自視覺檢查,見下方「視覺檢查」一節;「文件屬性」「客戶來信對照」「合約條款」見「文件屬性、來信對照、條款比對」一節。
4. **逐張看每頁畫面**(有跑視覺檢查時):腳本最後列出每頁的 PNG(問題處有紅框)。**每一張都用 Read 打開**,
在回報裡逐頁寫一句看到什麼:有沒有疊字、被切掉、空白、字擠成一團。
- 機器只判得準「字形互相壓到」;SmartArt、圖片裡的字、文字轉外框、字壓在圖案上,只有看圖才抓得到。
- 總覽圖 `overview.png` 只當索引,縮圖看不出細微疊字,不能代替逐張看。
- **Stop hook(`hooks/visual-view-gate.js`)會檢查**:清單上的每一張都要在清單印出後被 Read 過(讀取失敗的不算),漏看就擋下收尾。
圖檔已被刪掉的不要求;同一回合連擋 3 次都沒有進展會放行並提醒,這時回報必須列出哪幾頁沒看、屬未驗證。
5. **人工判斷五條**(機器判不了,逐條讀過文件再下判斷,不能跳):
- 鐵則 4/15:**從第一頁讀起,每個代號、術語在第一次出現時就看得懂嗎?** 先確認讀者是誰(PM、客戶主管、工程師),用那個讀者的眼睛讀結論頁與前三頁:「方案 B」「C1」「user_team」這類詞第一次出現時,同一句有沒有講它是什麼。腳本只抓得到代號形狀與英文術語形狀;中文行話(「聚合」「呼叫點」「去識別化」)只能靠這一條。
- 鐵則 1:讀者是否要兩邊對照才能做完一件事?
- 鐵則 2:同一件事的資訊是否散在正文與備註兩處?
- 鐵則 6:有沒有「待確認」其實我方自己查得到?
- 鐵則 10:有沒有機械性步驟該給腳本、卻叫對方手動做?
6. **逐條判斷腳本的「提醒」**:重複內容、推導痕跡、敬稱、代號先用後定義(鐵則4)、術語首次出現沒說明(鐵則15)都是判不準的項目——搜到不等於要改。代號先用後定義要對照第 5 步的人工判斷逐條看:機器沒認出的定義寫法很多,列出來不等於有問題,但「方案 B 第 2 頁首次出現、第 18 頁才定義」這種就是真問題。鐵則15 列出的數量本身是訊號:給決策者的文件列出幾十上百個,就是整份寫給工程師看的,要回頭改寫前幾頁。每條講清楚「要改/不用改,因為…」。
- **客戶來信對照**:腳本只列出每條待確認與信件串最新日期。逐條讀信判斷「這條信裡答了沒」,答了就列進要改的,附出處(信件日期、寄件人)與一句摘要——**不要把信件內文整段貼進回報**。
- **合約條款**:「舊版有、新版找不到」逐條問使用者是不是刻意刪除;「數字變動」確認新值是有意調整。不自己判對錯。
腳本報的硬缺陷也要先確認**是文件錯還是檢查器錯**(檢查器會過時,踩過)。
7. **回報**,照這個結構:
- 檔案、格式、段落數
- **要改的**:每項附位置(章節或原句片段)與建議改法
- **看過不用改的**:提醒項為什麼放行
- **每頁畫面**:逐頁一句看到什麼(視覺檢查有跑時)
- **這次沒檢查到的**:腳本「□ 這次沒檢查到的」段落列的每一項照列(沒給 --thread/--prev),提醒裡的「文件屬性未檢查」也列進來;md/pdf 不跑樣式一致與表格欄寬(沒有字級、欄寬資訊),請使用者目視或改用 docx 檢查;pdf 若是掃描圖檔沒有文字層,腳本會 exit 2;
視覺檢查用的不是對方實際的軟體時(Keynote、LibreOffice),要明講版面問題都只是提醒、需在 PowerPoint/Word 確認
- 兩份以上文件一起交付時,加做**跨文件一致性**:步驟數、項數、數字宣稱值兩份要一致
8. **不改檔**。使用者說要改再改,改完**同一類問題全文重掃**,再跑一次本腳本確認歸零。
## 文件屬性、來信對照、條款比對
| 項目 | 適用 | 判準 | 等級 |
|------|------|------|------|
| 產生工具預設值 | docx/pptx/xlsx/pdf | 欄位+值成對比對 `references/banned-patterns.json` 的 `generator_defaults`(PptxGenJS、python-pptx、python-docx、openpyxl 的預設標題、作者、描述、公司)。同一個值在別的欄位不算——Steve Canny 只有在「最後修改者」才是 python-pptx 的預設 | 硬缺陷 |
| AI 工具名稱、憑證、個資 | 同上 | 與內文同一套規則,掃每個屬性欄位 | 硬缺陷 |
| 沒有標題、標題與檔名看不出關聯 | 同上 | 中文標題配英文檔名不比;判不準 | 提醒 |
| 客戶來信對照 | 任何格式,給 `--thread` | 列出每條待確認(第幾段+原句)與信件串最新日期;「已答覆」是語意判斷,由人逐條判讀 | 提醒 |
| 合約條款比對 | 任何格式,給 `--prev` | 票期、付款、驗收、保固、報價有效期、稅別、金額、交期、違約九類:舊版有新版沒有、或該類句子裡的數字變了 | 提醒 |
| 隱藏工作表、儲存格註解 | xlsx | 隱藏(含深度隱藏)工作表列名稱;註解內容和工作表內容一起掃 | 提醒 |
- md/txt 沒有文件屬性,腳本表頭會註明「不適用」,回報照寫,不算沒檢查。
- PDF 的屬性從來源檔帶過來:PptxGenJS 產的簡報轉成 PDF,標題、作者、主旨照樣是 PptxGenJS 預設值。Chrome 列印的 PDF(to-checklist 的產出)Creator 是 HeadlessChrome、Producer 是 Skia/PDF,這是正常值,不擋。
- 改屬性:Word/PowerPoint/Excel 在「檔案 → 資訊 → 內容」;python-docx 用 `doc.core_properties`,python-pptx 用 `prs.core_properties`,PptxGenJS 設 `pptx.title/subject/author/company`(只設 title 的話 subject 仍是預設值)。
- 「這次沒檢查到的」只在 docx/pptx/xlsx/pdf 列(沒給 `--thread` 且文件有待確認、沒給 `--prev`)。md/txt 不列:日報寄送、確認清單轉檔也呼叫這支並照印輸出,印出「不算通過」會和放行結果矛盾。
- 文件屬性讀不到(壞掉的屬性檔、同一欄位出現兩次、本機沒有 Python、PDF 沒有 pypdf)記成提醒「文件屬性未檢查(此項屬未驗證)」,不 exit 2;缺 Python/pypdf 時提醒裡附安裝方式。Python 本身沒跑成(逾時、異常結束、查不出套件裝了沒)不算這種,是 exit 2。
- xlsx 一列接成一行(儲存格之間用全形空白),條款字眼與同列的金額數值才比對得到;資料格的 V2、S3、#4 這類代碼在 xlsx 降為提醒,不當成未定義代號擋下。
- 條款數字比對會去掉句首項次編號(1.、(2)),用出現次數比;同一類條款的數字在不同句子間互換,比不出來。
## 視覺檢查(`scripts/visual_check.py`)
**先排版、再判定**。排版交給對方實際會用的軟體,換行、字型替換、自動縮小文字才會跟對方看到的一樣:
| 檔案 | Windows | macOS | Linux |
|------|---------|-------|-------|
| pptx | PowerPoint → LibreOffice | PowerPoint → Keynote → LibreOffice | LibreOffice |
| docx | Word → LibreOffice | Word → LibreOffice | LibreOffice |
| pdf | 不必排版 | 不必排版 | 不必排版 |
前一個失敗(沒裝、開檔失敗、逾時)就換下一個,原因記在提醒裡;全都沒有 → exit 2(視覺未驗證)。
本機沒有 Python 或缺 PyMuPDF/Pillow 不算這種:視覺檢查列進「這次沒檢查到的」並附安裝方式,不 exit 2。
Keynote 與 LibreOffice 不是對方實際的軟體:字寬不同,換行位置跟著不同(實測兩份真實簡報,PowerPoint 0 處疊字、LibreOffice 各多 6~7 處,都是標題最後一個字被擠到下一行)。
所以用它們排版時,疊字、字跑出方塊、超出頁面**一律降為提醒**,標「PowerPoint 可能正常,請在 PowerPoint 確認」,紅框照畫、圖照樣逐張看;「溢出時縮小文字」改從檔案記錄的縮小比例推算 PowerPoint 會顯示的字級。
只關掉檢查器自己開的 PowerPoint/Word——使用者本來就開著的不會被關。
macOS 第一次跑會跳「允許終端機控制 PowerPoint/Keynote」,要有人按允許(系統設定 → 隱私權與安全性 → 自動化)。
判定只有一份,讀排版後每個字實際畫出來的位置:
| 項目 | 判準 | 等級 |
|------|------|------|
| 疊字 | 兩行字形互相壓到,面積超過較小那行的 5%;同一段字疊兩層(重複貼上)也算 | 硬缺陷 |
| 字跑出方塊外 | pptx 有底色或框線的方塊,裡面的字畫到方塊外(看不見的文字方塊不算,撞到別的字時由疊字抓) | 硬缺陷 |
| 超出頁面 | 字畫在頁面外;pptx 有字卻沒出現在畫面上(被裁掉、表格撐出投影片) | 硬缺陷 |
| 字太小 | 實際字級小於 10pt(含「溢出時縮小文字」縮出來的);頁首頁尾這種每頁都有的合併成一條 | 提醒 |
| 文字壓在圖上 | 文字和圖片重疊,整頁背景圖不算(pptx 看真正的圖片物件,方塊的陰影漸層不算) | 提醒 |
| 字型沒內嵌 | pptx 指定的字型沒內嵌,對方電腦沒有就會被替換、換行跟著變(Arial、Calibri 等 Windows 與 Mac 都有的不列) | 提醒 |
| 空白頁、重複頁 | 整頁同一顏色;兩頁畫面完全相同 | 提醒 |
輸出在系統暫存資料夾的 `deliver-report-visual/<檔名>-<時間>/`:`page-NNN.png`、`overview.png`、`rendered.pdf`、`visual-manifest.json`。
回歸測試:`python hooks/tests/visual/run_fixtures.py [--engine powerpoint|keynote|libreoffice]`(16 份測試文件,逐份對照預期)。
排版時一律開複本(暫存資料夾、不撞名的檔名),不會動到或關掉使用者正開著的原檔;只關掉、清掉用視窗代號確認是這次開的 PowerPoint/Word;逾時時若還沒拿到視窗代號(卡在啟動或開檔對話框),一律不殺,只在訊息列出可能殘留的程序編號,請使用者確認後手動關。
排版開的是複本,簡報或文件裡用相對路徑連結的外部檔(連結的圖片、OLE 物件)在複本位置找不到,這類內容的畫面可能和原檔不同。
隱藏投影片不會輸出,頁碼以放映時看到的順序為準;張數對不上時「字跑出方塊外」「文字被裁掉」「字被縮小」三項改記未檢查。
## 前置依賴
- Node.js(掃描本體;docx/pptx 用內建 zlib 解壓,不需 PowerShell,各平台都能跑)
- 檢查 docx 的目錄頁碼:Windows 上的 Microsoft Word(唯讀開檔、比對更新目錄前後,不存檔;約 5 秒)。沒有 Word 或非 Windows 時記成提醒「目錄頁碼未檢查(此項屬未驗證)」——腳本不會因此 exit 非 0,回報時要列進「這次沒檢查到的」,不可說目錄已檢查
- 檢查 xlsx 的內容、docx/pptx/xlsx 的文件屬性:Python 3(只用標準庫,不必另裝套件;XML 交給 `hooks/lib/office_xml.py` 解析)。沒有 Python 時不擋,列進「這次沒檢查到的」並附安裝方式
- 檢查 pdf 的文字與文件屬性:Python 3 與 `pypdf`(`pip install pypdf`)
- 視覺檢查:Python 3、`pip install pymupdf pillow`,加上排版軟體(見上表)。缺 Python 或這兩個套件時不擋,列進「這次沒檢查到的」並附安裝方式
## AI 工具名稱怎麼擋(不必逐一加名字)
- **品牌族規則**:`references/banned-patterns.json` 的 `ai_tool_names`,一條規則涵蓋整個系列與未來版號(GPT-任意版號、Llama 加數字、Claude/Codex/Gemini…)。
- **本機自動蒐集**:每次掃描時自動讀取本機已安裝的 Claude Code plugin、marketplace、MCP 伺服器名稱(只收含連字號或數字的,如 `deliver-report`、`openai-codex`),以及描述標為 AI/LLM/agent 的全域 npm 工具(如 `codex`、`openspec`)。以後裝了新的 AI 工具,不用改任何設定就會一起擋。
- 一般工具(Playwright、TypeScript、Figma、資料庫 cursor)不會被擋。命中時會印出原字,照提示改寫或刪除。
Files in this skill
- SKILL.md
- scripts/check_doc.js
- scripts/visual_check.py
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.