Skip to content

feat(PLAN70): 作り直しても残るシェルの設定の置き場所 ~/.shellrc.d (#253) - #262

Merged
takemi-ohama merged 13 commits into
mainfrom
feature/plan70-shellrc-dir
Sep 24, 2026
Merged

takemi-ohama merged 13 commits into
mainfrom
feature/plan70-shellrc-dir

Conversation

@takemi-ohama

@takemi-ohama takemi-ohama commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #253

コンテナを作り直しても残るシェルの設定の置き場所 ~/.shellrc.d/ を用意する。設計は issues/old/PLAN70_shellrc-dir-design.md(#257 でマージ済み)、要求と受け入れ条件・タスク分解は issues/old/PLAN70_shellrc-dir.md。

  • 読み込み器 containers/base/shellrc-dir.sh を /etc/devbase/shellrc-dir.sh へ置き、~/.bashrc から ai-cli-aliases.sh の次に 1 行で読む(置き場所の定義が devbase の起動定義に勝つ)
  • 置き場所のパスをイメージの ENV DEVBASE_SHELLRC_DIR=/home/${USERNAME}/.shellrc.d で示す(非対話の docker exec からも見える)。読み込み器は変数が空なら ~/.shellrc.d を読む
  • entrypoint.sh の分類 B(DEVBASE_GROUP_SETTINGS)へ .shellrc.d を足し、/persistent/group/.shellrc.d へ張る
  • 利用者向け文書(docs/user/container-operations.md)と CHANGELOG
  • zsh と lfm は対象外(設計の決定 5・8)

反映には devbase build base --no-cache が要る(devbase up だけでは反映されない)。

構造改善(cross-refactoring)では構造の変更の採用は 0 件で、読み込み器の現状固定テストを 8 コミット足した(改修計画: #262 (comment) )。

実装レビュー(cross-review、codex / agy / kiro / claude の 4 者、3 ラウンド)で 2 件を直した: 利用者の IFS に空白が無いと failglob / dotglob を戻せなかった件(2bb114b。設定ごとに別の変数へ控えて個別に戻す)と、読めないファイル・リンク切れは何も出さずに飛ばすことの文書への明記(cc8ea96)。

Test plan

  • uv run --locked pytest tests/containers/test_shellrc_dir.py -q → 37 passed, exit=0(受け入れ条件 4〜10・6a・8・非機能の性能・Dockerfile の配置と順序。ホストの /bin/bash 3.2)
  • uv run --locked pytest tests/containers/test_entrypoint_ai_settings.py -q → 37 passed, exit=0(受け入れ条件 1・3 の関数の部分・13)
  • env -u DEVBASE_ROOT uv run pytest -q -p no:cacheprovider → 3064 passed, exit=0(受け入れ条件 12・15。cc8ea96、2026-09-24 13:41)
  • CI(cc8ea96): Pytest 3.10 / 3.13・Ruff lint・ShellCheck・Python syntax check 3.10〜3.12 がすべて success
  • 作業ツリーの ./bin/devbase build base --no-cache(arm64)→ exit=0、3 分 17 秒(受け入れ条件 16)。2bb114b(レビューの修正の後。cc8ea96 は文書だけ)から建てたイメージ sha256:2078d38bc1f1…、作成 2026-09-24T04:37:44Z。イメージの /etc/devbase/shellrc-dir.sh は作業ツリーのファイルと一致(diff で差分なし、644 root)
  • 建て直したイメージで作ったコンテナ(受け入れ条件 1・11・14)
  • 同じボリュームでのコンテナの作り直し(受け入れ条件 2・3)
  • イメージの中の bash 5.3 で tests/containers/test_shellrc_dir.py と test_ai_cli_aliases.py → 75 passed

イメージの中での確認

使い捨ての docker run(-v <テスト用ボリューム>:/persistent/ai -v <テスト用ボリューム>:/persistent/group -e DEVBASE_ACCOUNT_GROUP=...)で entrypoint を通し、対話シェルは docker exec -t <c> bash -ic(devbase login と同じ対話・非ログインのシェル)で開いた。作ったコンテナとボリュームは終了時に消した。

## ~/.bashrc の末尾
export PATH="$HOME/.local/bin:$PATH"
. /etc/devbase/ai-cli-aliases.sh
. /etc/devbase/shellrc-dir.sh
## 受け入れ条件 1: symlink と所有者
$ readlink ~/.shellrc.d            → /persistent/group/.shellrc.d
$ stat -L -c '%U:%G %F' ~/.shellrc.d → ubuntu:ubuntu directory(中身は空)
## 受け入れ条件 11: 非対話
$ docker exec <c> printenv DEVBASE_SHELLRC_DIR → /home/ubuntu/.shellrc.d(rc=0)
## 受け入れ条件 14: ~/.zshrc に shellrc の行が無い
$ grep -c shellrc ~/.zshrc → 0(中身は uv と agy のインストーラの PATH の行だけ)
## 受け入れ条件 6: 置き場所が空の対話シェル
出力なし・rc=0(shopt -s failglob の後に読み込み器を読んでも rc=0)
## 受け入れ条件 2: ~/.shellrc.d/plan70.sh に alias plan70probe='echo kept'
作り直す前: kept
コンテナを消し、同じボリュームで作り直した後: kept
ログインシェル(tmux の窓の形 bash -lic): kept
非対話の bash -c では読まれない: not-defined
## 受け入れ条件 3
同じグループのボリュームの別のコンテナ: kept
別のグループのボリュームのコンテナ: not-defined
## 受け入れ条件 4・5・7・8(10-a.sh / 20-b.sh / x.txt / .h.sh / 構文の誤りの 15-bad.sh / 30-claude.sh)
15-bad.sh の構文の誤りは標準エラーに出て、後ろのファイルは読まれた
ord → b(20-b.sh が勝つ) / x.txt と .h.sh は読まれない / alias claude='echo overridden'(ai-cli-aliases.sh に勝つ)
## 受け入れ条件 9
読み込みの後、__devbase で始まる変数は 0 個、先に置いた f=keep は変わらない

受け入れ条件 2・3 は計画では実プロジェクトの devbase down → devbase up で確かめるとしていたが、検査の時点で利用者のコンテナを起こさない決まりのため、同じ形(アカウントグループのボリュームを保ったままコンテナを作り直す)を使い捨てのコンテナとテスト用のボリュームで確かめた。devbase up がボリュームを /persistent/group へ付ける経路はこの変更で変わっていない。

CI はイメージを建てない。上のイメージの中の確認は手元(arm64)で採った。amd64 では建てていない。

確定仕様化(b881eda)

対象 内容
docs/specifications/shellrc-dir.md 確定仕様を新設(前例 PLAN67 / PR #252 の 1d4c3b4 と同じ形)
issues/PLAN70_shellrc-dir*.md → issues/old/ 要求と設計の 2 文書を移した(中身は変えていない)
docs/user/container-operations.md 新しい確定仕様へのリンク

env -u DEVBASE_ROOT uv run pytest -q exit=0、CI(b881eda)すべて success。

🤖 Generated with Claude Code

- 読み込み器 containers/base/shellrc-dir.sh を /etc/devbase/ へ置き、~/.bashrc から
  ai-cli-aliases.sh の次に読む
- 置き場所のパスをイメージの ENV DEVBASE_SHELLRC_DIR で示す
- entrypoint の分類 B の一覧へ .shellrc.d を足し、グループのボリュームへ張る
- 回帰テスト、利用者向け文書、CHANGELOG、実装計画のタスク分解

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fix the observed no-fallback behavior when DEVBASE_SHELLRC_DIR points to a missing directory.

Item-Id: R1-001
Round: 1
Impl-Runtime: codex
Impl-Model: default
@takemi-ohama

takemi-ohama commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor Author

改修計画 — devbasex/devbase #262

/ndf:cross-refactoring が提案し、適用した改善項目の記録である。
理由と手順は提案の時点でしか残らないため、公開の直前に書き出している。

  • 対象範囲: containers/base/shellrc-dir.sh, tests/containers/test_shellrc_dir.py
  • 着手前のテスト: env -u DEVBASE_ROOT uv run pytest -q -p no:cacheprovider

ラウンド 1(実装 codex)

R1-001 — containers/base/shellrc-dir.sh#__devbase_shellrc_dir

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude 採用 1

なぜ: 置き場所の決定は『変数が指す既存ディレクトリ』と『未設定・空なら ~/.shellrc.d』しか固定されていない。DEVBASE_SHELLRC_DIR が存在しないディレクトリを指すときに ~/.shellrc.d へ戻らず何も読まずに 0 で終わる経路 (${VAR:-default} の既定値は空のときだけ効く) は未固定で、置き場所の決め方を書き換えるとフォールバックが紛れ込みうる。実測では何も出さず rc=0

手順: 1. rcdir (~/.shellrc.d) に a.sh (echo from-home) を置く
2. env={'DEVBASE_SHELLRC_DIR': str(tmp_path / 'missing')} (作らない) で _run('echo "rc=$?"', home) を実行する
3. stdout が 'rc=0\n' で from-home を含まず、stderr が空であることを比較する

R1-002 — containers/base/shellrc-dir.sh#__devbase_shellrc_dir

兆候・経路 手法・階層 重要度 提案元 状態 コミット
normal unit — claude 採用 1

なぜ: 実際の配置では entrypoint.sh が置き場所をアカウントグループのボリュームへの symlink にする (スクリプト冒頭のコメント) が、既存テストの置き場所はすべて実ディレクトリで、symlink の置き場所を辿って中の *.sh を読む代表経路が固定されていない。[ -d ] やグロブの書き方を変える構造改善で symlink を辿らなくなっても検出できない。実測では symlink 先の a.sh が読まれ rc=0

手順: 1. tmp_path / 'volume' に a.sh (echo read-volume) を置き、home / '.shellrc.d' をそこへの symlink として作る (rcdir フィクスチャは使わない)
2. 環境変数を与えずに _run('echo "rc=$?"', home) を実行する
3. stdout の行が ['read-volume', 'rc=0'] で stderr が空であることを比較する

R1-003 — containers/base/shellrc-dir.sh#__devbase_shellrc_dir_loader

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — kiro 採用 1

なぜ: failglob/dotglob の片方だけが on の状態で __devbase_shellrc_opts が単一トークンになり、その 1 つだけを復元する経路が固定されていない。既存テストは両方 on か両方 off のみ

手順: 1. rcdir に 10-a.sh(echo read-a)、20-noperm.sh(echo read-noperm)、30-b.sh(echo read-b)を置く
2. 20-noperm.sh を chmod 000 にして読めなくする
3. _run("") で source する
4. stdout が read-a, read-b の順、returncode が 0 であることを比較する(読めないファイルは飛ばし、後続は続く)

R1-004 — containers/base/shellrc-dir.sh#__devbase_shellrc_file

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude 採用 1

なぜ: ループ内の [ -f ] && [ -r ] の判定のうち、既存テストが通るのは『一致なしでグロブが文字列のまま残る』と『*.sh という名前のディレクトリ』だけで、読み取り権限の無い *.sh と、リンク先の無い symlink の *.sh を黙って飛ばし後続を読む経路は固定されていない。実測では chmod 000 の 15-u.sh とリンク切れの b.sh はどちらも何も出さずに飛ばされ、前後のファイルは読まれる

手順: 1. rcdir に 10-a.sh (echo read-a)、15-unreadable.sh (echo read-u、chmod 0o000)、17-dangling.sh (存在しないパスへの symlink)、20-b.sh (echo read-b) を置く
2. root では -r が常に真になるため、os.geteuid() == 0 のときは pytest.skip する (リンク切れの確認は root でも成立するので、必要なら 2 テストに分ける)
3. _run('echo "rc=$?"', home) を実行し、stdout の行が ['read-a', 'read-b', 'rc=0'] で stderr が空であることを比較する
4. 後片付けのため、テストの終わりに権限を 0o644 へ戻す

R1-005 — containers/base/shellrc-dir.sh#__devbase_shellrc_opts

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude 採用 1

なぜ: 利用者の glob 設定を控えて戻す分岐 (shopt -q failglob / shopt -q dotglob の 2 本) は、両方 on と両方 off の組み合わせでしか固定されていない。片方だけ on のとき控えの文字列に名前が 1 つだけ入り、引用符なしの shopt -s $__devbase_shellrc_opts で戻す経路は未固定で、控えの持ち方 (文字列・配列・連想配列) を変える構造改善でいちばん壊れやすい。実測では failglob=on/dotglob=off → fg=on/dg=off、failglob=off/dotglob=on → fg=off/dg=on がそのまま残る

手順: 1. 既存の test_glob_options_are_restored_before_reading の横に、before を 'shopt -s failglob; shopt -u dotglob' と 'shopt -u failglob; shopt -s dotglob' の 2 通りで parametrize するテストを足す
2. rcdir に SHOW を実行する 10-show.sh を置き、読み込み器の後でも SHOW を実行する
3. stdout の行が、読んでいる最中と読んだ後の両方で before の組み合わせどおり (例: ['fg=on','dg=off','fg=on','dg=off']) になることを比較する。stderr が空であることも見る

ラウンド 2(実装 kiro)

R2-001 — containers/base/shellrc-dir.sh#__devbase_shellrc_dir

兆候・経路 手法・階層 重要度 提案元 状態 コミット
boundary unit — claude 採用 1

なぜ: 置き場所のパスとファイル名に空白を含む入力が固定されていない。グロブ "$__devbase_shellrc_dir"/*.sh と "${__devbase_shellrc_files[@]}" の引用符が、配列や展開の書き換えで外れると単語分割で読まれなくなるが、既存テストは空白を含まないパスだけを使う(現状は空白入りのディレクトリ・ファイル名とも読まれ、stderr は空、終了状態 0 であることを確認済み)

手順: 1. tmp_path に空白を含むディレクトリ (例: 'a dir') を作り、その中に空白を含む名前の '10 x.sh' (echo read-space) と '20-b.sh' (echo read-b) を置く
2. DEVBASE_SHELLRC_DIR にそのディレクトリを渡し _run('echo "rc=$?"', home, env=...) で読み込み器を通す
3. stdout の行が ['read-space', 'read-b', 'rc=0'] で、stderr が空であることを比較する

R2-002 — containers/base/shellrc-dir.sh#__devbase_shellrc_files

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude 採用 1

なぜ: [ -f ] && [ -r ] の分岐のうち、実在するファイルを指す symlink の *.sh を読む経路が固定されていない。固定済みなのは指す先の無い symlink(読まない)と symlink のディレクトリ本体だけで、判定を -L や find 相当へ書き換えると実在の symlink ファイルを落としても検出できない(現状は symlink 先の内容が読まれることを確認済み)

手順: 1. 置き場所の外 (tmp_path) に echo read-target を書いた実ファイルを作る
2. rcdir に '20-link.sh' としてそのファイルへの symlink を張り、前後に '10-a.sh' (echo read-a) と '30-b.sh' (echo read-b) を置く
3. _run('', home) を実行し、stdout の行が ['read-a', 'read-target', 'read-b'] で stderr が空であることを比較する

R2-003 — containers/base/shellrc-dir.sh#source

兆候・経路 手法・階層 重要度 提案元 状態 コミット
normal integration — codex 採用 1

なぜ: 既存テストの読み込み先とファイル名は単純な名前だけであり、空白・グロブ文字を含む実ファイルのパスを分割・再展開せず source できる経路は固定されていない。実ファイルと Bash の読み込みのつなぎ目を対象とし、Docker は使わない。作業ディレクトリ内で現行ローダーを実行し、両ファイルの作用が名前順で呼び出し元シェルに残り、終了状態 0・標準エラー空となることを確認した。

手順: 1. tmp_path 配下に rc dir [x] というディレクトリを作り、DEVBASE_SHELLRC_DIR で指定する。
2. 10 first [a].sh に ORDER=first、20 second *.sh に ORDER="$ORDER second" を書く。
3. 既存の _run から公開入口であるローダー全体を source し、その直後の終了状態と ORDER を取得する。
4. 現行で観測した終了状態 0、ORDER の値 first second、標準エラー空を検証する。テスト用の値を比較し、実装テキストや表示メッセージは固定しない。

ラウンド 3(実装 claude)

(採用した改善項目なし)

見送った項目

ラウンド 対象 兆候・経路 理由
1 containers/base/shellrc-dir.sh#unset error 1 ラウンドの採用上限 5 件を超えた
3 tests/containers/test_shellrc_dir.py#test_unreadable_file_is_skipped_and_later_files_continue duplication 重要度 minor がしきい値 major 未満
3 tests/containers/test_shellrc_dir.py#test_option_set_by_a_file_is_kept duplication 重要度 minor がしきい値 major 未満
3 tests/containers/test_shellrc_dir.py#rcdir magic_value 重要度 minor がしきい値 major 未満
3 containers/base/shellrc-dir.sh#__devbase_shellrc_opts duplication 重要度 minor がしきい値 major 未満

takemi-ohama and others added 2 commits September 24, 2026 12:31
…llrc_dir

置き場所が別ディレクトリへの symlink のときに symlink 先の *.sh を読む
代表経路を現状固定する。実配置では entrypoint.sh が置き場所をアカウント
グループのボリュームへの symlink にするが、既存テストは実ディレクトリ
だけで、この経路が固定されていなかった。対象コードは変更しない。

Item-Id: R1-002
Round: 1
Impl-Runtime: kiro
Impl-Model: default
…llrc_dir_loader

読めないファイル (chmod 000) を -r の判定で飛ばし、後続のファイルを読み続けて
終了状態 0 で終える経路を現状固定テストで固定する。root は読めてしまうため飛ばす。

Item-Id: R1-003
Round: 1
Impl-Runtime: claude
Impl-Model: default
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
takemi-ohama and others added 5 commits September 24, 2026 12:36
Record silent skipping, continued loading, and successful loader status. Restore unreadable file permissions after the test and retain dangling-link coverage for root.

Item-Id: R1-004
Round: 1
Impl-Runtime: codex
Impl-Model: default
…_devbase_shellrc_opts

failglob/dotglob のどちらか一方だけ on のとき、控えの文字列に名前が
1 つだけ入り、引用符なしの shopt -s $__devbase_shellrc_opts で戻す経路を
現状固定する。読み込み中と読み込み後の両方で before の組み合わせが
そのまま残ることを比較し、stderr が空であることも確かめる。

Item-Id: R1-005
Round: 1
Impl-Runtime: kiro
Impl-Model: default
…iners/base/shellrc-dir.sh#__devbase_shellrc_dir

置き場所のパスとファイル名に空白を含む入力で、単語分割されずに名前順で
読まれ、stderr が空で終了状態 0 であることを現状固定する。

Item-Id: R2-001
Round: 2
Impl-Runtime: claude
Impl-Model: default
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fix the current behavior of reading an existing symlink target in filename order with no stderr output.

Item-Id: R2-002
Round: 2
Impl-Runtime: codex
Impl-Model: default
…e names — containers/base/shellrc-dir.sh#source

置き場所・ファイル名にグロブ文字 ([x]) と空白を含む実ファイルを DEVBASE_SHELLRC_DIR
で指定し、両ファイルの作用が名前の昇順で呼び出し元シェルに残り、終了状態 0・標準エラー
空になる経路を現状固定した。実装テキストや表示メッセージは固定しない。

Item-Id: R2-003
Round: 2
Impl-Runtime: kiro
Impl-Model: default

@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 | REQUEST_CHANGES

修正が必要な指摘は 1 件です。

Comment thread containers/base/shellrc-dir.sh Outdated

@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 | agy | APPROVE

PR #262 の現状固定テストの追加内容を確認し、問題ありません。

…-dir.sh

The saved option names were joined into one string and split unquoted on
restore, so with an IFS lacking a space (e.g. IFS=$'\n\t') shopt got one
bad word and both options stayed off. Keep each option in its own flag
variable and restore them one by one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | round 1 | commit 2bb114b

対応件数: critical=0 / major=0 / minor=1(合計 1 件)
決着: 1 件 / 見送り: 0 件 / 却下: 0 件
CI: SUCCESS

@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 2 | agy | APPROVE

PR #262 の変更内容および round 1 での修正(commit 2bb114b)を確認し、修正アクションを要する問題はありません。

@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 2 | kiro | APPROVE

failglob/dotglob の控えを 1 本の文字列 + 引用符なし分割から、オプションごとの独立フラグ変数 + 個別 shopt -s へ変更する修正。利用者の IFS に空白が無い場合 (IFS=$'\n\t' など) に控えが復元されず、旧コードでは stderr に invalid shell option name を出しつつ両オプションが off のまま残る不具合を解消している。修正は最小で正確、design doc も同期しており、新規回帰テスト (test_glob_options_are_restored_when_ifs_has_no_space) を含む 37 件が通過。旧コードで再現し新コードで解消することも確認した。修正を要する指摘は無し。

@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 3 | claude | APPROVE

round 3: 追加の修正提案なし(IFS に依存しない glob 設定の復元を含め、読み込み器・entrypoint・Dockerfile・文書の整合を確認。tests/containers/test_shellrc_dir.py 37 件通過)

@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 3 | kiro | REQUEST_CHANGES

PLAN70 のシェル設定置き場 ~/.shellrc.d に関する特性テスト群と、IFS 非依存で failglob/dotglob を控えて戻す修正 (2bb114b)。テストは全件 pass し、ローダー本体は空白・グロブ文字・symlink・読めないファイル・IFS 変更に対して堅牢であることを実測でも確認した。設計・正確性の面で追加の修正提案は無い。ドキュメントの誤りの記述だけ、実装(読めないファイルは無言でスキップ)と食い違うため 1 点だけ修正を提案する。

Comment thread docs/user/container-operations.md Outdated
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | commit cc8ea96

対応件数: critical=0 / major=0 / minor=0(合計 0 件)
決着: 1 件 / 見送り: 0 件 / 却下: 0 件
CI: NONE

@takemi-ohama
takemi-ohama marked this pull request as ready for review September 24, 2026 04:42
takemi-ohama and others added 2 commits September 24, 2026 18:57
…#253)

PLAN70 の要求・設計を issues/old/ へ移し、置き場所と環境変数の約束・読む先の
決め方・読むものと読む順・グロブの設定の控えと戻し(IFS に依らない)・黙って
飛ばすものと知らせるもの・伝播の規則・テスト観点を shellrc-dir.md として確定
仕様にした。利用者向けの小節から新しい仕様へリンクする。

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@takemi-ohama
takemi-ohama merged commit b612ae5 into main Sep 24, 2026
7 checks passed
@takemi-ohama
takemi-ohama deleted the feature/plan70-shellrc-dir branch September 24, 2026 10:26
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

振り返り(2026-09-24)

対象: issue #248 / issue #234 / issue #253、PR #263 / PR #264 / PR #262

3 本を 1 つのまとまりとして main へマージした(#263 → #264 → #262)。変更は次の 3 つ。

  • スナップショットの世代をアカウントグループごとの系列で持つ(PLAN68)
  • tmux のセッションを名指しで扱う tmux-go / tmux-peek / tmux-kill と prefix S のメニュー(PLAN69)
  • 作り直しても残るシェルの設定の置き場所 ~/.shellrc.d(PLAN70)

このリポジトリは検証チャネルを持たないため、main へのマージがそのまま配布にあたる。承認の範囲に従い、タグと GitHub Release は作っていない。

何が起きたか

観点 事実
手戻り(配布) 提示物は「#264 は #263 の後でも CLEAN」と見込んでいた。実際は、main の branch protection が strict: true のため、#263 のマージ後に #264 が BEHIND になり、gh pr merge に拒まれた。main の取り込みと CI 1 巡が追加で要った。#262 は見込みどおり CHANGELOG.md の [Unreleased] / ### Added だけが衝突し、shellcheck → tmux → ~/.shellrc.d の順で両方を残して解いた
実装レビュー #263・#262 は 4 者・3 ラウンド、#264 は 2 ラウンドで収束した。未解決のスレッドは 0 件
リリース後テスト(#263) main を更新した後の CLI で、読み取り側を確かめた。snapshot list は 3 世代を表示した。rotate --help は --keep(グループごと)と --max-total を出した。系列の積み先は with → 20260920-212546、default → 20260923-081407 で、グループの取り違えは無い。keep 3 / max 9 のローテーションの計画は 0 件。snapshot.yml は前後で変わっていない(md5 が一致)
見落とし(#263) 実環境での with → default の devbase up は踏めていない。利用者のコンテナを起こすため、利用者の操作待ちとした
リリース後テスト(#262・#264) devbase build base --no-cache の後、使い捨てのコンテナで確かめ、すべて通った。
- ~/.shellrc.d は /persistent/group/.shellrc.d を指す。DEVBASE_SHELLRC_DIR は非対話のシェルからも見える
- *.sh は名前の順に読まれ、ドットで始まるファイルと .sh 以外は読まれない。AI CLI の alias より後に読まれ、置き場所の定義が勝つ
- tmux-peek と tmux-kill は名前の完全一致で動き、実行中のセッションも落とせる。tmux-go -c は実行元の端末を移し、移り先に繋がっていた端末を外す(疑似端末 2 つで確認)
- prefix S のバインドは効いている
見落とし(#262・#264) 人が実際の端末で prefix S のメニューを操作する確認(#264 条件 15)と、amd64 での建て直し(手元は arm64 だけ)は未確認のまま
工程 飛ばした工程は無い。起点の 3 件は PR 本文の Closes でマージ時に閉じた

context window の大きさ

層 持ち場 モデル 件数 固定費の中央値 実作業の中央値 実作業 < 固定費 最大充填の最大 印
conductor - claude-opus-5-5 1 30775 76105 0 106880
supervisor 取り込み claude-opus-5-5 1 32474 87706 0 120180
supervisor 仕上げ claude-opus-5-5 1 33004 90012 0 123016
worker その他 claude-opus-5-5 3 24229 77708 0 116895
層 件数 固定費の合計 実作業の合計 総消費
conductor 1 30775 76105 106880
supervisor 2 65478 177718 243196
worker 3 72735 234005 306740
合計 6 168988 487828 656816
持ち場 supervisor supervisor の実作業 worker の件数 supervisor と worker の固定費の合計 印
取り込み 1 87706 3 105209 worker を使いすぎ
  • 取り込み(worker を使いすぎ): そのままにする。3 本の確定仕様化は互いに独立しており、3 つの worker で並べて進めたため所要が短く済んだ。固定費の増分(約 7 万)はその対価として許容する
  • 仕上げは worker を使わず、supervisor が直接進めた。マージ・CI の待ち・後片付けは順に進める作業で、並べて速くなる部分が無かったため

次に変えること

変えること 落とし先 状態
複数の Pull Request のマージ順を示す提示物で、branch protection の strict を読む。true なら 2 本目以降に「取り込み → push → CI → マージ」の段と待ち時間を見込む issue-plan-strategy / release の手順 devbasex/ai-plugins#976 として起票

途中で起票した課題

番号 何を見つけたか 見つけた場面
#255 snapshot restore の復元前バックアップが、実行した場所のグループのボリュームを控える 設計・実装中(#248)
#256 snapshot-guide の名前付き世代の記述が実装と合わない 設計・実装中(#248)
#259 entrypoint.sh・ai-cli-aliases.sh が ShellCheck の対象外で、既存の指摘が 8 件ある 実装中(#234)
#261 containers/lfm が AI CLI の起動定義と ~/.shellrc.d を継がない 実装中(#253)
#265 / #266 _ensure_env_files の長さ、アーカイブ名の組み立ての散在 構造改善(#263)
#267 引用符の無い created_at で snapshot list が TypeError になる 実装中(#263)
#269 rotate が危険な世代を一覧から外しただけのときに「ローテーション不要です」と出る 確定仕様化(#263)
devbasex/ai-plugins#976 マージ順の提示物が branch protection の strict を見込まない 配布(この振り返り)

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.

feat: コンテナを作り直しても残るシェルの設定の読み込み先(~/.shellrc.d/*.sh)を用意する

1 participant