active: true
derived: false
groups:
- CACHE
header: |
  Strict Scoping for Imperative Execution (Runtime Guard)
level: 1.14
links:
- ARCH001: njFV9W_NXjx3dMCDMAVXf0g99DYN8tKwPHU5nP1tFhA=
- REQ001: 06OUEtR_P_Ao75pk04k0_gee2X4JLNEDpL76-c2iGgQ=
normative: true
ref: ''
reviewed: 6wv9V1n4Inw8zxrYf11igH7uzetDO9c7Rm1Lu_cV7E8=
status: accepted
text: |
  # 命令型実行のための厳密なスコープ管理（ランタイムガード）

  ## コンテキストと課題

  `spot.cached_run()` コンテキストマネージャを使用すると、ユーザーは一時的に関数のキャッシュ挙動を適用できます。しかし、Python の `with` 文のスコープルールにより、ブロック内でバインドされた変数（例: `with ... as task:`）はブロック終了後もアクセス可能です。

  これにより、ユーザーが特定のコンテキスト設定（`version="v1"` や一時的なストレージ設定など）を持つ関数ラッパーを、意図しない場所で再利用してしまうリスクがあります。これは微妙なバグやリソースリークの原因となります。

  ## 判断基準

  * **Safety**: 意図しないスコープ外での「古い」または「コンテキスト固有の」ラッパーの使用を排除すること。
  * **Clarity**: キャッシュ挙動が厳密に一時的なものであるというメンタルモデルを強制すること。
  * **Resource Management**: 短命な `spot` インスタンスや注入されたインスタンスをより安全に使用できるようにすること。

  ## 検討した選択肢

  * **Option 1**: ガードを実装せず、ユーザーの注意に任せる。
  * **Option 2**: **Runtime Guard** パターンを導入し、ブロック外での呼び出しを制限する。

  ## 決定事項

  採用した選択肢: **Option 2**.

  `ScopedMark` コンテキストマネージャに **Runtime Guard** パターンを実装します。

  1.  **State Tracking**: コンテキストマネージャはアクティブ状態のフラグを保持する。
  2.  **Wrapper Guard**: `cached_run` から返される関数は、実行前にこのフラグをチェックするガードでラップされる。
  3.  **Fail Fast**: ラップされた関数が `with` ブロックの外で呼び出された場合、即座に `RuntimeError` を送出する。

  ## 影響・結果

  * **ポジティブ**:
      * 意図しないスコープ外での使用によるリスクを排除できる。
      * 「キャッシュマジック」は厳密に一時的なものであるという確信が持てる。
      * 関数参照が使用直後に無効になるため、リソース管理が安全になる。
  * **ネガティブ**:
      * ブロック内での関数呼び出しごとに、極小のオーバーヘッド（ブールフラグのチェック）が発生する。
      * ラップ処理の追加により、`ScopedMark` の実装がわずかに複雑になる。
