[プロジェクトが失われる空のレジストリ作成問題] - DevClaw Silently Forks Project Registry State by Creating Empty devclaw/projects.json
ワークスペーススキャフォールディングがレガシー状態を検出せずに空の正規レジストリを作成し、再起動後にプロジェクトが消えたように見える状態を引き起こします。
🔍 症状
観察可能な動作
DevClawワークスペース足場が標準レジストリ缺失を検出した際、既存のレガシー状態を検出せずに空のレジストリを作成します:
# Canonical registry path
$ cat ~/.openclaw/workspace/devclaw/projects.json
{
"projects": {}
}
이전 세션에서 등록된プロジェクトがあるにもかかわらず、レジストリは空です。
下流の影響
ユーザーは次の動作不良を経験します:
- 再起動後にプロジェクトが消える: 以前的セッションで登録されたプロジェクトが `devclaw projects list` に表示されなくなりました
- チャネルルーティングの失敗: タスクルーティングが、以前登録されたチャネルに対して
Project not foundエラーで失敗します - ツール動作の異常: プロジェクト/タスクツールが空の結果を返すか、「プロジェクトが登録されていません」エラーを返します
- サイレント状態フォーク: 起動中にレガシー状態がバイパスされたことを示す警告やエラーが発生しません
診断コマンドの出力
$ devclaw projects list
[]
$ devclaw status
Project Registry: EMPTY
Last Updated: (timestamp of empty file creation)
$ ls -la ~/.openclaw/workspace/devclaw/
total 8
drwxr-xr-x 2 sai sai 4096 Jan 20 10:30 devclaw/
-rw-r--r-- 1 sai sai 0 Jan 20 10:30 projects.json
# Legacy registry still exists unexamined
$ ls -la ~/.openclaw/workspace/
total 8
-rw-r--r-- 1 sai sai 2048 Jan 19 14:22 projects.json # Legacy state ignored
drwxr-xr-x 2 sai sai 4096 Jan 20 10:30 devclaw/
🧠 原因
アーキテクチャの背景
DevClawはプロジェクトレジストリをコントロールプレーン状態として維持します。レジストリはすべての登録済みプロジェクト、そのメタデータ、チャネルルーティング情報を追跡します。この状態は標準パスにディスクに永続化されます。
失敗のシーケンス
ワークスペースの初期化中に次のシーケンスで重大な障害が発生します:
- ワークスペース足場のトリガー: 初回起動時または標準ディレクトリ構造が欠落している場合、DevClawはワークスペース足場ロジックを実行します
- 標準レジストリの欠落を検出: 足場が
~/.openclaw/workspace/devclaw/projects.jsonを確認します - 欠落は新鮮な状態を意味する: 足場はレガシー位置をクエリせずに「ファイル欠落」を「新しワークスペース」と解釈します
- 空のレジストリが作成される: 空の
{ "projects": {} }が標準パスに書き込まれます - レガシー状態が孤立: レガシーパスにある既存のレジストリは検出も移行もされません
コードフローの分析
// Pseudocode representation of current scaffolding behavior
function initializeWorkspace():
canonicalRegistry = resolvePath("~/.openclaw/workspace/devclaw/projects.json")
if not fileExists(canonicalRegistry):
# BUG: Missing check for legacy registry locations
createDirectoryStructure()
writeEmptyRegistry(canonicalRegistry) # Silent fork occurs here
return
# Only reached if canonical exists
loadRegistry(canonicalRegistry)
レガシーレジストリの場所
DevClawは歴史的に複数のレジストリ保存パスをサポートしていました:
~/.openclaw/workspace/projects.json~/.openclaw/workspace/projects/projects.json~/.openclaw/projects.json
現在の足場は新鮮な標準レジストリを作成する前にこれらのパスをクエリしません。
これが危険な理由
障害がサイレントなのは以下のためです:
- 終了コードは0(成功)
- レジストリ作成を示すコンソール出力がない
- 標準vsレガシー状態の整合性チェックがない
- 履歴状態が実際には存在するがバイパスされたことを示す通知がユーザーに届かない
🛠️ 解決手順
フェーズ1:予防的ガード(足場レイヤー)
ワークスペース足場ロジックは、新鮮な標準レジストリを作成する前にレガシー レジストリの存在を確認する必要があります。
修正前(脆弱な足場):
function initializeWorkspace():
canonicalRegistry = resolvePath("~/.openclaw/workspace/devclaw/projects.json")
if not fileExists(canonicalRegistry):
createDirectoryStructure()
writeEmptyRegistry(canonicalRegistry)
return
loadRegistry(canonicalRegistry)
修正後(保護された足場):
function initializeWorkspace():
canonicalRegistry = resolvePath("~/.openclaw/workspace/devclaw/projects.json")
legacyRegistries = [
resolvePath("~/.openclaw/workspace/projects.json"),
resolvePath("~/.openclaw/workspace/projects/projects.json"),
resolvePath("~/.openclaw/projects.json")
]
if not fileExists(canonicalRegistry):
// Check for orphaned legacy state
existingLegacy = findFirstExisting(legacyRegistries)
if existingLegacy is not null:
throw MigrationRequiredError(
"Legacy registry found at: " + existingLegacy.path +
". Migrate before initializing fresh workspace."
)
createDirectoryStructure()
writeEmptyRegistry(canonicalRegistry)
return
loadRegistry(canonicalRegistry)
フェーズ2:移行パス
レガシー状態が検出された場合、移行コマンドを提供します:
CLI移行コマンド:
# Detect and display legacy registry locations
$ devclaw registry diagnose
Registry Diagnostic Report
===========================
Canonical Path: ~/.openclaw/workspace/devclaw/projects.json
Status: MISSING
Legacy Registries Found:
- ~/.openclaw/workspace/projects.json (MODIFIED: 2024-01-19 14:22)
- ~/.openclaw/projects.json (MODIFIED: 2023-12-15 09:30)
To migrate legacy state:
$ devclaw registry migrate --source ~/.openclaw/workspace/projects.json
To start fresh (WARNING: deletes legacy state):
$ devclaw registry reset --force
移行の実行:
# Migrate from legacy location
$ devclaw registry migrate --source ~/.openclaw/workspace/projects.json
Migrating registry...
Source: ~/.openclaw/workspace/projects.json
Target: ~/.openclaw/workspace/devclaw/projects.json
Projects to migrate: 5
Channels to migrate: 12
[████████████████████] 100%
Migration complete. 5 projects migrated successfully.
フェーズ3:修正の検証
# Subsequent startup should not create empty registry when legacy exists
$ devclaw start
Error: Legacy registry detected at ~/.openclaw/workspace/projects.json
Run 'devclaw registry migrate' before starting DevClaw.
# After migration, startup proceeds normally
$ devclaw registry migrate --source ~/.openclaw/workspace/projects.json
$ devclaw start
DevClaw initialized successfully.
Projects: 5 registered
Channels: 12 active
🧪 検証
テストケース1:新しワークスペース(レガシーなし)
# Clean state: no canonical, no legacy
$ rm -rf ~/.openclaw/workspace/devclaw
$ rm -f ~/.openclaw/workspace/projects.json
$ devclaw start
DevClaw initialized successfully.
Canonical registry created: ~/.openclaw/workspace/devclaw/projects.json
$ cat ~/.openclaw/workspace/devclaw/projects.json
{"projects":{}}
# Exit code
$ echo $?
0
テストケース2:レガシーが存在、標準が欠落
# Setup: legacy exists, no canonical
$ mkdir -p ~/.openclaw/workspace
$ echo '{"projects":{"test-project":{"path":"/home/sai/test"}}}' > ~/.openclaw/workspace/projects.json
$ rm -rf ~/.openclaw/workspace/devclaw
$ devclaw start
# Should FAIL with migration error
Error: Legacy registry detected.
Location: ~/.openclaw/workspace/projects.json
Run: devclaw registry migrate
$ echo $?
1
# Verify empty canonical was NOT created
$ ls ~/.openclaw/workspace/devclaw/
ls: cannot access '~/.openclaw/workspace/devclaw/': No such file or directory
テストケース3:正常移行後
$ devclaw registry migrate --source ~/.openclaw/workspace/projects.json
Migration complete.
$ devclaw start
DevClaw initialized successfully.
$ cat ~/.openclaw/workspace/devclaw/projects.json
{"projects":{"test-project":{"path":"/home/sai/test"}}}
$ devclaw projects list
test-project
テストケース4:回帰防止
# Attempt to bypass migration by pre-creating empty canonical
$ echo '{}' > ~/.openclaw/workspace/devclaw/projects.json
$ devclaw start
# Should detect fork/inconsistency
Warning: Canonical registry is empty but legacy state exists.
Canonical: ~/.openclaw/workspace/devclaw/projects.json
Legacy: ~/.openclaw/workspace/projects.json (2048 bytes)
Run 'devclaw registry migrate' to reconcile.
$ echo $?
1
⚠️ よくある落とし穴
環境固有のトラップ
- Dockerコンテナ初期化: DevClawがDocker内で実行される場合、ボリュームマウントはディレクトリ構造を作成するかもしれませんが、
projects.jsonを欠落したままにする可能性があります。コンテナのエントリポイント足場は、ホストボリュームにレガシーが存在する場合に状態をフォークします。 - macOSの大文字小文字の区別: ファイルシステムはデフォルトで大小文字を区別しません。
projects.jsonとProjects.jsonが異なるレガシー場所に両方存在する可能性があり、診断中に混乱を招く動作を引き起こします。 - Windowsパスの解決: レガシーパスはバックスラッシュまたは混合区切り文字を使用する可能性があります。ガードは比較前にパスを正規化する必要があります。
- ネットワークファイルシステム(NFS): ファイルの存在チェックは同時書き込みと競合する可能性があります。レジストリのチェックと作成時にファイルロックまたはアトミック操作を使用します。
ユーザーの設定ミス
- 部分的な移行: ユーザーが正しいソースパスを指定せずに
devclaw registry migrateを実行すると、別のpopulateされたレガシーが他の場所に存在する間に空のレガシー場所から移行する可能性があります。 - 手動状態編集:
projects.jsonを手動で編集するユーザーはJSON構文エラーを作成し、移行がサイレントに失敗して空の標準レジストリを作成する可能性があります。 - シンボリックリンクの混乱: レガシーまたは標準パスへのシンボリックリンクは検出ロジックを混乱させる可能性があります。比較前に
realpath解決を実装します。 - 権限の問題: ユーザーが
devclaw/projects.jsonを作成する書き込み権限を持っていない場合、足場は明確なエラーメッセージなしで失敗するか、ディレクトリは作成するがファイルは作成しない可能性があります。
エッジケース
- ゼロバイトのレガシーファイル: 存在するが空(0バイト)であるレガシー
projects.jsonは、欠落ファイルとは異なった扱いを受ける必要があります。ガードは「レガシーなし」と「空のレガシー」を区別する必要があります。 - 破損したJSONレガシー: レガシーが不正なJSONを含む場合、移行は空の標準レジストリを作成することへのフォールバックではなく、特定のエラーで失敗する必要があります。
- 同時DevClawインスタンス: 複数のDevClawインスタンスが同時に起動すると、空のレジストリを作成するために競合する可能性があります。初期化中にファイルロック(
flock)を使用します。 - 書き込み中の移行中断: レガシーのコピーの後、内部状態の更新前に移行プロセスがkillされた場合、システムが一貫性のない状態のままになる可能性があります。アトミック書き込みまたはトランザクションログを実装します。
🔗 関連するエラー
論理的に接続されたエラーコード
REGISTRY_NOT_FOUND: 標準レジストリパスが存在せず、フォールバックも利用不可REGISTRY_CORRUPTED: レジストリファイルは存在するが有効なJSONを含まないLEGACY_REGISTRY_DETECTED: 初期化中にレガシー レジストリの場所が検出された; 移行が必要MIGRATION_IN_PROGRESS: レジストリ移行が失敗したか中断されたPROJECT_NOT_REGISTERED: プロジェクトがレジストリに存在しないため、プロジェクト検索が失敗したCHANNEL_ROUTING_FAILED: プロジェクトメタデータの欠落によりタスクルーティングが失敗したWORKSPACE_INIT_FAILED: 足場が必要なディレクトリ構造を作成できなかった
過去のIssues
- Issue #142: 「システム再起動後にプロジェクト レジストリが断続的に空になる」- このサイレントフォーク動作を露呈した初期症状レポート
- Issue #156: 「新鮮なセッションですべてのプロジェクトのチャネルルーティングが失敗する」- 孤立した空のレジストリの下流の結果
- Issue #167: 「移行コマンドがすべてのレガシー パスを検出しない」- 不完全な移行パス修正
- Issue #189: 「Dockerボリュームのマウントがレジストリ状態の損失を引き起こす」- 同じ根本原因の環境固有の現れ
防止チェックリスト
# Pre-flight check before upgrading DevClaw
$ devclaw registry pre-flight-check
Running pre-flight checks...
[✓] Verifying canonical registry path accessibility
[✓] Checking for legacy registry locations
[✓] Validating registry JSON integrity
[✓] Confirming write permissions
Pre-flight complete. No issues detected.
# If issues detected:
$ devclaw registry pre-flight-check --verbose
Running pre-flight checks...
[✓] Canonical: ~/.openclaw/workspace/devclaw/projects.json (exists)
[⚠] Legacy detected: ~/.openclaw/workspace/projects.json (2048 bytes)
[!] Action required: Run 'devclaw registry migrate' before upgrading