一键导入
persistence-check
シリアライズ・on-disk 形式(index.bin / config.toml / history / window.bin 等)の追加・変更時、または計画レビュー時に使用。version バンプ要否・旧形式の後方互換テスト・デコード失敗時のデータ保全を検証する。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
シリアライズ・on-disk 形式(index.bin / config.toml / history / window.bin 等)の追加・変更時、または計画レビュー時に使用。version バンプ要否・旧形式の後方互換テスト・デコード失敗時のデータ保全を検証する。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | persistence-check |
| description | シリアライズ・on-disk 形式(index.bin / config.toml / history / window.bin 等)の追加・変更時、または計画レビュー時に使用。version バンプ要否・旧形式の後方互換テスト・デコード失敗時のデータ保全を検証する。 |
| argument-hint | [対象, 例: 'IndexCache: Cow 統合' / 'HistoryStore: 新フィールド追加' / 'window_data v5 マイグレーション'] |
| allowed-tools | ["Read","Grep","Glob"] |
$ARGUMENTS のシリアライズ/永続化ロジックについて、後方互換とデータ保全の安全性を検証する。 $ARGUMENTS が空の場合は、会話の直近の変更内容から対象を推定する。
実装後のコードレビューだけでなく、workspace/plan.md の計画レビューにも使える。計画段階で「この永続化変更は既存ユーザーのデータを壊さないか?」を検証し、見落としがあれば計画を更新してから実装に進む。
このリポジトリの最頻出の高リスク領域が on-disk 永続化(index.bin / config.toml / history.bin / window.bin)で、#338・#343・#394・#461 が繰り返し噛まれてきた。SSOT は snotra-core/CLAUDE.md「データ永続化の注意」。このスキルはそのルールを機械的に検証する(/cache-check が incremental 単調性を検証するのと同型)。
永続化バグの典型パターン:
match 兄弟分岐の保全方針の不揃い → 1 分岐だけ直しても別分岐に破壊的フォールバックが残る(Config::load 型)$ARGUMENTS から対象の永続化構造を特定し、ソースコードを読む。変更を分類する:
対象: <struct 名 / ファイル>
変更種別:
[ ] フィールド追加/削除/型変更(バイト形式が変わる)
[ ] セマンティクス変更(バイト形式は同一だが値の解釈が変わる)
[ ] シリアライザ切替(bincode↔postcard 等)
[ ] リファクタ(バイト形式不変を主張・例: owned/borrowed struct の Cow 統合)
[ ] 読み込み失敗ハンドリングの変更(load / fallback)
形式が変わる or セマンティクスが変わる → version バンプ必須
- 該当 version 定数(INDEX_CACHE_VERSION / magic+version ヘッダー / 各 struct の version)をバンプしたか
- 旧バージョン用フォールバック構造体(IndexCacheVN / Legacy variant 等)を残したか
- load 経路に「新 → 旧」のフォールバックチェーンを追加したか
バイト形式もセマンティクスも不変(純リファクタ)→ バンプ不要
- ただし「不変」の主張を Step 3 のテストで証明すること
セマンティクス変更の見落としに注意: バイト列フォーマットが同一でも、値の意味が変われば version バンプが要る(#338 の座標系変更が例)。「バイトが同じだからバンプ不要」は誤り。
後方互換は 旧形式を新コードで読めること で証明する。以下を確認する:
[ ] 旧オンディスク形式(凍結バイト列 or 旧 struct でシリアライズした bytes)を入力に、
新コードで deserialize できるテストがあるか
[ ] そのテストは「新形式の往復」とは別に存在するか
(新形式往復だけでは旧形式の読込失敗を検出できず false-green)
Legacy {..} variant 等で必ず受理し apply_migrations() で移行#[serde(default = ...)] を検証するなら、その field が属するセクションを fixture に存在させる: セクションごと省いた TOML は親側の #[serde(default)](例 Config.visual)で struct 丸ごと既定値に落ち、field の属性は一度も実行されない——属性を消してもテストが通る false-green になる。正しい形は「セクションは書く・新キーだけ書かない」。加えて既存キーを 1 つ sentinel として入れ、その値が反映されること(=struct 既定に落ちていないこと)を同じテストで示す(#646 PR2 で PR1 由来の穴として検出)[ ] deserialize 失敗時に空データを即時 save() で上書きしていないか(学習データ喪失・#338)
→ フォールバック読み込みを先に試み、次回の通常 save() で新形式へ昇格
[ ] 読み込み失敗を種類で扱い分けているか(Config::load 型):
- 不在(NotFound)= 既定値を生成・保存
- 内容破損(parse 失敗・InvalidData)= .bak へ退避し既定値・保存しない
- 一時的失敗(権限・ロック)= 退避も上書きもせず既定値・保存しない
[ ] 同じ match の全兄弟分岐で保全方針が揃っているか
(1 分岐だけ直しても別分岐に破壊的フォールバックが残る・#343)
[ ] IndexCache 系: CLAUDE.md「IndexCache バージョン変更チェックリスト」の全項目を満たすか
(struct / version / fallback / load / save / CachedMasks / new_with_cached_masks)
[ ] history 系: CLAUDE.md「history.rs のキー正規化チェックリスト」の3者
(新規記録 / 既存データ移行 / 参照 API)が揃うか
[ ] Config をデシリアライズする新経路を追加した場合、apply_migrations() の適用要否を判断したか
[ ] TOML フィールド移動時、旧フィールドを skip_serializing で残し apply_migrations() で移行したか
以下に対応するテストが存在するか grep で確認する:
| 境界条件 | テストの内容 |
|---|---|
| 旧形式の読込 | 旧 version / 旧 struct の凍結バイト列を新コードで deserialize |
| 新形式の往復 | 現行 struct の serialize → deserialize が一致 |
| デコード失敗 | 破損バイト列で既定値フォールバック・実データを潰さない |
| バイト安定 | 固定 fixture の serialize が golden bytes と一致(形式ドリフト検出) |
不足していれば具体的なテストケースを提案する。
根拠の規律: 全判定に根拠(file:line または grep 結果)を付ける。コード・テストを確認せずに下した判定は「満たす」とせず「要確認」として報告する。
workspace/plan.md の完成後、実装着手前に使用。計画の影響範囲・不変条件・スコープの漏れを検証する。
GitHub issue から作業を開始するときに使用。実装の前段階(ブランチ作成・調査・計画・計画レビュー)までを行う。
コード変更を伴うタスク(機能追加・バグ修正・リファクタリング)の実装時に使用。実装からコミット作成まで自律的に行う(計画が要る変更は /start-issue へ)。
大きなサイクル完了後や定期メンテナンス時に使用。governance:check(決定的検査)を実行し、機械化できない意味的整合(コマンド直書き grep・npm ラッパー等価・メモリ整合)を検証して報告する(修正はしない)。
開発サイクル完了時(実装・レビュー・追加修正まで済んだ後)に使用。教訓の抽出・残タスクの振り分け・RETROSPECTIVE.md 更新を行う。
UI モード・状態遷移・ガード条件の追加・変更時、または計画レビュー時に使用。既存モードとの直交性・リセット経路・入力分岐・SPEC §8.6 整合を検証する。