Skip to content

release: v0.3.2 → v0.4.0(#50〜#59 を main へ)#60

Merged
sasagar merged 10 commits into
mainfrom
dev
Jul 5, 2026
Merged

release: v0.3.2 → v0.4.0(#50〜#59 を main へ)#60
sasagar merged 10 commits into
mainfrom
dev

Conversation

@sasagar

@sasagar sasagar commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

リリース内容(v0.3.2 以降、dev の 10 コミット)

release-please が feat: を検出して 0.3.2 → 0.4.0(マイナー)に上げる想定。

✨ 機能 (feat)

🐛 修正 (fix)

🧪 テスト / 雑務

検証

  • dev で app build & test(Swift 6.0)緑、実機(macOS 26.5)でメニュークラッシュ/フリーズ解消・ヘルプ・ビルド番号を確認済み。
  • マージ後、main への push で release-please が version/CHANGELOG/タグ (v0.4.0) を生成します。

sasagar added 10 commits July 4, 2026 15:22
設定 > 一般 に「アップデート」セクションを追加。GitHub Releases を見て新版の有無を知らせる
(署名/自動インストールは伴わない。将来 Sparkle へ昇格可能な形)。

- 現在バージョン表示/「起動時に確認する」トグル(既定 ON)/「今すぐ確認」ボタン+状態表示。
- 新版発見時は macOS 通知。バージョン比較はエンジン層 ReleaseVersion に集約し swift test で検証。

ultracode の adversarial レビュー(4 次元×各所見を反証検証)の指摘を反映:
- 通知の重複投函を防止(version ごとに一度だけ・UserDefaults で記録)。
- 初回起動の許可レース対策(未許可なら投函せず記録もしない→許可後の次回起動で通知)。
- html_url が無い/壊れていても .upToDate に誤判定せずリリース一覧へフォールバック。
- version 未取得時("0.0.0" で全リリースを新扱いする誤判定)を回避(読めなければ確認しない)。
- 起動時チェックを 6h throttle(GitHub 未認証レート制限の連打を回避)。
- repo スラッグを GitHubRepo に一元化(ChangelogView との重複解消)。
- 通知投函を AgentNotifier に集約(UpdateChecker 直投函の重複解消)。

swift test 58 passed / app build 警告0。
* feat: メイン上部に org 付きリポジトリ名+色を表示し、サイドバー選択を指定色に

- メイン上部バーに org 付きリポジトリ名(session.repoName = 例: Love-Rox/labolabo)と、
  サイドバーと同じリポジトリ色ドットを表示。session 名が repo フォルダ名と異なるとき
  (worktree セッション等)のみ session 名を併記。
- サイドバーの選択ハイライトを macOS 既定の青ではなく**リポジトリ指定色**に変更。
  List のシステム選択ハイライトは使わず onTapGesture で選択し、選択行を repo 色(枠線+
  塗り)で強調。非選択行は従来どおり淡い repo 色タイント。

app build 警告0。※選択・色の見た目は実機確認推奨。副作用: List のキーボード行移動は不可に。

* fix: サイドバー選択のキーボード移動を維持+ヘッダー色を塗り/枠タグ化+ウィンドウ位置記憶

フィードバック反映:
- サイドバー選択を List(selection:) に戻し、キーボード行移動(↑↓)を維持。選択色は
  .tint(選択中リポジトリの色・未割り当ては既定アクセント)で寄せる。
- メイン上部のリポジトリ色表現を丸ドットから、塗り+枠線の色タグ(org/repo 名)に変更。
- 複数モニタでのウィンドウ位置/サイズ記憶を NSWindow の frameAutosave で有効化
  (WindowAccessor をウィンドウに attach)。

app build 警告0。

* fix: ⌘Q が効かない(埋め込み端末が cmd+q を握る)をローカルモニタで解消

libghostty 端末がフォーカス時に cmd+q(ghostty のキーバインド)を消費し、メニューの
Quit までイベントが届かないため ⌘Q でアプリが終了しなかった。NSEvent のローカル
keyDown モニタで ⌘Q を端末より先に横取りし NSApp.terminate する(他の修飾キー併用は対象外)。

* fix: 複数モニタでウィンドウ位置が復元されない問題を自前 frame 保存/復元で解消

frameAutosave は起動時の SwiftUI 再配置(メインモニタへ)が move を誘発して外部モニタの
保存位置を上書きしてしまい、複数モニタで位置が記憶されなかった。自前で UserDefaults へ
frame を保存/復元する方式に変更:
- isRestorable=false でシステム/SwiftUI 復元を無効化。
- 復元は起動直後+0.2s 後にも再適用(SwiftUI の再配置に上書き勝ち)。
- 保存は 0.6s 後(起動時の再配置を保存しない)から didMove/didResize で行う。

あわせて ⌘Q モニタの NSApp.terminate を MainActor.assumeIsolated 化して警告解消。
メニューバーのメニューを開くと AppKit が「サイドバーを表示/隠す」項目(toggleSidebar:)を
検証する際、NavigationSplitView のサイドバー NSSplitView の respondsToSelector: が
17万回超の無限再帰を起こしてスタックオーバーフローで落ちる macOS の不具合があった
(クラッシュログのレジスタに toggleSidebar: セレクタが残存)。

CommandGroup(replacing: .sidebar) {} で当該メニュー項目を撤去(サイドバー開閉は自前ボタンで
行っており元々不要)。Help/View メニューを開いてもクラッシュしないことを実機で確認。
一連の UI を日英対応にする第一歩。既存の日本語をソースにした String Catalog に英訳を追加。

- app/project.yml: developmentLanguage=ja、SWIFT_EMIT_LOC_STRINGS=YES。
- Localizable.xcstrings(sourceLanguage=ja)に UI 文字列 166 キー+英訳を追加。
  SwiftUI リテラル(Text/Button/Label/.help/Toggle/Picker/Section/alert 等)**110 件は
  コード変更なし**で英語システム時に英語表示される。ビルドで en.lproj/Localizable.strings 生成を確認。
- 残る plain String 56 件(通知・計算 help・エラー・ペイン名等)は次 PR で String(localized:) 化。

抽出+英訳は ultracode(6 グループ並列・型から printf format 指定子を推定)で作成。
* fix: メニューを開くと落ちる macOS 26 の NSSplitView 無限再帰を根治

#52 の CommandGroup(replacing: .sidebar) はサイドバー開閉のメニュー項目を消すだけで、
クラッシュは解消していなかった(Help など任意のメニューを開くと再発)。

真因: メニューを開くと AppKit が項目検証で responder chain を辿り
(-[NSApplication targetForAction:to:from:] → _objectFromResponderChainWhichRespondsToAction)、
NavigationSplitView のサイドバー NSSplitView に respondsToSelector: を送る。macOS 26.5 の
-[NSSplitView(NSSplitViewSidebar) respondsToSelector:] が弱参照経由で自分自身へ転送して
無限再帰し、スタックを溢れさせて EXC_BAD_ACCESS でクラッシュする。項目種別に依らないので
CommandGroup 撤去では防げない。

対策: -[NSSplitView respondsToSelector:] を swizzle し、同一オブジェクトへの再入を検出したら
元実装を再帰させず class_respondsToSelector で素の応答可否を返して循環を断ち切る
(非循環時は元実装のままなので挙動不変)。AppEntry.main() で UI 構築前に install。

検証: macOS 26.5 実機で、修正前ビルド(同一 UUID)は Help を開くとクラッシュ(.ips 確認)。
修正後ビルドは Help/View/アプリメニュー(Services)を開いても生存・新規クラッシュなしを確認。

* fix: メニュークラッシュ対策を自動検証の無効化に変更+メニューバーを整備

先の respondsToSelector swizzle はクラッシュをハング(ビーチボール)に化けさせていた
(サンプルで確定: _sendMenuEnableItems → -[NSSplitView(NSSplitViewSidebar)
validateUserInterfaceItem:] が長大ループ)。個別メソッドの swizzle は whack-a-mole なので、
真因である**メニュー項目の自動検証**そのものを無効化する方式へ変更(NSMenu.autoenablesItems
= false を起動時+メニュー追跡開始ごとにメインメニュー全体へ適用)。実機 macOS 26.5 で
クラッシュ・ハングともに解消を確認。

あわせてメニューバーを整理:
- NSWindow.allowsAutomaticWindowTabbing = false で、無関係なウインドウタブ項目
  (表示>タブバー、ウインドウ>前/次のタブ・ウインドウ結合 等)を一掃。
- 既定の無意味な「LaboLabo ヘルプ」を実用導線へ差し替え(GitHub を開く/リリースノート/
  問題を報告…)。GitHubRepo に homeURL / newIssuePage を追加、日英 3 キーを追加。

副作用(autoenablesItems=false により一部標準項目が常に有効表示)は、上記整理で
無関係項目を減らして軽減。
Text/Button など SwiftUI 引数は自動ローカライズされるが、var/return/通知 content/
PaneItem title などの平文 String は対象外のため String(localized:) でラップして
String Catalog 経由の英語化を有効にする。FileListMode の enum 生値はコンパイル時
定数でラップできないため、表示用の label(switch で String(localized:))を追加し
表示側を rawValue から label に切替。
* test: 包括的テスト一式(エンジン単体・アプリ単体・UIスモーク)と CI 追加

エンジン単体(swift test に追加、いずれも実行確認済み):
- AgentStatus.from(hookEvent:) の全マッピング/未知イベント
- ToolLocator.locate(実在バイナリ解決・不在→nil・危険文字で非クラッシュ)
- AgentStatusBus の AF_UNIX ソケット往復(受信→AgentStatus 変換、不正JSON無視)
- ProcessRunner.runSync(stdout/stderr/exit/timeout/cwd/env)

アプリ単体(新ターゲット LaboLaboAppTests, @testable import LaboLabo):
- GitHubRepo の URL 構築、ErrorMessage.sessionUIMessage の分岐
- 表示ラベル(FileListMode/FileViewMode/AppIconMode/AgentStatus/RepoPalette)
- PaneTilingModel の split/add/close/swap/snapshot 復元など純ツリーロジック

UI スモーク(新ターゲット LaboLaboUITests, XCUITest):
- 起動+各メニュー開閉でクラッシュしないこと(toggleSidebar 無限再帰の退行検知)

project.yml に 2 テストターゲット+scheme 配線。CI に app-tests ジョブを追加
(build-for-testing → アプリ単体=ブロッキング → UIスモーク=informational)。
UIスモークはローカルではランナーの自動化権限でハングするため CI 実行を前提とし、
安定を確認するまで continue-on-error にしている。

検証: swift test 88 / アプリ単体 39 = 127 パス(0 失敗)。

* fix: 通知許可状態の取得を継続ベースにし Xcode 16 SDK でビルドを通す

Xcode 16 の SDK では UNUserNotificationCenter.notificationSettings() の async 版が
非 Sendable な UNNotificationSettings を返すため、@mainactor の AgentNotifier から
await すると隔離境界をまたいで送れずコンパイルエラーになる(新設の app-tests CI ジョブ
= Xcode 16.4 で検出。ローカルの Xcode 26 SDK では当該型が注釈済みで顕在化しなかった)。
getNotificationSettings 完了ハンドラ版に切替え、Sendable な UNAuthorizationStatus
だけを継続へ渡すことで両 SDK でビルドできるようにする。

* fix: usage 反映を @mainactor セッター経由にし Swift 6.0 の sending-self 判定を回避

Xcode 16.4 の Swift 6.0 は region-based isolation 解析が Xcode 26 の Swift 6.2 より
保守的で、detached タスク内の MainActor.run { self?.usage = parsed } を「sending self
risks data races」で拒否する。@mainactor 隔離の applyUsage(_:) を self? に対して呼ぶ形へ
変更(self をクロージャへ送らず、Sendable な AgentUsage のみ渡す)。

* fix: ホスト型ユニットテスト時は最小シーンで起動しヘッドレス CI のクラッシュを回避

LaboLaboAppTests はアプリを起動してテストバンドルを注入するホスト型のため、起動時に
ContentView が libghostty/Metal 端末サーフェスを生成する。ヘッドレスの CI ランナーでは
これがクラッシュし「Early unexpected exit ... Crash: LaboLabo」でテストが失敗する。
XCTestConfigurationFilePath が設定されているとき(=ホスト型ユニットテスト)だけ最小の
TestHostApp を起動するよう分岐し、@testable import 対象のシンボルは維持したまま重い UI を
立てない。UI スモーク(XCUITest)は別プロセスで実アプリを起動するため影響しない。
ローカル: アプリ単体 39/39 パス。
Config/Version.xcconfig のコメントには「archive 時に git rev-list --count HEAD を
CFBundleVersion へ注入」とあったが、その注入が未実装で常に CURRENT_PROJECT_VERSION=1
のフォールバックが入っていた(標準 About パネル・設定「現在のバージョン」・Changelog が
すべて v0.3.2 (1) 表示)。

app/project.yml の LaboLabo ターゲットに postBuildScripts を追加し、GENERATE_INFOPLIST_FILE
が生成した最終 Info.plist の CFBundleVersion を PlistBuddy で git コミット数へ上書きする
(Debug/Release/archive すべてに反映)。ローカル確認: CFBundleVersion=1 → 44。
.github/ISSUE_TEMPLATE/ に YAML issue form を用意:
- バグ報告 / Bug Report、機能リクエスト / Feature Request(日英4種)
- config.yml: blank_issues_enabled: true(アプリ内「🐞 バグを報告」の
  issues/new?body=... プリフィルリンクを弾かないため)+リリースへの導線

バグ報告フォームはアプリが自動添付する環境情報(バージョン/macOS/ツール診断)や
クラッシュ/フリーズ採取手順(.ips / sample)と整合させている。
サーバーを持たない本アプリでは「バグ報告 = プリフィルした GitHub Issue をブラウザで開く」。
BugReportSheet を追加し、タイトル・内容を入力すると環境情報(アプリ版+ビルド番号・macOS 版・
git/gh/claude のツール診断)を折りたたみ <details> ブロックで本文へ自動添付する。

- 「GitHub で Issue を作成」→ GitHubRepo.newIssueURL(title:body:)(URLComponents で
  正しくパーセントエンコード、+ のみ %2B に補正)を NSWorkspace で開く。
- 「内容をコピー」→ 本文を NSPasteboard へ(ブラウザに頼らない導線)。
- 環境情報は起動時診断のみなので、シート内に「再検査」(ToolDoctor.check)を用意。
- 導線: サイドバーヘッダに ladybug ボタン(変更履歴の ⓘ はワンクリックのまま維持)+
  設定に「フィードバック > バグを報告…」。
- 文言は String Catalog に日英 12 キーを追加(既存キーは再利用)。

検証: ビルド成功、en.lproj に新規12キーの英訳を確認、newIssueURL の
+/&/#/空白/改行エンコードを実機ロジックで確認。
@sasagar sasagar merged commit 656782a into main Jul 5, 2026
7 of 11 checks passed
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.

1 participant