THE SPECS

AutoDev LG に渡している仕様書

AutoDev LG に渡しているのは、これだけです。
このテキストから、設計・テスト・実装までを全部ローカル LLM が行います。

仕様書は、人間のひと言(例: 「インベーダーゲームを作って」)をもとに Claude Code が書きます。将来は、仕様書づくりも AutoDev LG 自身に任せる予定です。箇条書きの仕様だけで、画面のデザインやコードの書き方は指示していません。後半の保存やエラー処理の細かい決まりは、ローカル LLM が作ったアプリを自動テストで厳しくチェックするためのものです。

taskboardINVADERS

taskboardタスクボード

✅ 3 回連続 PASS 達成
65 行・1,499 文字 · SPEC_LG1_DEMO.md · このアプリを見る →
LG1 Demo App: Mini Task Board

Windows 11で動くPython標準ライブラリのみの小規模デスクトップアプリを作成する。

UI

  • Tkinter GUI
  • タスク追加
  • タスク削除
  • status変更: todo / doing / done
  • 一覧表示
  • 一覧には ID / Title / Status を表示する
  • タスク選択後にボタン操作で削除・status変更する
  • 操作エラーは tkinter.messagebox でユーザーへ通知する

Domain

  • titleはstrのみ
  • titleはstripして保存
  • strip後空ならValueError
  • statusは todo / doing / done のみ
  • 不正statusは、unhashable値を含めValueError
  • unknown task idはKeyError
  • boolをinteger IDとして扱わない
  • listはID昇順
  • listの返り値は内部listそのものではない

Persistence

  • JSON
  • 保存先は data/tasks.json
  • UTF-8
  • 日本語タイトルを保持
  • 再起動後も状態保持
  • IDは1から開始
  • 削除済みIDを再利用しない
  • next_idは永続化する
  • 既存の空JSONファイルはStoreError
  • malformed JSONはStoreError
  • invalid UTF-8はStoreError
  • strict schema validation
  • duplicate IDを拒否
  • next_idは全既存IDより大きい

Atomic save

  • 保存先と同一ディレクトリにtemporary file
  • flush
  • os.fsync
  • os.replace
  • mkstemp/write/fsync/replace失敗を適切に扱う
  • replace前の失敗では既存destinationを破壊しない
  • temporary fileをcleanupする

Transaction contract

add_task / set_status / delete_task の永続化処理中に例外が発生した場合:

  • TaskServiceのin-memory stateを操作前へ完全rollbackする
  • add_taskではtasksとnext_idの両方を戻す
  • set_statusでは元statusへ戻す
  • delete_taskでは削除したtaskを戻す
  • persistence層から発生した元例外を別の例外へ変更せず、そのまま再raiseする
  • rollback後もTaskServiceが公開する状態と次回save対象状態が一致する

Structure

最低限:

  • task_model.py
  • task_store.py
  • task_service.py
  • app.py
  • test_task_manager.py

TaskStoreは永続化を主責務とし、domainのmutable stateをTaskServiceと二重所有しないこと。

Constraints

  • Python標準ライブラリのみ
  • アプリ本体はネットワーク通信しない
  • アプリ本体はsubprocessを実行しない
  • テスト専用の特殊分岐を実装しない

INVADERSインベーダーゲーム

🚧 挑戦中
65 行・1,913 文字 · SPEC_LG1_INVADERS.md · このアプリを見る →
LG1 Demo App: Mini Invaders

Windows 11で動くPython標準ライブラリのみの小規模デスクトップゲーム(インベーダー風)を作成する。

UI

  • Tkinter GUI
  • Canvasにゲーム状態を描画する
  • 左キー / 右キーで自機を移動する
  • Spaceキーで弾を発射する
  • Pキーで一時停止 / 再開する
  • Rキーでゲームをリスタートする
  • スコアとライフをLabelで表示する
  • ゲームオーバー / クリア時にメッセージをLabelで表示する
  • 描画はゲーム状態を読み取るだけで、状態を変更しない
  • 時間進行はtkinterのafterで一定間隔にtickを呼ぶ。テストからはafterに頼らずtickを直接呼べる

Domain

  • ゲーム盤は整数セルの格子で、幅は20、高さは15
  • 自機は最下行にいて、xは0以上19以下。範囲外へは移動しない(端で止まる)
  • 移動方向はleftまたはrightのみ。それ以外はValueError
  • インベーダーは初期状態で4行×8列。最上段から2行目の位置に左寄せで並ぶ
  • インベーダー群はtickごとに1セル横へ進み、端に達したら1行下がって向きを反転する
  • 自機の弾は同時に1発まで。tickごとに1セル上へ進む。発射済みの間の発射はno-op
  • 弾がインベーダーと同じセルに入ったらそのインベーダーを削除し、スコアを10点加算し、弾を消す
  • インベーダーの爆弾は、注入されたrandom.Random(seed)でどのインベーダーが撃つかを決める。同じseedなら同じ結果になる
  • 爆弾はtickごとに1セル下へ進む。自機と同じセルに入ったらライフを1減らし、爆弾を消す
  • ライフが0になるか、インベーダーが自機の行に到達したらゲームオーバー
  • インベーダーを全滅させたらクリア
  • ゲームオーバー / クリア後および一時停止中の操作とtickは状態を変更しない
  • 状態のスナップショットは内部のlistそのものではない
  • boolを整数座標として扱わない

Persistence

  • ハイスコアはJSON
  • 保存先は data/highscore.json
  • UTF-8
  • 形式は {"high_score": 0以上の整数}
  • 既存の空JSONファイルはStoreError
  • malformed JSONはStoreError
  • invalid UTF-8はStoreError
  • strict schema validation(未知のキー、負数、bool、整数以外を拒否)
  • ファイルが存在しない場合はhigh_score 0として扱う

Atomic save

  • 保存先と同一ディレクトリにtemporary file
  • flush
  • os.fsync
  • os.replace
  • mkstemp/write/fsync/replace失敗を適切に扱う
  • replace前の失敗では既存destinationを破壊しない
  • temporary fileをcleanupする

Transaction contract

ゲーム終了時のハイスコア更新の永続化処理中に例外が発生した場合:

  • ゲームのin-memory state(score, game_over, high_score)を操作前へ完全rollbackする
  • persistence層から発生した元例外を別の例外へ変更せず、そのまま再raiseする
  • rollback後もゲームが公開する状態と次回save対象状態が一致する

Structure

最低限:

  • game_model.py (状態を表すデータクラスとStoreError)
  • game_engine.py (Tkに依存しない純粋なゲームロジック)
  • score_store.py (ハイスコアの永続化)
  • app.py (Tkinter GUI)
  • test_game.py

ScoreStoreは永続化を主責務とし、ゲームのmutable stateをGameEngineと二重所有しないこと。

Constraints

  • Python標準ライブラリのみ
  • アプリ本体はネットワーク通信しない
  • アプリ本体はsubprocessを実行しない
  • テスト専用の特殊分岐を実装しない
  • game_engine.pyはtkinterをimportしない