目的
adapter/claude/hooks/on-session-start.sh の MEMORY_DIR 解決が slug 境界を越え、別ワークスペースの memory を当該セッションの observe stage 入力として採用する経路を塞ぐ。
観測事実
cold-start で surface された promotion candidates が、別ワークスペースの memory ディレクトリ由来だった。二つのワークスペースから独立に再現。
| 観測元 |
slug |
surface された候補 |
| Lin |
C--Users-smile-Claude-Lin |
C--Users-smile-Code/memory/ の5件 |
| Lay |
C--Users-smile-Claude-Lay |
同一の5件 |
ls -1td ~/.claude/projects/*/memory の並びでは C--Users-smile-Claude-Lin / C--Users-smile-Claude-Lay が C--Users-smile-Code より新しい。しかし両者とも空で memory_dir_populated() を通らないため、glob fallback は populated な C--Users-smile-Code を採用する。
つまり誤選択の形は「直近更新を掴む」ではなく 「空でない他 slug を掴む」。memory_dir_populated() が shadow 防止のために課している populated 条件が、slug 境界の外側にまで作用している。
前提
- 該当箇所 =
adapter/claude/hooks/on-session-start.sh の MEMORY_DIR 解決ブロック(glob fallback ls -1td "$HOME"/.claude/projects/*/memory)
- 同形の fallback が同ファイルの self-eval log lookup 側にも存在する(コメントは「self-eval log fallback の mirror」と述べている)ため、射程は同一ファイル内の2箇所
- codex 側の PowerShell port は本件の射程外(検証済み)。
adapter/codex/hooks/on-session-start.ps1 は self-eval lookup(L355-360)・$memoryDir 解決(L618-624)のいずれも $projectRoot/memory と $liplusDir/memory のみを見ており、cross-slug glob を持たない。理由は同ファイル L353 のコメントが述べているとおり「Codex has no ~/.claude/projects/<slug>/memory」——ホスト側に per-slug memory レイアウト自体が存在しないため、構造的に本欠陥に到達しない
- したがって本件は Claude ホスト固有であり、両 port の差分は移植漏れではなく前提の差である
- fallback 自体は slug 不一致時の救済として意図的な設計。撤去ではなく射程の議論
- 観測環境: Claude Desktop / build-2026-08-21.2
制約
memory_dir_populated() の「空の高優先ディレクトリが populated な低優先を shadow しない」意図は slug 内では正しい。この不変条件を壊さないこと
- 空の memory dir と「観測材料が無い」は区別可能でなければならない(silent skip が正しい振る舞いのケースを潰さない)
- codex port には手を入れない(上記のとおり射程外。parity を理由に同形の変更を持ち込まないこと)
論点
observe stage の入力面として、別ワークスペースの観測を自分の promotion 判断材料に混ぜてよいか。混ぜてはならないなら、glob fallback の探索範囲を当該 slug に閉じるか、候補が自 slug 外だったときに surface 側で出所を明示するかの二択。
変更予定ファイル
adapter/claude/hooks/on-session-start.sh —— MEMORY_DIR 解決 + self-eval log lookup の2箇所の glob fallback
tests/ —— fallback 射程の契約テスト(自 slug 外を掴まないこと)
目的
adapter/claude/hooks/on-session-start.shの MEMORY_DIR 解決が slug 境界を越え、別ワークスペースの memory を当該セッションの observe stage 入力として採用する経路を塞ぐ。観測事実
cold-start で surface された promotion candidates が、別ワークスペースの memory ディレクトリ由来だった。二つのワークスペースから独立に再現。
C--Users-smile-Claude-LinC--Users-smile-Code/memory/の5件C--Users-smile-Claude-Layls -1td ~/.claude/projects/*/memoryの並びではC--Users-smile-Claude-Lin/C--Users-smile-Claude-LayがC--Users-smile-Codeより新しい。しかし両者とも空でmemory_dir_populated()を通らないため、glob fallback は populated なC--Users-smile-Codeを採用する。つまり誤選択の形は「直近更新を掴む」ではなく 「空でない他 slug を掴む」。
memory_dir_populated()が shadow 防止のために課している populated 条件が、slug 境界の外側にまで作用している。前提
adapter/claude/hooks/on-session-start.shの MEMORY_DIR 解決ブロック(glob fallbackls -1td "$HOME"/.claude/projects/*/memory)adapter/codex/hooks/on-session-start.ps1は self-eval lookup(L355-360)・$memoryDir解決(L618-624)のいずれも$projectRoot/memoryと$liplusDir/memoryのみを見ており、cross-slug glob を持たない。理由は同ファイル L353 のコメントが述べているとおり「Codex has no~/.claude/projects/<slug>/memory」——ホスト側に per-slug memory レイアウト自体が存在しないため、構造的に本欠陥に到達しない制約
memory_dir_populated()の「空の高優先ディレクトリが populated な低優先を shadow しない」意図は slug 内では正しい。この不変条件を壊さないこと論点
observe stage の入力面として、別ワークスペースの観測を自分の promotion 判断材料に混ぜてよいか。混ぜてはならないなら、glob fallback の探索範囲を当該 slug に閉じるか、候補が自 slug 外だったときに surface 側で出所を明示するかの二択。
変更予定ファイル
adapter/claude/hooks/on-session-start.sh—— MEMORY_DIR 解決 + self-eval log lookup の2箇所の glob fallbacktests/—— fallback 射程の契約テスト(自 slug 外を掴まないこと)