Skip to main content

elf-mcp-book

Elf Express 書籍素材(mcpjungle/books/<書名>/source/)與「挑一份上架成 docs-mcp 語料」的規範。 當任務涉及 mcpjungle/books/<書名>/source/ 下的檔案、新增或整理一本書的素材、把某本書的某個語言上架成語料、 寫或修改某本書的 import.ts/transform.ts、 書籍圖片(一般 git、-text -diff)、.gitattributes 的素材規則、語料的 sources.json、168小隊譯文審查, 或排查「書上架後查不到 / CI 擋大檔」時觸發。

معلومات المصدر

المستودع
elf-express/skillshare-source
آخر نشاط في المصدر
١٨ أكتوبر ٢٠٢٦ في ١٤:٤٢
لغة SKILL.md المكتشفة
الصينية
النجوم
٠
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
4 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
elf-mcp-book
description
Elf Express 書籍素材(mcpjungle/books/<書名>/source/)與「挑一份上架成 docs-mcp 語料」的規範。 當任務涉及 mcpjungle/books/<書名>/source/ 下的檔案、新增或整理一本書的素材、把某本書的某個語言上架成語料、 寫或修改某本書的 import.ts/transform.ts、 書籍圖片(一般 git、-text -diff)、.gitattributes 的素材規則、語料的 sources.json、168小隊譯文審查, 或排查「書上架後查不到 / CI 擋大檔」時觸發。
metadata
{"version":"1.1.0","owner":"Elf Express"}
# 書籍素材與語料上架(Elf Express) > 參考實作:`elf-express/mcp-library` 的 `mcpjungle/books/<書名>/source/`(素材區,commit `f05dcb1` 建立、`9465d9d` 搬到現址)、 > `mcpjungle/books/<書名>/{import,transform}.ts`(產生語料)、`mcpjungle/books/<書名>/corpus/`(語料區)、 > 根 `.gitattributes`(圖片與素材政策)。量測基準:`origin/release` @ `73b8206`。 > 核心觀念來自 `.gitattributes:10` 的註解原文:**「書是素材,不是原始碼。放進這裡不代表要上架成語料 —— 上架是另一回事,由人挑哪一種形式。」** 相關 skill: - **`elf-mcp-knowledge`** — 上架流程的主規範(Step 0–7:語料、`corpus.json`、smoke test、註冊、部署、文件同步)。 **本 skill 只管「素材區怎麼放」與「挑哪一份上架」;真的要上架時照它走。** - `elf-mcp-gateway` — 註冊與部署 - `elf-mcp-server` — 語料模式放不下時才寫新 server - 權威目錄規範:repo 的 `mcpjungle/books/README.md`(語料 id、目錄樹、`corpus.json` 欄位、內容規則) --- ## 1. 何時使用 - 新增一本書的素材到 `mcpjungle/books/<書名>/source/`,或整理 / 改名既有的書 - 把某本書的某個語言**上架**成 docs-mcp 語料(挑哪一份、排除哪些) - 寫或修改某本書的 `import.ts`/`transform.ts`(篩選與轉換) - 處理書籍圖片(一般 git、`-text -diff`)、`.gitattributes` 的素材規則 - 產生或修補語料的 `sources.json` - 執行或延續 168小隊的譯文審查 - 排查「素材有、AI 查不到」「CI 擋大檔」 ### 素材區與語料區的分界(先認清這條線) | | 素材區 `mcpjungle/books/<書名>/source/` | 語料區 `mcpjungle/books/<書名>/corpus/<id>/` | |---|---|---| | 目的 | 人閱讀、翻譯、審稿的工作區 | 餵給 MCP 的純文字語料 | | 保留範圍 | **完整**:原文、譯文、雙語對照、回譯、合併全書、圖片 | **只取一種形式**,且只放文字 | | 圖片 | 有,走一般 git(`-text -diff`) | **沒有**,md 內的 `../images/…` 刻意留成失效連結,或由 `transform.ts` 改成官方網址連結(證據 B4) | | 進不進 Docker image / npm 套件 | 不進(`mcpjungle/.dockerignore:7`) | 進 Docker image(所以有容量上限);npm 套件的 `files` 只有 `dist`、`README.md`,不含語料(`docs-mcp-server/package.json:10-13`) | | 誰決定內容 | 擷取工具產出,原樣保留 | **人**決定篩選規則,寫進 `transform.ts` 的 `isIncluded`;`import.ts` 產生、勿手改(`books/README.md:74`) | 現況(`origin/release` @ `73b8206`,實測 2026-10-17)。篇數用 `git -c core.quotepath=false ls-files -- "mcpjungle/books/<書>/source/<語言>" | grep -c '\.md$'` 量, 不受本機被 `.gitignore` 排除的合併檔影響;圖片欄同法量 `\.(png|jpe?g|gif|webp)$`: | 書 | 語言資料夾(md 篇數) | 圖片(png/jpg/gif/webp,一般 git) | 已上架成語料? | |---|---|---|---| | `multica` | `zh-CN` 92、`zh-TW` 92 | 60(png/jpg 1、gif/webp 59) | 否 | | `nginx` | `en` 355、`en+zh-TW` 355 | 22 | 是:`nginx-en` 149 篇 | | `opnsense` | `en` 379、`zh-TW` 379、`en+zh-TW` 378、`en-translated` 379 | 399 + 6 svg | 是:`opnsense-en` / `opnsense-zh-tw` 各 377 篇 | | `portabase` | `en` 110、`en+zh-TW` 110 | 57 | 否 | | `stalwart` | `en` 478、`en+zh-TW` 569 | 105(png/jpg 93、gif/webp 12) | 是:`stalwart-en` 487 篇 | | `fc`、`sqlsugar` | 舊式語料,沒有 `import.ts`(第 3 節「舊式語料」) | 0 | 是:`fc-zh-tw` 133 篇、`sqlsugar-zh-tw` 74 篇 | `books/README.md:36-45` 的現有語料表與實測一致(6 個),見第 7 節待確認 1。 --- ## 2. 固定規則 ### 素材區(`mcpjungle/books/<書名>/source/`) 1. **MUST** 目錄結構 `mcpjungle/books/<書名>/source/<語言>/*.md` + 同層 `mcpjungle/books/<書名>/source/images/`; 書資料夾另有 `import.ts`、`transform.ts`(產生語料)與 `corpus/`(語料區)。 `<書名>` 用小寫、可含 `-`,且**與未來語料 id 的書名部分同一個字串**(`opnsense` → `opnsense-en` / `opnsense-zh-tw`)。 WHY:素材與語料靠這個字串對應;`mcpjungle/books/README.md` 規定 id 為 `<書名>-<語言>`,書名不一致就無法回溯來源; registrar 的 `gen-book-configs.mjs:52` 要求 `corpus.json` 的 `book` 等於書資料夾名,`:53-55` 要求 id 等於 `<book>-<language 小寫>`,或 `<book>-bi`(中英混排,`gen-book-configs.mjs:54-55`)。 現況(`73b8206`):stalwart 的 `source/en/` 不是扁平的,底下是巢狀子目錄(`auth/`、`cluster/`、`email/`…);它的 `isIncluded` 收所有不以 `_` 開頭的 `.md`/`.mdx`(`stalwart/transform.ts:9-12`,`_` 開頭的是 Starlight 片段)。 2. **MUST** 語言資料夾用擷取工具的原樣命名,現況五種:`en`、`zh-TW`、`zh-CN`(原文 / 譯文)、`en+zh-TW`(雙語對照)、`en-translated`(回譯)。 **MUST NOT** 把 `en+zh-TW`、`en-translated` 這類衍生物刪掉或壓成一份。 WHY:`.gitattributes:10-11` 註解明文「素材區保留完整(含 en+zh-TW 雙語對照、en-translated 等衍生物),語料只取其中一種」; `en+zh-TW` 是 168小隊審稿的**輸入**(見規則 16),刪了審查就沒有對照基準。 3. **MUST** 圖片走一般 git,不走 LFS:`.gitattributes` 對 `mcpjungle/books/*/source/**` 的 `png`/`jpg`/`jpeg`/`gif`/`webp` 標 `-text -diff`(`:26-30`);svg 不另設規則。**MUST NOT** 改回 Git LFS。 WHY:mcp-library `21786bc` 推送時 GitHub 回 `This repository exceeded its LFS budget`,配額是帳號層級、repo 內解不了,整個 push 失敗;這批圖單檔都遠小於 GitHub 100 MB 上限,不需要 LFS(`.gitattributes:13-23` 註解原文,證據 B2)。`-text -diff` 讓二進位圖不做換行轉換、diff 不展開。 圖片容量只靠規則 5 的 CI 5 MB 檢查擋,git 設定本身不擋。驗證:`git check-attr text diff -- "mcpjungle/books/<書>/source/images/<檔>.png"` 應回 `text: unset`、`diff: unset`。 4. **MUST** 保留 `mcpjungle/books/*/source/** linguist-vendored`(`.gitattributes:34`)。 WHY:`.gitattributes:32-33` 註解——2600+ 篇書會把這個 repo 標成 Markdown 專案,蓋掉真正的 TypeScript 原始碼;也讓 diff 預設折疊。 5. **MUST** 單一檔案 < 5 MB。CI `basics` 的檢查是 `ci.yml:77` 對**整棵樹**的 `find . -type f -size +5M -not -path "./.git/*" -not -path "*/node_modules/*"`(只排除 `.git/` 與 `node_modules/`), 不是只看變更檔,也**不**排除 `mcpjungle/books/`;不分副檔名,對圖片也有效。 **現況(新書不要再犯)**:4 個超標合併檔都不在版控——`nginx/source/en/000 全書 (nginx.org) en.md` 12 MB、`nginx/source/en+zh-TW/000 全書 (nginx.org) en+zh-TW.md` 16 MB、 `opnsense/source/en+zh-TW/000 全書 (docs.opnsense.org) en+zh-TW.md` 7.3 MB 由 `4554bdf` 移除;`stalwart/source/en+zh-TW/000 全書 (stalw.art) en+zh-TW.md` 從未進版控、由 `920892f` 列名。 四個都靠 `.gitignore:13-20` **逐檔列名**排除,不是通用規則;新書再出現超標檔只有 CI 擋得住。見第 7 節待確認 2。 自查: ```bash # 在 mcp-library repo 根目錄執行(CI 掃的是整棵樹) find . -type f -size +5M -not -path "./.git/*" -not -path "*/node_modules/*" ``` 6. **MUST** 擷取產出的 md 保持與來源一致(YAML front matter、`[⬆ 目錄]` / 上下篇導航行都留著)。 WHY:front matter 的 `source:` 是 `transform.ts` 去引號或產 `sources.json`(規則 9)與日後重新同步的唯一依據。 ### 挑哪一份上架 7. **MUST** 一個語言資料夾 = 一個語料,id = `<書名>-<語言小寫>`(`opnsense/source/zh-TW/` → `opnsense-zh-tw`)。 命名的完整規則(禁底線、禁點、≤ 30 字元、禁泛名、全 gateway 唯一)以 `mcpjungle/books/README.md` 第一節(`:12-34`)為**權威**,不要在這裡另立一套; (`:12-34` 指第一節的命名規則:語言後綴表與規則表;同一節的 `:36-45` 是「現有語料」表,不屬命名規則。) registrar 會實際檢查(`gen-book-configs.mjs:10-11,38-40,53-55`)。 8. **MUST NOT** 上架下列四類,它們只留在素材區: | 不上架 | 原因(權威出處) | |---|---| | `en+zh-TW/`(雙語對照) | `books/README.md:31`(第一節):「不可再放第三份雙語合併版」——同內容存三份、搜三次;要雙語就讓 AI 分別查兩個語料 | | `en-translated/`(回譯) | 衍生物,內容與 `en/` 重複;`.gitattributes` 把它歸在素材區 | | `000 全書 *.md`(合併全書) | `books/README.md:201-202`(第六節):合併檔是重複內容,每次搜尋都多命中一篇超大檔,**一律排除**;也是規則 5 的超標來源 | | `images/` 與任何非文字檔 | `books/README.md:199-200`(第六節):語料只放文字;md 內的 `../images/…` 失效連結可接受,但要在 `corpus.json` 的 `description` 註明 | 由 `transform.ts` 的 `isIncluded` 執行(opnsense `transform.ts:7` 排除 `000 `、nginx `transform.ts:17-19` 只收 `NNN [章節] 標題.md`)。 9. **MUST** 每篇都要抽得到正確的來源網址,結尾不能多帶 `"`,也不能是空值。做法二擇一: ① 新書由 `transform.ts` 把 front matter 的 `source: "…"` 去引號(nginx `transform.ts:67-68`、opnsense `transform.ts:56-59`;stalwart 由 `sourceUrl()` 產生,`transform.ts:22`); ② 舊式語料(fc、sqlsugar),或 `transform.ts` 無法去引號時,用 `templates/make-sources-json.mjs` 產生 `sources.json`。 WHY:`mcpjungle/books/README.md` 第五節(`:183-193`)——自動抽取只掃前 15 行,front matter 帶引號時會把結尾的 `"` 一起吃進網址(`:190`);`sources.json` 優先於自動抽取(`:187`);匯入腳本去引號的例外寫在 `:193`。 驗證:第 3 節的上架前檢查,「來源問題」必須是 0 篇。 10. **MUST** 要不要收目錄頁(`000 目錄.md`)由 `import.ts` 的 `isIncluded` 決定;有收的話,目錄頁同樣要通過規則 9 的來源檢查。 WHY:`books/README.md` 第六節(`:202`)允許保留目錄頁;但它沒有 front matter,開頭是 `# …`+`> 網站:https://…`(證據 B12),收了卻抽不到來源就違反規則 9。 現況(`73b8206`):opnsense `transform.ts:7` 排除 `000 `、nginx `transform.ts:17-19` 只收有章節標籤的檔名,兩本都不收目錄頁。 stalwart 的 `isIncluded`(`stalwart/transform.ts:9-12`)收所有不以 `_` 開頭的 `.md`/`.mdx`,但它的 `source/en/` 是巢狀子目錄、沒有 `000 目錄.md` 這類目錄頁,所以不涉及本條。 11. **MUST** `import.ts` 產出的語料不得有泛名標題:`page`、`index`、`untitled` 或空標題。 標題取法:先取 front matter 的 `title:`,沒有才取第一個 `# ` 標題,去掉頭尾空白,不分大小寫。(`title:` 的值依 YAML 解析,外層引號不算標題的一部分。)重複標題只列出,不算失敗。 WHY:`docs_search`/`docs_outline` 回傳的是檔名與標題,那是 AI 選檔的唯一線索。 驗證:第 3 節的上架前檢查,「泛名標題」必須是 0 篇。舊式語料另有已知的例外,見 evidence。 注意:nginx 的 `source/en` 有 41 篇 `page`,語料裡是 0 篇,靠的是 `transform.ts:6-14` 的章節白名單間接擋下,不是標題檢查(證據 B11)。 12. **MUST** 上架是**人工挑選**的決定,不是把素材區自動同步過去。 WHY:`.gitattributes:10` 註解明文「放進這裡不代表要上架成語料 —— 上架是另一回事,由人挑哪一種形式」。 13. **MUST** 上架動作本身照 **`elf-mcp-knowledge` 第 3 節 Step 1–7** 走完: 素材放進 `source/` → `import.ts` 產生 `corpus/<id>/` → `corpus.json`(`book` / `language` / `source` / `title` / `description` / `capabilities` 六欄)→ 本機驗證 + smoke test + 上架前檢查 → 註冊(見 `elf-mcp-gateway` 第 2 節〈註冊〉)→ 部署 → 驗證 gateway 曝露工具 → 同 PR 更新文件。 **MUST NOT** 手放 md 進 `corpus/` 當作上架,也 **MUST NOT** 手改 `import.ts` 產出的 md(`books/README.md:74`)。fc、sqlsugar 見第 3 節「舊式語料」。 14. **MUST** 顧容量:`books/*/corpus/` 總量上限約 **200 MB**(`books/README.md:204-206`;語料會打包進 `docs-mcp-server` 的 Docker image,每次 clone 都下載)。 目前總量 17 MB(`du -sh --total mcpjungle/books/*/corpus`,`73b8206`:`opnsense-en` 4.6、`opnsense-zh-tw` 4.4、`stalwart-en` 3.8、`nginx-en` 2.2、`fc-zh-tw` 1.0、`sqlsugar-zh-tw` 0.8 MB)。 超過時把大型語料拆到獨立 repo、以 `DOCS_CORPORA_DIR` 掛載,**不要**繼續塞進本 repo。 15. **MUST** 授權與品質如實註明: - 上游要求保留聲明(BSD、MIT…)→ 語料根目錄放 `LICENSE` 全文,並在 `corpus.json` 的 `license` 欄註明。 - 機器翻譯 / 未校稿 → 在 `description` 寫明,並指出以哪個語料為準。範例(`books/README.md:142-144` 的 `opnsense-zh-tw`): 「機器翻譯(google_v2),168 小隊審稿中,術語以 opnsense-en 原文為準」。 - 刻意失效的連結(圖片、被排除的合併檔)→ 一併寫進 `description`。 WHY:`corpus.json` 的 `description` 是 `docs_list_corpora` 唯一會顯示給 AI 的品質說明;不寫=AI 把機翻當權威。 ### 168小隊(譯文審查) 16. **MUST** 譯文審查在**素材區**做;目前只針對 opnsense:在 `mcpjungle/books/opnsense/source` 開工作階段(`168小隊-啟動提示.md:6`), 產出放 `../168小隊/`(即 `mcpjungle/books/opnsense/168小隊/`,`73b8206` 上尚未建立)。 **MUST NOT** 直接改 `corpus/`(`import.ts` 產出,勿手改)。啟動方式見 `mcpjungle/books/opnsense/168小隊-啟動提示.md`: 建 agent team(不是只用子代理)、 隊員 `168-terminologist` ×1、`168-reviewer` ×3(依 `000 目錄.md` 把章節平均切三段、範圍不重疊;共 377 篇,`:13`)、 `168-devils-advocate` ×1、`168-format-checker` ×1,審稿任務依賴「術語表完成」。 WHY:審查的輸入是 `en/` + `zh-TW/` + `en+zh-TW/` 三者對照(規則 2),語料區只有一份、無法對照。 17. **MUST NOT** 在啟動提示裡寫模型,也**MUST NOT** 把 `168-*` agent 改成 `elf-*` 的形狀(預載 skill、改 tools)。 WHY:啟動提示原文(`168小隊-啟動提示.md:7`)——「提示裡不要寫模型,否則會蓋過定義檔中的 model 設定」; skillshare 的 `AGENTS.md` 明文:`168-*` 與 `elf-*` 慣例無關、不預載 skill,**不要**為了一致性去改它們。 --- ## 3. 標準範本 | 檔案 | 用途 | |---|---| | `templates/make-sources-json.mjs` | 舊式語料,或 `transform.ts` 無法去引號時使用(規則 9):從 front matter 的 `source:` 產生 `sources.json`(零依賴、跳過 `examples/` 與 `images/`;已在 opnsense / nginx 素材上實測,證據 B12) | | `templates/corpus-book.json` | 書籍語料的 `corpus.json`(六個必填欄位 + `license`,含機翻 / 失效連結的註明範例) | 素材區與語料區目錄樹: ```text mcpjungle/books/ ├── README.md # 語料命名與目錄結構的唯一權威版本 └── <書名>/ ├── import.ts # 在 mcpjungle/docs-mcp-server 執行 npx tsx ../books/<書名>/import.ts ├── transform.ts # isIncluded(篩選)+轉換,純函式 ├── source/ # 素材區;不進映像(mcpjungle/.dockerignore:7) │ ├── en/ # 原文 → 可產生 <書名>-en │ │ ├── 000 全書 (<來源網域>) en.md # ✗ 不上架(合併檔;超過 5 MB 要逐檔列進 .gitignore) │ │ ├── 000 目錄.md # 收不收由 isIncluded 決定(規則 10) │ │ └── 001 … .md │ ├── zh-TW/ # 譯文 → 可產生 <書名>-zh-tw │ ├── en+zh-TW/ # ✗ 不上架(雙語對照,168小隊審稿用) │ ├── en-translated/ # ✗ 不上架(回譯衍生物) │ └── images/ # ✗ 不上架(一般 git,-text -diff) └── corpus/ └── <書名>-<語言>/ # import.ts 產出的 md 勿手改;corpus.json、LICENSE 手寫 ``` opnsense 另有 `168小隊-啟動提示.md`(譯文審查的啟動提示,貼給新工作階段)、`ONBOARDING.md`,以及審查產出(術語表、報告)的目錄 `168小隊/`(`73b8206` 上尚未建立)。 上架一本書(素材 → 語料),指令照抄: ```bash # 所在目錄:0)、1) 在 mcp-library repo 根目錄;2)–4) 在 mcpjungle/docs-mcp-server;5) 回到 repo 根目錄 # 0) 選 id 並查撞名(規則 7;權威規則見 mcpjungle/books/README.md 第一節) ls mcpjungle/books/*/corpus/ mcpjungle/registry/ docker compose exec mcpjungle /mcpjungle list servers # 以 gateway 執行期清單為準 # 1) 素材放進 mcpjungle/books/<書名>/source/<語言>/,寫 transform.ts(isIncluded 排除規則 8 的四類)與 import.ts # 寫法照 mcpjungle/books/nginx/{import,transform}.ts;來源已是 md 時,import.ts 只做篩選與複製 # 2) 產生語料:全部轉換成功才清掉舊 md 再寫入,任何錯誤都不寫檔 cd mcpjungle/docs-mcp-server npm ci npx tsx ../books/<書名>/import.ts # corpus/<id>/corpus.json(與 LICENSE)手寫;import.ts 只清 md,不會刪它們 # 3) 確認沒有漏進非文字檔與超標檔
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub