Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when adding or changing save games, settings or progression storage - a versioned save format with a tested migration chain, atomic writes with backup and checksum, per-engine storage locations, safe serializers, and the round-trip/migration/corruption tests.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
A save file outlives the code that wrote it. Players carry saves across updates, crashes happen mid-write, and a lost 40-hour save is the bug players remember. Every save has a version, every older version has a tested migration, and a write never destroys the last good save.
Core principle: Versioned, migrated, written atomically, checked on load — and never deserialized with a format that can execute code.
{
"version": 3,
"savedAtUtc": "2026-10-08T12:00:00Z",
"player": { "levelId": "forest_02", "position": [12.5, 0, -4.0], "hp": 72 },
"inventory": [{ "itemId": "sword_iron", "count": 1 }],
"flags": ["met_blacksmith", "boss_forest_defeated"]
}
GameObject, Node or AActor references, no array indices into data tables — stable IDs only (data-driven-gameplay-design).store_var without objects) is fine when size matters — the version field stays first.type Migration = (save: any) => any;
const migrations: Record<number, Migration> = {
1: (s) => ({ ...s, version: 2, inventory: s.items.map((id: string) => ({ itemId: id, count: 1 })) }),
2: (s) => ({ ...s, version: 3, flags: Object.keys(s.questState ?? {}).filter((k) => s.questState[k] === "done") }),
};
export function upgrade(raw: any): SaveV3 {
if (typeof raw?.version !== "number") throw new SaveError("unversioned");
if (raw.version > CURRENT) throw new SaveError("from a newer game version"); // refuse, never guess
let s = raw;
while (s.version < CURRENT) s = migrations[s.version](s);
return SaveV3Schema.parse(s);
}
tests/fixtures/saves/v1.json, v2.json).save.json.tmp, flush to disk.save.json.bak.save.json (atomic on the same volume).On load: verify the checksum and parse; on failure fall back to .bak, tell the player, and never crash or silently start a new game over the old one.
Serialize on the main thread if the engine requires it, but do file I/O off it (or between frames at a checkpoint) — a save must not hitch gameplay. Autosave at checkpoints, not every frame.
| Engine | Location / API |
|---|---|
| Unity | Application.persistentDataPath + System.IO; PlayerPrefs only for tiny settings |
| Godot | user:// with FileAccess; ConfigFile for settings |
| Unreal | USaveGame subclass + UGameplayStatics::AsyncSaveGameToSlot / LoadGameFromSlot; keep a version UPROPERTY in it |
| Web | IndexedDB for saves (async, larger; e.g. idb-keyval), localStorage only for small settings — it is synchronous, ~5 MB and can throw in private mode or when full |
| Bevy / Rust | serde to the platform data dir (directories crate) |
| pygame / MonoGame | the OS user data directory, never the install folder |
Consoles and some stores impose their own save APIs and size limits — follow the platform layer the repository already has.
BinaryFormatter: obsolete and insecure; do not use it in Unity, MonoGame or Godot C#.bytes_to_var_with_objects / str_to_var on untrusted data, and loading a user-supplied .tres/.res, can instantiate scripts — use JSON, ConfigFile, or FileAccess.get_var(false) (objects disallowed).pickle for pygame saves: a shared or downloaded save becomes code execution — use JSON.vN.json → upgrade → matches the expected current-version object..bak and reports; no exception escapes.BinaryFormatter, pickle, or object-enabled Godot variant decoding in a save path.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。