Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 5 additions & 227 deletions .claude/rules/mcp-cli-parity.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions .claude/rules/measurement-commands-self-prove.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
從 [`zero-instance-guards`](zero-instance-guards.md) 的量測段抽出來的通則(#711,使用者 2026-10-05 裁決:規則檔裡本身是通則的段落抽成獨立的小規則)。
那份表有幾十條「重跑指令」,原本各自寫「同第 13 列的自證」,而那個「自證」的寫法與理由只住在第 13 列與第 19 列的量測段裡(現在都在量測文件)。

適用於**零實例裁決表的量測**——規則檔與 [`docs/zero-instance-measurements.md`](../../docs/zero-instance-measurements.md)(量測文件)裡給人重跑的指令;
`zero-instance-rows-audit` 兩份都掃。其他地方(changelog、issue comment、別的規則檔)寫給人照抄重跑的量測,用同一個寫法——守衛不掃那裡
適用於**零實例裁決表的量測**——規則檔、裁決表 [`docs/rulings/zero-instance-guards.md`](../../docs/rulings/zero-instance-guards.md)(2026-10-15 從規則檔搬出)與 [`docs/zero-instance-measurements.md`](../../docs/zero-instance-measurements.md)(量測文件)裡給人重跑的指令;
`zero-instance-rows-audit` 三份都掃。其他地方(changelog、issue comment、別的規則檔)寫給人照抄重跑的量測,用同一個寫法——守衛不掃那裡
(2026-10-09 #711 b37:`.claude/rules/` 底下別的規則檔裡數 binary 輸出的量測只有 `identity-is-judged-not-matched` 一條,已改成這個寫法)。

## 規則
Expand Down Expand Up @@ -35,16 +35,16 @@

**第 2、3 條的既有違反**(#711 b37,b36 verify 第 5 列;逐列列名、只減不增,改到那一段時順手修,新腳本不得照抄):量測文件裡第 13、23 列
的行級 grep 數 store(第 2 條);第 18、41、64、77 列的腳本對讀不到的檔或 index 列靜默略過(第 3 條,第 24 列的量測段記過第 18 列)。
4. **每個數字旁寫日期與條件**(`# 2026-09-29:…`):數字會過期,寫出條件,重跑的人才知道比的是什麼。`measured-numbers-audit` 對規則檔與量測文件裡
4. **每個數字旁寫日期與條件**(`# 2026-09-29:…`):數字會過期,寫出條件,重跑的人才知道比的是什麼。`measured-numbers-audit` 對規則檔、裁決表與量測文件裡
的「實測 N」要求時間錨或可重跑的指令。
5. **新增合模板的量測之後,把量測文件的棘輪下限調高**(`<!-- zero-instance-rows-audit 棘輪:… -->`):它記依閘去重後至少幾條,少於下限守衛就紅。

## 守衛與它管不到的

`zero-instance-rows-audit` 掃規則檔與量測文件:提到 binary 又有計數的單位就是一條量測,不合模板即紅、具名那一行;量測文件裡一條都掃不到也紅;
`zero-instance-rows-audit` 掃規則檔、裁決表與量測文件:提到 binary 又有計數的單位就是一條量測,不合模板即紅、具名那一行;量測文件裡一條都掃不到也紅;
合模板的量測依閘去重後少於棘輪下限也紅。負控是 `audit-guards-mutations` 裡 `zi-rows:` 開頭的格子。

這兩份檔 PR 改得到,所以守衛的判讀是線性的,另有三道上限:每份檔 4 MiB、單一 fence 或段落 1,500 行與 128 KiB、依閘去重 500 條——
這三份檔 PR 改得到,所以守衛的判讀是線性的,另有三道上限:每份檔 4 MiB、單一 fence 或段落 1,500 行與 128 KiB、依閘去重 500 條——
超過即具名紅、不判讀那一塊(#711 b37)。接近上限時先問那份檔是不是該拆。

**認不出來、所以不紅的寫法是開放的**:binary 的輸出先存進變數或檔案、在另一個單位計數;以別名、複本或名字不以 akashic 開頭的變數執行 binary;
Expand Down
47 changes: 2 additions & 45 deletions .claude/rules/two-kinds-of-edits.md

Large diffs are not rendered by default.

271 changes: 6 additions & 265 deletions .claude/rules/zero-instance-guards.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions .githooks/protected-ratchet.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ Sources/akashic-mcp/Server.swift
Sources/akashic/CLI.swift
Sources/akashic/CreateEntryCommand.swift
Sources/akashic/WriteGateRulings.swift
docs/rulings/mcp-cli-parity.md
docs/rulings/two-kinds-of-edits.md
docs/rulings/zero-instance-guards.md
docs/zero-instance-measurements.md
mcpb/manifest.json
plugin/.claude-plugin/plugin.json
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/census-parity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ on:
- ".claude/rules/**"
# 零實例裁決表的量測與歷輪補記(#711):zero-instance-rows-audit 與 measured-numbers-audit 讀它。
- "docs/zero-instance-measurements.md"
# 三份規則的裁決表(2026-10-15 從 .claude/rules 搬出、不自動載入):zero-instance-rows-audit、
# parity-table-drift、measured-numbers-audit 讀它們,trigger-coverage 以檔名把它們算進讀 .claude/rules 同名檔的守衛。
- "docs/rulings/**"
# parity-table-drift 拿這兩支當真值來源(#407 R50)。
- "Sources/akashic-mcp/Server.swift"
- "Sources/akashic/*.swift"
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Foresay 管**人機確認的格式與迴圈**,本 repo 的規則管**哪些寫
| [no-compat-fallback.md](.claude/rules/no-compat-fallback.md) | 不留相容 fallback——要改格式就一次改完全部;例外須離開 default 位置、附退場量測、退場即刪 |
| [replace-endnote-and-zotero.md](.claude/rules/replace-endnote-and-zotero.md) | 目標是完全取代 EndNote 與 Zotero——檔案住 Akashic、位元組複製進 store、對 Zotero 的 pull 是過渡、能力缺口記 issue 不得靠「回去用 Zotero」帶過 |
| [apa7-is-the-work-floor.md](.claude/rules/apa7-is-the-work-floor.md) | 一筆 work 的資訊下限是「能產出正確的 APA7 參考文獻」——ch10 的 113 例是驗收矩陣、`Entry.type` 的值域須**細分**(非等於)ch10 的 16 節;下限不是上限,分類可更細不可更粗 |
| [zero-instance-guards.md](.claude/rules/zero-instance-guards.md) | 為「還沒發生過的形狀」寫守衛是一列一列裁決出來的——封閉決策表+理由欄同列,刻意不給總括判準(那會在邊界上長出沒人同意的答案);各列的量測腳本與逐輪補記住在不自動載入的 [`docs/zero-instance-measurements.md`](docs/zero-instance-measurements.md),規則檔每一列只留核心(#711)|
| [zero-instance-guards.md](.claude/rules/zero-instance-guards.md) | 為「還沒發生過的形狀」寫守衛是一列一列裁決出來的——封閉決策表+理由欄同列,刻意不給總括判準(那會在邊界上長出沒人同意的答案);各列的量測腳本與逐輪補記住在不自動載入的 [`docs/zero-instance-measurements.md`](docs/zero-instance-measurements.md);裁決表(含每一列的核心)住在同樣不自動載入的 [`docs/rulings/zero-instance-guards.md`](docs/rulings/zero-instance-guards.md)(#711;2026-10-15 搬出)|
| [measurement-commands-self-prove.md](.claude/rules/measurement-commands-self-prove.md) | **數 binary 輸出的量測只有一種寫法**——自證閘(舊 binary 印 `0` 與「檢查過且乾淨」要分得開)、`LC_ALL=C`、必要變數的前置條件寫在整條最前面;讀 store 用 YAML 解析、讀不到的檔要計數、數字旁寫日期與條件;`zero-instance-rows-audit` 掃零實例的規則檔與量測文件(#711 從量測段抽出)|
| [blocked-issues-must-be-scannable.md](.claude/rules/blocked-issues-must-be-scannable.md) | 被阻塞的 issue 必須把「在等什麼」寫在工具掃得到的三個位置之一,不得只寫在散文裡——四次「空等」的實測(#314)+哪些「等」需要標記的封閉裁決表 |
| [two-kinds-of-edits.md](.claude/rules/two-kinds-of-edits.md) | 每個寫入面只能是兩種編輯之一——AI 編輯(判定型、依規則,必留 verdict 且可逆轉)或程式編輯(決定論式,冪等、整批擋、附量測);混合面拆成「提名(程式)→ 判定(AI)→ 落地(程式)」;封閉的歸類表逐列理由(#505) |
Expand Down
20 changes: 14 additions & 6 deletions Sources/AkashicAppKit/AdjudicationViews.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ struct OrphanView: View {
/// 理由草稿:失敗之後重開同一筆還在(不必重打),空理由時破壞性按鈕停用。
@State private var removalDraft = RemovalReasonDraft()

/// 標題的串接拆到 body 之外、三元先定型成 String:寫在 `.navigationTitle(…)` 的引數裡時,CI 對整個 body 報
/// type-check 逾時(unable to type-check this expression in reasonable time)。組出來的字串逐字不變
private var navigationTitleText: String {
let additional: String = (model?.orphanedAdditionalSourceEntries.count ?? 0) > 0
? "+\(model!.orphanedAdditionalSourceEntries.count) 附加來源" : ""
return "Orphans(\(model?.orphans.count ?? 0)" + additional + ")"
}

var body: some View {
Group {
if let model {
Expand Down Expand Up @@ -187,9 +195,7 @@ struct OrphanView: View {
}
}
}
.navigationTitle("Orphans(\(model?.orphans.count ?? 0)"
+ ((model?.orphanedAdditionalSourceEntries.count ?? 0) > 0
? "+\(model!.orphanedAdditionalSourceEntries.count) 附加來源" : "") + ")")
.navigationTitle(navigationTitleText)
.task(id: state.reloadCount) { model = OrphanModel(state: state) }
.confirmationDialog("刪除這筆 entry?檔案會移到垃圾桶(可救回)。",
isPresented: Binding(
Expand Down Expand Up @@ -225,9 +231,11 @@ struct OrphanView: View {
} message: { presented in
switch presented {
case .confirmRemoval(let pending):
Text("將拿掉這幾個在 Zotero 端已刪除的來源:\(pending.sourcesLabel)。" // display-safe-exempt: pending.sourcesLabel 是 `displayOrphanedAdditionalSources` 的消毒投影
+ "主來源與活著的來源不動,書目欄位不動。"
+ "記錄檔要先 commit——移除前的版本只留在 git 裡。理由不寫進 store,請寫進 commit message。")
// `verbatim:` 讓串接直接定型成 String(同上:body 的 type-check 逾時);`+` 的結果本來就是 String、
// 走的就是不翻譯的那個 init,顯示逐字不變
Text(verbatim: "將拿掉這幾個在 Zotero 端已刪除的來源:\(pending.sourcesLabel)。" // display-safe-exempt: pending.sourcesLabel 是 `displayOrphanedAdditionalSources` 的消毒投影
+ "主來源與活著的來源不動,書目欄位不動。"
+ "記錄檔要先 commit——移除前的版本只留在 git 裡。理由不寫進 store,請寫進 commit message。")
case .removed(let report):
Text(report) // display-safe-exempt: 報告在 kit 層逐項消毒
case .failed(let message):
Expand Down
Loading
Loading