Skip to content

fix(entrypoint): JSON エントリのプレースホルダを {} で作る - #137

Merged
takemi-ohama merged 1 commit into
mainfrom
fix/issue136-json-placeholder
Sep 2, 2026
Merged

takemi-ohama merged 1 commit into
mainfrom
fix/issue136-json-placeholder

Conversation

@takemi-ohama

Copy link
Copy Markdown
Contributor

Closes #136

背景

新規アカウントグループの初回起動で ~/.claude.json が 0 バイトで作られ、Claude Code が起動を拒否していました。

The configuration file at /home/ubuntu/.claude.json contains invalid JSON.

#133 の対応で with / kkg グループを新設したところ、両方で発生しました。

原因

devbase_ensure_entry はファイルエントリを : > "$path" で作ります。default グループは devbase_seed_group_settings が /persistent/ai から実体をコピーするため踏みませんが、非 default はシードを飛ばすので必ず空のプレースホルダになります。

# devbase_seed_group_settings (349-355 行)
if [ "$group" != "default" ]; then
    return 0
fi

このガード自体は正しい設計です。 非 default グループをシードすると PLAN39 で分離したはずの他社テナントの認証情報をコピーしてしまいます。問題はガードではなく、プレースホルダが妥当な JSON になっていないことでした。

変更内容

空で作ると壊れるエントリを DEVBASE_JSON_FILE_ENTRIES として列挙し、該当するものは {} を書きます。

DEVBASE_JSON_FILE_ENTRIES=(
    ".claude.json"
    ".credentials.json"
    "settings.json"
)
  • history.jsonl は 入れません。JSON Lines なので {} を書くと 1 行目が履歴の 1 件として読まれます
  • CLAUDE.md も Markdown なので空でよい
  • 拡張子(*.json)で判定しないのは DEVBASE_FILE_ENTRIES と同じ理由です。かつて .jsonl が *.json にマッチせず history.jsonl がディレクトリとして作られた経緯がコメントに残っています

devbase_is_file_entry と devbase_is_json_file_entry が同型になったので、名前の照合を devbase_entry_name_in に集約しました。

検討したが採らなかった案

案 不採用の理由
.claude.json だけ特別扱い settings.json は共通ボリュームを新規に作れば同じ壊れ方をする。今直せる穴を残す理由がない
非 default グループもシードする PLAN39 の分離目的(他社テナントの認証情報を持ち込まない)を壊す
起動時に 0 バイトを検出して {} を書く 「実体があるものには触れない」という devbase_ensure_entry の契約を壊す。利用者が意図的に空にしたファイルも書き換えてしまう

判断の記録は issues/PLAN41_json-placeholder-invalid.md に残しています。

影響範囲

DEVBASE_FILE_ENTRIES の各エントリが実際にどの経路を通るかを実機で確認しました。

エントリ ensure_entry に渡るか 空だと壊れるか 状態
.claude.json 渡る 壊れる 顕在。本 PR で修正
settings.json 渡る 壊れる 潜在。共通ボリュームに実体があるため未発生。本 PR で予防
CLAUDE.md 渡る 壊れない 影響なし
.credentials.json 渡らない(.claude ごと symlink) 壊れる 影響なし。将来の予防として列挙
history.jsonl 渡らない(同上) 壊れない 影響なし

テストプラン

  • 失敗するテストを先に書き、赤を確認(test_new_group_gets_a_parsable_claude_json / test_shared_settings_json_is_parsable)
  • 実装後に緑を確認
  • pytest tests/ 全件: 1724 passed
  • ruff check --select=E9,F63,F7,F82 lib(CI と同じ): All checks passed
  • shellcheck -S warning containers/base/entrypoint.sh: 変更箇所に新規警告なし(既存 3 件は別行)

追加したテスト:

テスト 固定する契約
test_new_group_gets_a_parsable_claude_json 非 default の初回起動で .claude.json が妥当な JSON
test_shared_settings_json_is_parsable settings.json も同様
test_non_json_entries_stay_empty CLAUDE.md は空のまま
test_history_jsonl_is_not_pre_created history.jsonl はプレースホルダとして作られない(実挙動の記録)
test_existing_file_content_is_not_overwritten 2 回目以降の起動で利用者の設定を {} へ巻き戻さない
test_deliberately_emptied_file_is_left_alone 意図的に空にしたファイルは書き換えない

既存テストの期待値変更は test_non_default_groups_are_not_seeded の 1 件のみです。「シードされていない」ことを空文字で表現していた箇所で、確認内容は変えていません。

  • devbase build --no-cache でイメージを再ビルドし、新規グループのコンテナで実機確認(マージ後に実施)

注意

entrypoint.sh の変更は devbase up では反映されません。反映には devbase build --no-cache によるイメージ再ビルドが必要です。

関連

🤖 Generated with Claude Code

https://claude.ai/code/session_01NMEpP29QkUDLwrsyYjpnDL

新規アカウントグループの初回起動で ~/.claude.json が 0 バイトで作られ、
Claude Code が "contains invalid JSON" で起動を拒否していた。

devbase_ensure_entry はファイルエントリを `: > "$path"` で作る。default
グループは devbase_seed_group_settings が /persistent/ai から実体をコピーする
ため踏まないが、非 default はシードを飛ばす (他社テナントの認証情報を持ち込ま
ないための正しいガード) ので必ず空のプレースホルダになる。

空で作ると壊れるエントリを DEVBASE_JSON_FILE_ENTRIES として列挙し、そこに
該当するものは {} を書く。history.jsonl は JSON Lines なので入れない ({} を
書くと 1 行目が履歴の 1 件として読まれる)。CLAUDE.md も空でよい。

拡張子で判定しないのは DEVBASE_FILE_ENTRIES と同じ理由による。かつて .jsonl が
*.json にマッチせず history.jsonl がディレクトリとして作られた経緯がある。

test_non_default_groups_are_not_seeded は「シードされていない」ことを空文字で
表現していたため期待値を {} へ更新した。確認している内容は変えていない。

Closes #136

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMEpP29QkUDLwrsyYjpnDL

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | gemini | APPROVE

実装の正確性、既存の仕様との一貫性、テストの網羅性のいずれも問題なく、要件を安全に満たしています。修正指摘はありません。

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | codex | APPROVE

新規 JSON プレースホルダ、既存内容の保持、非 JSON エントリの後方互換性を確認し、修正必須事項はありません。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: 新規アカウントグループの .claude.json が 0 バイトで作られ Claude Code が起動しない

1 participant