Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
- `CONTEXT.md` — AI エージェント指示の層(規範フラグメント・グローバル / プロジェクト AGENTS.md・SOUL.md・CLAUDE.local.md・channel prompt)を区別する用語集
- `aliases` — alias 定義の SSOT(root 直下、`~/.aliases` にシンボリックリンク)。旧 `nix/modules/home/zsh.nix` の `shellAliases` から移行(`setup/link.zsh` が配置、Tier 1)
- `scripts/` — 外部シェルスクリプト(`aliases` の alias から呼び出される。旧 `aliase/` から改名)
- `setup/` — Tier 1(リアルタイム symlink)・Tier 2(明示的スクリプト実行)・Tier 3(カットオーバー・ロールバック)の実装。`darwin-rebuild switch` を使わず、`zsh setup/link.zsh` で dotfiles を配置し(Tier 1)、`setup/languages.zsh`(mise+corepack)/`setup/defaults.zsh`(macOS defaults・IME)/`setup/pam.zsh`(Touch ID for sudo)/`setup/claude-sync.zsh`(skills clone・plugin sync・MCP merge)/`setup/codex-sync.zsh`(config.toml seed-if-absent)を個別実行する(Tier 2)。既存 PC を home-manager 込みの旧構成から移行する場合は `setup/cutover.zsh`(pre-flight build 確認 + `darwin-rebuild switch`)/`setup/rollback.zsh`(`.before-nix` 衝突検出付きロールバック)を使う(Tier 3)。**実機での実行は `setup/migrate.zsh` が唯一のエントリポイント**(`--dry-run`/`--apply`。Tier 1/2/3 を依存順(Phase 1: link → Phase 2: cutover/pam [root] → Phase 3: languages/defaults/claude-sync/codex-sync)で実行し、`~/.dotfiles-migrate/manifest.log` で部分適用を検出・再開する。fail-closed、rollback.zsh は自動では呼ばない)。個別スクリプトの直接実行はメンテナンス目的のみ。詳細は `setup/README.md` と `docs/superpowers/specs/2026-08-21-restore-script-management-inventory.md`・`docs/superpowers/specs/2026-08-22-restore-script-management-tier3-cutover-design.md`・`docs/superpowers/specs/2026-08-22-migrate-orchestrator-recovery-plan.md` を参照
- `setup/` — Tier 1(リアルタイム symlink)・Tier 2(明示的スクリプト実行)・Tier 3(カットオーバー・ロールバック)の実装。`darwin-rebuild switch` を使わず、`zsh setup/link.zsh` で dotfiles を配置し(Tier 1)、`setup/languages.zsh`(mise による言語ランタイム + corepack + バージョン固定 CLI)/`setup/defaults.zsh`(macOS defaults・IME)/`setup/pam.zsh`(Touch ID for sudo)/`setup/claude-sync.zsh`(skills clone・plugin sync・MCP merge)/`setup/codex-sync.zsh`(config.toml seed-if-absent)を個別実行する(Tier 2)。既存 PC を home-manager 込みの旧構成から移行する場合は `setup/cutover.zsh`(pre-flight build 確認 + `darwin-rebuild switch`)/`setup/rollback.zsh`(`.before-nix` 衝突検出付きロールバック)を使う(Tier 3)。**実機での実行は `setup/migrate.zsh` が唯一のエントリポイント**(`--dry-run`/`--apply`。Tier 1/2/3 を依存順(Phase 1: link → Phase 2: cutover/pam [root] → Phase 3: languages/defaults/claude-sync/codex-sync)で実行し、`~/.dotfiles-migrate/manifest.log` で部分適用を検出・再開する。fail-closed、rollback.zsh は自動では呼ばない)。個別スクリプトの直接実行はメンテナンス目的のみ。詳細は `setup/README.md` と `docs/superpowers/specs/2026-08-21-restore-script-management-inventory.md`・`docs/superpowers/specs/2026-08-22-restore-script-management-tier3-cutover-design.md`・`docs/superpowers/specs/2026-08-22-migrate-orchestrator-recovery-plan.md` を参照
- `claude/` — Claude Code 設定(`~/.claude/` にシンボリックリンク)
- `claude/rules/` — 全 AI エージェント向けグローバル指示のフラグメント(SSOT)。`core` / `worker` / `orchestrator` / `hermes-identity` の 4 ファイルを `scripts/build-agent-rules.zsh`(旧 `aliase/build-agent-rules.zsh`)が結合して生成物を作る
- `claude/hermes/SOUL.md` — Hermes Agent 用グローバル指示の生成物(`~/.hermes/SOUL.md` にシンボリックリンク)。直接編集しない
Expand Down Expand Up @@ -42,6 +42,7 @@
- 既存のパッケージのみを対象とする。ユーザーが明示的に依頼していないパッケージを追加しない
- `taps` / `brews` / `casks` / `masApps` の区分を守る
- CLI tool は Homebrew (`homebrew.nix` の `brews`) で管理する(Tier 3 で home-manager の `packages.nix` から完全移行済み)
- 例外として、**バージョンを固定する必要がある CLI tool だけは mise で供給する**(`setup/languages.zsh`、Tier 2)。Homebrew formula は任意バージョンの pin を表現できず、nix-darwin の `homebrew.brews` にも version フィールドが無いため、宣言的に版を固定できる経路が mise しかないことによる。現状の対象は standalone `dolt`(beads が要求する 2.2.0)。Homebrew が同名 formula を他パッケージの依存として引き込んでいてもそれは削除せず、PATH 先頭を mise が取ることで実行体だけを mise 側に寄せる(non-interactive shell は `zshenv` の `mise activate --shims`、interactive shell は `zshrc` の `mise activate zsh` が `brew shellenv` の後に走ることによる)
- PC ローカル専用の cask は `~/.config/dotfiles/homebrew.local.nix`(リポジトリ外配置)で declarative に宣言する。`homebrew.nix` が絶対パスで `builtins.pathExists` + `import` する。用途は「git に追跡させたくないが `default` role の zap から守りたい cask」(例: 特定アカウントの個人用ツール、業務用アプリ)。別 PC では復元されないため、再現性が必要なものは `homebrew.nix` 本体に書くこと。現状 casks のみ対応(brews / taps / masApps の overlay が必要になったら `homebrew.nix` の `local` 解決を拡張する)。nix flake は git tree のみコピーするため、`.gitignore` で除外したリポジトリ内ファイルは flake から不可視になる点に注意(リポジトリ外配置を選んでいる理由)

# zsh スクリプト規約
Expand Down
42 changes: 33 additions & 9 deletions setup/languages.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
# setup/languages.zsh
#
# Tier 2: mise で言語ランタイム (node/go/ruby/rust/python/dart) を install し、
# mise 管理下の node に対して corepack を有効化する (pnpm/yarn グローバル供給)。
# mise 管理下の node に対して corepack を有効化し (pnpm/yarn グローバル供給)、
# バージョンを固定する必要がある CLI tool を mise で供給する。
#
# 旧 setup/install/{04_node,05_go,06_ruby,07_rust,08_python,09_dart}.zsh
# (Nix 移行で削除済み)の役割を復元する。node だけ `lts` を使う理由は corepack 同梱版の
# 安定性を優先するため。他言語は旧スクリプトの `@latest` 慣行をそのまま復元する。
#
# ここで宣言するものはすべて `mise use --global` なので role (default / sub-1) に依らず
# 共通に効く。role 別の出し分けが要るものは Homebrew (homebrew.nix) 側で宣言すること。
#
# 前提: `mise` は Homebrew (nix/modules/darwin/homebrew.nix の coreBrews) で導入される。
# このスクリプトはパッケージマネージャを呼ばない (mise 自体の install は担当しない)。
#
Expand All @@ -34,17 +38,18 @@ fi

util::info "=== Tier 2: 言語ランタイム install (mise) ==="

# mise::pin <lang> <version>
# mise install <lang>@<version> → mise use --global <lang>@<version> の順で呼ぶ
# mise::pin <tool> <version>
# mise install <tool>@<version> → mise use --global <tool>@<version> の順で呼ぶ。
# <tool> には backend 接頭辞付きの指定 (例: aqua:dolthub/dolt) もそのまま渡せる。
mise::pin() {
local lang="${1}"
local tool="${1}"
local version="${2}"

util::action "${lang}@${version} を install"
mise install "${lang}@${version}"
util::action "${tool}@${version} を install"
mise install "${tool}@${version}"

util::action "${lang}@${version} を --global に設定"
mise use --global "${lang}@${version}"
util::action "${tool}@${version} を --global に設定"
mise use --global "${tool}@${version}"
}

mise::pin node lts
Expand Down Expand Up @@ -74,4 +79,23 @@ local corepack_install_dir="${HOME}/.local/share/corepack/bin"
mkdir -p "${corepack_install_dir}"
"${corepack_bin}" enable --install-directory "${corepack_install_dir}"

util::info "=== Tier 2: 言語ランタイム install 完了 ==="
# ---- バージョン固定 CLI --------------------------------------------------------
# 版を固定する必要がある CLI tool だけは Homebrew ではなく mise で供給する。Homebrew
# formula は任意バージョンの pin を表現できず (`dolt@2.2` のような versioned formula は
# 存在しない)、nix-darwin の homebrew.brews にも version フィールドが無いため、宣言的に
# 版を固定できる経路が mise しかないことによる。
#
# dolt: beads の server / shared-server モードは PATH 上の standalone `dolt` を
# exec.LookPath で解決する。beads は 2.2.0 を pin しており、2.3.0/2.3.1 は
# CALL DOLT_RESET('--hard') が新規 DB の数 % で恒久破損する回帰を持つ (upstream 実測:
# 2.2.0 0/60、2.3.0 3/60、2.3.1 3/100)。Homebrew の `beads` formula が依存として引き込む
# dolt 2.3.x は削除しない (beads の依存なので zap 対象外)。実行体が mise 側に寄るのは
# PATH 順序による:
# - non-interactive shell (beads が spawn する dolt sql-server はこちら): zshenv の
# `mise activate --shims` が shims を PATH 先頭に置き、`brew shellenv` は走らない
# - interactive shell: zshrc の `mise activate zsh` が `brew shellenv` より後に走る
util::info "=== Tier 2: バージョン固定 CLI install (mise) ==="

mise::pin aqua:dolthub/dolt 2.2.0

util::info "=== Tier 2: 言語ランタイム / バージョン固定 CLI install 完了 ==="
39 changes: 39 additions & 0 deletions setup/tests/languages.bats
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# setup/tests/languages.bats

SETUP_DIR="$(cd "$(dirname "${BATS_TEST_FILENAME}")/.." && pwd)"
REPO_ROOT="$(cd "${SETUP_DIR}/.." && pwd)"

# stub `mise` executable that records every invocation to MISE_LOG.
# `mise which node` returns a fixed path under a stub node bin dir that also
Expand Down Expand Up @@ -84,6 +85,44 @@ setup() {
[[ "${output}" == *"enable --install-directory ${HOME}/.local/share/corepack/bin"* ]]
}

@test "languages.zsh pins the standalone dolt CLI to 2.2.0 globally via mise's aqua backend" {
PATH="${STUB_BIN}:${PATH}" run zsh "${SETUP_DIR}/languages.zsh"
[ "${status}" -eq 0 ]

run cat "${MISE_LOG}"
[[ "${output}" == *"install aqua:dolthub/dolt@2.2.0"* ]]
# --global (not --local / --path): the pin must apply for both the default
# and sub-1 roles, neither of which languages.zsh branches on.
[[ "${output}" == *"use --global aqua:dolthub/dolt@2.2.0"* ]]
# 2.3.0/2.3.1 permanently break CALL DOLT_RESET('--hard') on a few percent
# of freshly created databases, which is the whole reason this pin exists.
# Raising it to 2.3.x would silently reintroduce that regression.
[[ "${output}" != *"dolthub/dolt@2.3"* ]]
}

@test "the shell config keeps mise ahead of Homebrew on PATH, so the pinned dolt is the one beads runs" {
# Homebrew's `beads` formula depends on an unversioned `dolt`, so
# /opt/homebrew/bin/dolt exists (2.3.x today) and is deliberately left in
# place. beads resolves the binary with exec.LookPath("dolt"), so which one
# actually runs is decided purely by PATH order, on two separate paths.

# Non-interactive shells -- which is how beads spawns `dolt sql-server` --
# only ever read zshenv, and `brew shellenv` never runs there. The shims
# activation is what puts the mise-managed dolt first.
run grep -c 'mise activate --shims' "${REPO_ROOT}/zshenv"
[ "${status}" -eq 0 ]

# Interactive shells additionally run zshrc, where `brew shellenv` prepends
# /opt/homebrew/bin. `mise activate` must come afterwards to win it back;
# swapping these two lines would silently hand over the regressed 2.3.x.
local brew_line mise_line
brew_line=$(grep -n 'brew shellenv' "${REPO_ROOT}/zshrc" | head -1 | cut -d: -f1)
mise_line=$(grep -n 'mise activate' "${REPO_ROOT}/zshrc" | head -1 | cut -d: -f1)
[ -n "${brew_line}" ]
[ -n "${mise_line}" ]
[ "${mise_line}" -gt "${brew_line}" ]
}

@test "languages.zsh fails clearly when mise is not on PATH" {
HOMEBREW_PATH_PREFIX_OVERRIDE="${BATS_TEST_TMPDIR}/no-mise-here" PATH="/usr/bin:/bin" \
run zsh "${SETUP_DIR}/languages.zsh"
Expand Down
Loading