把「新增文本錄入必須掛異體字落地替換」寫成常規並機械化把關(S8) - #1278
Merged
Merged
Conversation
第二階段之所以漏掉 19 個 handler,是因為當時沒有任何機制會在漏掉時發出聲音。本次補上規則 與機械化把關,讓繞過掛鉤的新寫入路徑在測試階段就會紅。 規則文件: - `AGENTS.md` 新增 §1.3(與 §1.1/§1.2 並列的資料完整性規則):範圍由欄位型別決定、未知表 fail-closed、預設 lenient、掛鉤必須早於 PK 計算/查重/拼音派生/`resource_id` 組裝、 精確比對必須兩形都探、通知(含 409/422)要掛、不該替換的地方一律不掛。 另補兩個常被忽略的邊界:繼承基底但自己另寫副表/鏡像的 handler、以及沒有 `tableName()` 的 handler 必須顯式傳表名(否則是 runtime fatal)。 - 「提交前最低檢查」補一行。 - `.claude/skills/mutation-api-record-editing.md` 補實作步驟與踩過的坑(掛哪個 hook、順序 為什麼是硬性要求、通知怎麼接、測試該斷言哪 8 件事含鑑別力)。 - `.claude/skills/database-schema.md` 補交叉引用:新增文本欄自動進入範圍;新增對照/映射表 必須加進排除清單。 機械化把關 `tests/Unit/VariantReplaceHookCoverageTest.php`(10 支測試): - `app/Services/Mutations` 下**每一個** handler 都必須掛(或繼承)替換 trait,或列在例外 清冊。刻意不先判斷「有沒有寫入」——現存 8 個非基底 handler 裡有 4 個把寫入委派給 repository/service,自己檔案裡沒有任何寫入慣用法,以「有寫入才要求登記」為前提會 fail-open。 - 三本清冊各有機械檢查:`EXEMPT`(要寫理由)、`EXEMPT_DELEGATES`(指名下層檔案**與掛鉤數**)、 `SUBCLASS_EXTRA_WRITES`(繼承基底但自己另有寫入)。已掛 trait 的類別不可列進前兩本 (殭屍豁免會讓它從此不受檢查)。 - 基底不只要 `use`,還要**真的呼叫** `applyVariantReplacement()`/`resetVariantReplaced()`/ `withVariantNotices()`——刪掉呼叫比刪 `use` 容易得多,後果一樣(21 個子類靜默失去替換)。 - 逐檔記數鎖住 handler 體系之外的 12 個掛鉤點(controller/repository/import service), 掛鉤變少也會紅。 - 比對走 PHP tokenizer 而非正則:註解與字串字面值都不算,且只認 `->method(` 形式, 同名靜態呼叫無法冒充。 - 目錄內非 handler 檔案若自己落庫也要交代(這條當場抓出 `Concerns/RecordsAiFillSubmission` 寫 `ai_fill_logs`,屬紀錄類表、確認不替換後登記)。 - 偵測邊界誠實寫在 docblock 與 AGENTS.md:目錄外新開檔案、以及委派給下層方法的鏡像同步 偵測不到,靠 review 與人工判斷。 鑑別力已逐項實測會紅:中和基底呼叫、拿掉下層掛鉤、掛鉤數減少、用字串字面值冒充掛鉤、 用同名靜態呼叫冒充、新增未登記的 handler、把寫入搬進目錄內的 helper、殭屍豁免、 未登記的子類額外寫入。 順帶修正 `AppliesVariantReplacement` 的 docblock:顯式傳表名的是四個 handler,不是三個。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
這是什麼
docs/CHAR_VARIANT_MAP_TEXT_COLUMN_ROLLOUT_PLAN.md的 S8:把「新增文本錄入必須掛落地替換」寫成常規,並補上會在漏掉時發出聲音的機械化把關。沒有行為改動:只有規則文件、skill、一支新測試,加一處 docblock 修正。
為什麼需要
第二階段之所以漏掉 19 個 handler,正是因為當時沒有任何機制會在漏掉時發出聲音。本階段價值的一半在「以後不會再漏」。
內容
規則
AGENTS.md新增 §1.3,與 §1.1(外鍵 RESTRICT)/§1.2(稽核欄)並列為資料完整性規則。含兩個常被忽略的邊界:繼承基底但自己另寫副表/鏡像的 handler、沒有tableName()的 handler 必須顯式傳表名(省略是 runtime fatal 而非靜態錯誤)。.claude/skills/mutation-api-record-editing.md:掛哪個 hook、順序為什麼是硬性要求、通知怎麼接、測試該斷言哪 8 件事(含鑑別力)。.claude/skills/database-schema.md:新增文本欄自動進入範圍;新增對照/映射表必須加進排除清單。機械化把關
tests/Unit/VariantReplaceHookCoverageTest.php(10 支測試)EXEMPT(要寫理由)、EXEMPT_DELEGATES(指名下層檔案與掛鉤數)、SUBCLASS_EXTRA_WRITES。已掛 trait 的類別不可列進前兩本(殭屍豁免會讓它從此不受檢查)。use,還要真的呼叫三個 trait 方法。->method(,同名靜態呼叫無法冒充。Concerns/RecordsAiFillSubmission寫ai_fill_logs(紀錄類表,確認不替換後登記)。驗證
php-cs-fixerclean(0 of 675)。🤖 Generated with Claude Code