wiki-lint 是做什麼的?
首次執行前,請先閱讀工具包中的
docs/GOTCHAS.md(已知的誤報與操作注意事項)。
一個維基(wiki.config.json 中的 wiki_root)的唯讀健康掃描,加上三個修復工具。所有程式皆使用 Python 標準函式庫,並在 Windows、macOS 與 Linux 上以相同方式運作。每條維基專屬規則(資料夾、狀態分類、欄位對應、豁免、動詞列表、佔位符模式、閾值)都儲存在設定中,因此當維基新增欄位、資料夾或檢查時,邏輯無需變更。設計目標是在超過 3,000 則筆記時仍能保持快速(完整執行只需數秒,但檢查 13 在該規模下約需半分鐘)。
相關技能
wiki-ingest,wiki-ingest-book:撰寫此技能檢查的筆記(共用相同的設定來決定狀態與索引路由)。wiki-synthesize:檢查 15 產生其工作清單;檢查 32 稽核其封章。vocabulary-update:檢查 30 的修復方法。
佈局
skills/wiki-lint/
SKILL.md
scripts/
lint.py # 執行檢查(--only, --out-dir, --self-test)
fix.py # 修復工具:索引提案、檢查 12 反向連結、提升草稿
references/
check-origins.md # 每項檢查存在的原因(單一權威)
cli-reference.md # 標誌、設定鍵、輸出檔案、報告格式
wikikit/lint/ # 實作:context.py, checks_*.py, fixes.py, defaults.json
tests/fixtures/lint/ # 合成迷你維基,涵蓋每項檢查 + expected_counters.txt
各類事實的存放位置(切勿在這些位置重複):references/check-origins.md = 檢查為何存在;此檔案 = 它做什麼;wikikit/lint/checks_*.py = 它如何實作;tests/fixtures/lint/expected_counters.txt = 為何固定數值就是那個值。在實際執行結束時,工具會為每個觸發的檢查印出 check-origins.md 的指標,因此當您判斷結果是真是假時,動機資訊就會呈現。
工程不變量(請勿破壞)
- 所有檔案 I/O 都透過
wikikit.textio(位元組層級 UTF-8,無 BOM,永不轉換換行符號)。切勿使用預設換行處理的文字模式open():讀取並重新寫入 CRLF 檔案會默默將其轉換。 - 切勿對可能包含 CRLF 的文字使用帶有
$的多行正規表達式:$位於 CR 與 LF 之間,會拆散這對組合。應按行編輯(frontmatter.set_key,fixes._insert_backlinks)。 - 設定是唯一的真相來源。 當維基新增欄位、資料夾、狀態或豁免時,請編輯
wiki.config.json(lint區段),而非程式碼。預設值位於wikikit/lint/defaults.json。 - 草稿豁免是統一的。
lint.stub_exempt_checks列出會跳過status: stub筆記的檢查編號;請從設定中讀取該列表,切勿在文字中重述。檢查 10 和 11 會內聯排除草稿(檔案系統計數)。 - 佔位符偵測以未解析為條件。 在筆記庫索引中已解析的維基連結目標永遠不會被標記為佔位符,即使其名稱符合模式;合法的全大寫縮寫筆記不得觸發標記。
- 在發佈邏輯變更前先進行自我測試。 對檢查的任何修改(新增檢查、變更閾值、重構啟發式方法)都必須通過測試:
python skills/wiki-lint/scripts/lint.py --self-test。當變更是刻意的時,請同時更新tests/fixtures/lint/和expected_counters.txt。證明固定數值具有區辨力:還原邏輯變更,重新執行,並確認計數器發生變化。一個在變更前後都通過的固定數值無法保證任何保護。 - 零是檢測器的測量結果,而非維基的測量結果。 在信任新檢查的零結果之前,請注入一個陽性案例並確認其觸發。
- 警告標記所有權是位置性的,絕非正規表達式鏈結(檢查 22)。 維基可能同時使用
[[Paper]]⚠和⚠[[Paper]]。一個圖形的擁有者是:如果左側修剪後文字以]]結尾,則為其左側的連結;否則為其右側的連結;與任何連結相鄰的圖形是散文式警告。請勿使用兩個鏈結的正規表達式來解決此問題(第二個表達式會吃掉相鄰連結的標記,並默默解除對未驗證來源的標記)。對標記進行任何批量編輯都需要在事前和事後對每個引用鍵進行普查。
檢查如何運作
| # | 名稱 | 標記內容 | 豁免 |
|---|---|---|---|
| 1 | 孤立概念 | 沒有任何論文/書籍的反向連結(內聯連結或 concepts_touched)且無任何同級概念的反向連結(內聯或 related_concepts);同級條款可防止綜合樞紐誤報 | 草稿 |
| 2 | 孤立方法 | 沒有任何論文/書籍的反向連結,且無指向任何論文/書籍的對外連結 | 草稿 |
| 3 | 空的 concepts_touched | 欄位為 null、空值或 [] 的論文筆記(也是批量匯入中 frontmatter 損壞的預警) | 草稿 |
| 4 | 無來源的主張 | 概念筆記中至少 unsourced_threshold 行包含主張動詞(verb_list),且在 +/-unsourced_radius 行內無維基連結,也無位於維基連結標題下的行 | 草稿 |
| 5 | 損壞/佔位符維基連結 | 目標不在整個筆記庫索引中(broken),或符合 placeholder_wikilink_patterns 且未解析(placeholder),或為空([[]],empty-target) | link_target_ignore_patterns(Bases 嵌入) |
| 6 | 草稿 | promote:引用至少 min_distinct_sources_for_final 個不同來源作品的草稿(一本書及其章節算一個作品)。stale:低於該門檻且超過 stale_days 的草稿,或無日期的草稿 | 無 |
| 7 | 索引覆蓋率 | 基本名稱不在 index.md 中的維基連結內的筆記 | 草稿;當 index_mode 為 bases 時跳過 |
| 7b | 索引區段錯置 | - [[X]] 位於錯誤的 ## 區段(index_sections)下 | 在 bases 模式下跳過 |
| 8 | 書籍 chapters_ingested 同步 | 宣告的集合與磁碟上的 {book}_ChNN.md 檔案不同 | 草稿章節 |
| 9 | 章節缺少 book: | *_ChNN 筆記的 book: 連結缺失或無法解析 | 無 |
| 10 | Quick Stats 漂移 | ## Quick Stats 中宣告的計數與對應資料夾的實際檔案計數不同(quick_stats_labels) | 無 |
| 11 | 依領域的覆蓋率漂移 | ## Coverage by Field 的 Concepts/Methods 欄與實際非草稿計數不同(領域列依據 field:,-> 子領域列依據 subfield:,以 [[MOC_*]] 連結為鍵;有筆記但無對應列的子領域為 MISSING-ROW) | 草稿;無領域的筆記為 INFO |
| 12 | 雙向 concepts_touched | paper -> concepts_touched[token] 的目標缺少 [[paper]] 反向連結(asymmetry,可自動修復)或解析後無筆記(missing_target,需處理 token) | 無 |
| 13 | 無連結的別名 | 在其他概念/方法的散文中使用了已記錄的別名(獨特縮寫或多詞短語),但未提供指向其規範筆記的連結。INFO | 草稿;alias_link_stoplist;不搜尋區塊引用 |
| 14 | 語言雷達 | 使用非維基語言的標題(H2-H6),或散文中至少 prose_threshold 個停用詞命中。僅報告;除非 language_radar.enabled 否則停用 | 草稿 |
| 15 | 綜合雷達 | 針對 final 概念/方法:missing = 符合知識現狀區塊資格但尚無區塊;stale = 區塊早於其引用作品的最新 last_verified | 非 final |
| 16 | 狀態詞彙 | status 不在 status_by_type[type] 中,缺少 status 或 type,或模板遺漏(draft | final) | 無 |
| 17 | 無 source_verification | 沒有封章的論文;以 abstract 開頭的值不是封章。INFO 待辦事項 | 草稿 |
| 18 | 已验证但不完整 | 已密封但缺少 volume 或 pages,且無註明日期的 check18_exempt: "YYYY-MM-DD, reason" 的論文;會議論文和學位論文按其類型和格式豁免 | 草稿 |
| 19 | evidence_level 超出詞彙範圍 | 值不在 evidence_level_vocab 中(僅限論文) | 無 |
| 20 | 實用引用 ]] | ## Useful Quotes 下的區塊引用含有洩漏的 ]] | 無 |
| 21 | 全文前群組 | 日期早於 synthesis.prefulltext_cutoff 且無全文級別封章的論文。INFO | 草稿 |
| 22 | 過時的全文前標記 | ⚠ 的擁有維基連結是已具有全文封章的論文,在三次尾部豁免(散文式備註、斜體日期註釋、(N src 信心)之後。有實際誤報 | 無 |
| 23 | 未填寫的主張佔位符 | 符合 unfilled_claim_patterns 的行(命名了來源但未撰寫主張) | 無 |
| 24 | 已棄用的 Frontmatter 鍵 | 鍵在 deprecated_frontmatter_keys 中(預設 journal 改為 venue);精確比對,因此無誤報 | 無 |
| 25 | 未引用的數字 | 統計數字(numeric_claim_patterns)在半徑內無維基連結,分類為 cited / block / methods / domain。INFO。無任何豁免 | 草稿;跳過區塊引用 |
| 26 | 表格欄位不一致 | 表格中行數與分隔行數不同的列(唯一的結構檢查) | 無 |
| 27 | 亂碼 | 透過 encode('cp1252').decode('utf-8') 往返後變成不同字串的行 | 無 |
| 28 | 無 last_verified 的封章 | 帶有 source_verification 但無 last_verified 的論文/書籍(對檢查 15 的 stale 不可見)。INFO | 無 |
| 29 | 超出筆記庫的 Slug 連結 | 指向位於 memory_slug_prefixes 中 slug 的維基連結,範圍為整個筆記庫。除非列表非空,否則停用 | memory_slug_exempt_files |
| 30 | 詞彙同步 | _VOCABULARY.md 缺少活躍概念/方法(missing)或包含已刪除筆記的行(ghost)。INFO;修復方法 /vocabulary-update | 無 |
| 31 | 無文字的封章 | 最多 60 個字元的封章,在任何管道中均無描述性驗證文字。INFO | 無 |
| 32 | 無封章的配對 | (筆記, 其知識現狀區塊中引用的作品) 配對,其來源筆記封章未提及該筆記。封鎖性;在 seal_debt_file 中宣告的債務會報告但不計入 | 已宣告的債務 |
| 33 | 無標題或發表場所 | 帶有空白 title 或 venue 的論文 | 草稿 |
調用
從筆記庫(向上找到最近的 wiki.config.json 即為設定):
python skills/wiki-lint/scripts/lint.py # 所有檢查;列表輸出至 _temp/
python skills/wiki-lint/scripts/lint.py --only 5,12 # 選定檢查
python skills/wiki-lint/scripts/lint.py --self-test # 固定數值 vs expected_counters.txt
python skills/wiki-lint/scripts/fix.py check12 --dry-run
python skills/wiki-lint/scripts/fix.py promote _temp/promote_batch.txt
python skills/wiki-lint/scripts/fix.py index # 需要 index_mode "manual" 且先前已執行 lint
標誌、設定鍵以及每個檢查寫入的檔案:references/cli-reference.md。
何時編輯什麼
- 新的維基資料夾(例如
datasets/):將其加入wiki.config.json的folders中。必須在建立筆記之前註冊,否則指向它的每個連結都會顯示為損壞。 - 新的狀態值:將其加入
lint.status_by_type.{type}。新的筆記類型:加入該類型及其允許的狀態。 - 概念/方法的新欄位:將 slug 加入
field_titlecase_map。 - 調整檢查 4:
lint.verb_list。放寬/收緊其容差:lint.defaults.unsourced_radius。 - 新的佔位符模式:
lint.placeholder_wikilink_patterns(記住它僅適用於未解析的目標)。 - 某個檢查應跳過草稿:將其編號加入
lint.stub_exempt_checks。 - 開啟語言雷達:將
examples/languages/es.json(或自行撰寫列表)複製到lint.language_radar。 - 新增檢查:在
wikikit/lint/checks_*.py中實作,將其計數器加入expected_counters.txt,加入一個可供練習的固定數值,在references/check-origins.md中撰寫其條目。動機未記錄的檢查在首次看起來有雜訊時就會被停用。如果無法找到動機,請寫「not documented」;切勿憑空發明。
安全規則
- lint 對維基是唯讀的;它只會將每個檢查的列表寫入
--out-dir(預設為_temp/)。 fix.py僅在其報告的內容處(反向連結、狀態)修改筆記,保留每個檔案的換行符號,並記錄每次變更以供回滾。- 若不確定啟發式變更是否正確,請先撰寫固定數值,觀察自我測試失敗,然後再進行變更。
- 快取目錄永遠不進行版本控制(
_temp/及類似目錄保留在.gitignore中)。版本化的測量結果會在數月後被讀取,仿佛它是今天的結果。