Conversation
左ペインの種別ドットは primary/ordinary を出し分ける設計だったが、primary は 常に false でデッドコードと化し、primary はルート行 `⌂` でも示すため意味がなかった。 この死んだ枠を、セッションを最後に触ってからの経過時間で塗り分ける鮮度ドットに転用する。 - 15分以内 `●`(緑) / 4時間以内 `◐` / 4時間超 `○`(淡色)。ルート行は `⌂`。 - 「触る」= 切替・在席でアクティブにする / 端末・Agent の活動を観測。 - SessionRecord.last_active(Option, serde default で後方互換)を追加。未設定なら created_at にフォールバック。 - bump はインメモリ(enter_focus / apply_badges の活動変化)で行い、hot path に I/O を置かない。 終了時に persist_last_active で state.json へ一括フラッシュし、再起動でも鮮度を保つ。 - heat_of / kind_dot は純関数として単体テスト、描画側は内部で now を読む。 - カバレッジ 100% 維持。document/design/05-home.md・data/02-workspace.md を更新。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📊 Test Coverage
🎉✨ パーフェクト!全ファイル Lines カバレッジ 100% を達成しました 🏆🐰 |
Merged
kkyosuke
added a commit
that referenced
this pull request
Jun 27, 2026
## 目的 `usagi` の **v1.4.0** をリリースする。`Cargo.toml` の `version` を `1.3.0` → `1.4.0` に上げ、マージ後に `auto-release.yml` が `v1.4.0` タグと GitHub Release を自動生成する。 ## 変更内容 - `Cargo.toml` / `Cargo.lock` の version を `1.4.0` に更新(version のみ)。 ### v1.3.0 以降の主な変更(マージ済み) TUI / セッション周りの機能追加・改善が中心。 - **TUI 機能追加** - セッション一覧の種別ドットを鮮度(heat)ドットに転用 (#412) - 没入モードのキー方式を設定で切替可能に(Ctrl-O prefix / Alt)(#411) - サイドメニューにメモ・更新時刻・ahead/behind を表示 (#410) - サイドバーのうさぎを操作に反応させる (#408) / 終了時のエンゲージメント段階を復帰 (#368) - issue graph / gantt をフルサイズのモーダルで表示 (#403) / graph に状態グリフ表示 (#404) - セッション削除モーダルを overlay 表示に (#405) - preview のコードブロックを syntect でハイライト (#391) - サイドバーに既定ブランチとの差分バッジ +N -M を表示 (#389) - `?` でキーバインドのチートシートを表示 (#393) / man ヘルプを大きいモーダルで表示 (#374) - 入力待ち(◆)セッションを先頭へ寄せる並び替えトグル(s) (#390) / 切替モードで K/J による並び替え (#372) - **セッション / エージェント** - セッションのブランチを `usagi/<name>` に名前空間化 (#407) - 起動した Agent をセッション worktree に閉じ込める (#392) - **doctor** - `doctor --fix` で Nerd Font をダウンロード導入 (#409) - **バグ修正 / 安全性** - 依存ツリーの非有界再帰でスタックオーバーフローを防ぐ (#400) - JSON-RPC id 欠落・入力契約の不一致を修正 (#399) - ollama 出力の read エラー伝播とデッドロック回避 (#398) - リソースリーク・非有界入力を塞ぐ (#397) / 進捗計算をオーバーフロー安全に (#362) - ログ追記の原子化・config 編集での設定喪失防止 (#396) / 並行更新のロストをストアロックで防止 (#394) - 破壊的な worktree 削除と孤立ブランチを安全化 (#395) - **パフォーマンス / リファクタ** - 端末ペインのメモリと多数セッション時の描画負荷を削減 (#402) ほか perf 改善 (#401, #388, #382) - TUI モジュール構成の整理・カバレッジ対象の整理など複数のリファクタ ## テスト・確認方法 - `cargo fmt` / `cargo clippy --all-targets -- -D warnings` / `cargo test`(pre-push フックで clippy・test がパス済み)。 - マージ後、`auto-release.yml` が version 変更を検知し `release.yml` を起動 → 4 プラットフォームのバイナリビルドと `v1.4.0` Release が自動生成されることを確認する。 Co-authored-by: test <test@example.com>
kkyosuke
pushed a commit
that referenced
this pull request
Jun 27, 2026
main の大きなサイドバー変更(#430 リソース行で 3 行化・#428 詳細行の固定桁化・ #426 左ペインのクリック選択)にコンフリクトを解消しつつ追従し、PR バッジ機能を 複数 PR 対応に拡張する。 - 表示: PR バッジを line-2 の固定桁クラスタ(`DetailCols`)に `#N` セルとして統合。 セッションが複数 PR を持つときは `#412 #98` のように全部並べ、桁は描画ごとに最大値で固定。 - データ: `WorktreeState.pr` を `Option<PrLink>` → `Vec<PrLink>` に。`PrLink::aggregate` は 全 worktree の PR を URL 単位で重複排除して集約。 - 検出: `link::pr_link`(単一)→ `pr_links`(画面上の全 PR を重複排除して収集)。 - 保存: `pr_link_store` は `set`(置換)→ `add`(URL 単位で蓄積)/ `get -> Vec`。 没入の出力スキャンで `add`、`sync` が session root キーで読み戻し `state.json` に永続化。 - クリック: `sidebar_pr_link_at` → `sidebar_pr_links_at`(Vec)。没入中に行クリックで そのセッションの全 PR をブラウザで開く。 - ドキュメント(design/05-home.md・data/02-workspace.md・02-architecture.md)を更新。 cargo fmt / clippy / test 通過、カバレッジ lines・functions 100%。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kkyosuke
added a commit
that referenced
this pull request
Jun 27, 2026
## 目的 セッションに紐づく **Pull Request** をホーム画面の左サイドメニューから一目で分かるようにし、`#N` を**クリックするとブラウザで PR を開く**。PR 番号は GitHub に問い合わせず、**AI が返信に出力した PR URL を既存のリンク検出で拾って**得る。 ## 表示のされ方(PR バッジ) セッション行の **2 行目の右端**に `#N` を **青・下線**でリンク風に表示する。**複数 PR を持つセッションは `#412 #98` のように全部**並ぶ。 ```text ▎ ● main pushed ← 1行目: 鮮度ドット + 名前 + status ▶ running +124 -18 #412 #98 ← 2行目: Agent状態(左) / 更新時刻・↑N↓M・差分バッジ・#N…(右端の固定桁クラスタ) CPU 8% MEM 120MB ← 3行目: リソース使用量(live なセッションのみ・main 由来) ``` - main の新レイアウト(固定桁クラスタ `DetailCols`・3 行化)に合わせ、PR を **固定桁の `#N` セル**として統合。桁幅は描画ごとに表示中セッションの最大値で決まり、行ごとに揃う。差分バッジと並んで右端に最優先で残す。 - **クリックで開く**のは**没入(Attached)中・フル幅サイドバー**。`#N` を出している行をクリックすると、その**セッションの全 PR** を既定ブラウザで開く(AI 返信 URL のクリックと同じ起動経路)。レール/没入以外のモードは表示のみ。 ## 仕組み - **検出**: `link::pr_links` が画面上の `…/pull/<N>`(GitHub / GHE)を**全部・URL 単位で重複排除**して収集(`parse_pr_url`)。 - **永続化**: `pr_link_store`(`~/.usagi/pr-links/`)に **URL 単位で蓄積**し、セッション再同期で `state.json` の `WorktreeState.pr`(配列)へ畳み込む。一度きりの URL でもバッジは**再起動後も残る**。 - **集約**: 複数リポジトリに跨るセッションは全 worktree の PR を重複排除して並べる。 ## テスト・確認方法 - `cargo fmt` / `cargo clippy --all-targets -- -D warnings` / `cargo test`(2221 件)通過。 - カバレッジ強制(lines・functions 100%)通過。 - ユニットテスト: PR URL のパース・画面走査(複数収集・重複排除・wrap 行)、`pr_link_store` の蓄積/重複排除/worktree 照合、`WorktreeState.pr`(配列)の round-trip と集約、`pr_cell`/`pr_width`/`detail_cols` の複数バッジ桁揃え、`sidebar_pr_links_at` の行/列ヒット・Rail で空・body 外、`sync` がストアの PR 群を反映し永続化すること。 - 手動: 没入中に AI に PR を作らせ URL 出力 → サイドバーに `#N`(複数なら並ぶ)→ クリックでブラウザ → usagi 再起動後も残存。 > 注: main に大きなサイドバー変更(#430 リソース行で 3 行化・#428 詳細行の固定桁化・#426 左ペインのクリック選択)が入ったため、本ブランチに main をマージしてコンフリクトを解消済み。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: test <test@example.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kkyosuke
added a commit
that referenced
this pull request
Jun 28, 2026
## 目的 没入(Attached)中にサイドバーのセッション行をクリックすると、その行に紐づく**全 PR がブラウザで開いてしまう**問題を解消する。あわせて、行のクリックをセッション操作に開放し、**ダブルクリックでそのセッションへ切替**できるようにする。 ## 変更内容 ### ① PR を開くのは `#N` バッジのクリック時だけに - `sidebar_pr_links_at` → **`sidebar_pr_link_at`** に作り替え(`ui/panes.rs`)。 - クリック位置が**詳細行の `#N` バッジの桁範囲**に入ったときだけ、**その 1 件**の PR を開く。`#412 #98` が並んでいればクリックした側だけ。バッジ間の空白・行の余白・他の行はヒットしない。 - 桁計算はレンダラと同じ「クラスタ右端寄せ・PR は最右」前提を使い、狭すぎてバッジがクリップされる場合は誤爆を避けて何も開かない。 ### ② 没入中の行ダブルクリックでセッション切替 - 没入中もサイドバーのセッション行を**ダブルクリック**するとそのセッションへ切替(ライブなら再アタッチ)。`Ctrl-O o` で切替へ戻る必要がなくなる。 - ダブルクリック判定を `pane_input::is_double_click` に切り出し、切替(Switch)の `switch_click` と**共有**(しきい値 `DOUBLE_CLICK` も SSoT 化)。 - `PaneStep::ToSession` → `PaneExit::ToSession` → `focus_and_attach` の経路は `Ctrl-^`(直前セッション)と同じ再ルートに乗せている。 ### ドキュメント - `document/design/05-home.md`(PR バッジ節・没入のマウス操作表)を実装に合わせて更新。 ## テスト・確認方法 - `cargo fmt` / `cargo clippy --all-targets -- -D warnings` クリーン - `cargo test` 全 **2265 件** 通過。追加テスト: - `sidebar_pr_link_at_*`(バッジ毎ヒット・非詳細行/PRなし/サイドバー外/レール/桁あふれ)計 6 件 - `is_double_click_*`(同一行確定・別行/しきい値超の再アーム)2 件 - `a_double_click_in_an_attached_pane_switches_to_the_clicked_session`(没入→切替の結合)1 件 - カバレッジ **lines/functions 100%**(`scripts/coverage.sh` の閾値を満たす) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: test <test@example.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
目的
左ペイン(セッション一覧)の先頭にある丸アイコン(
kind_dot)はWorktreeState.primaryで●(primary)/○(通常) を出し分ける設計だったが、production ではprimaryが常にfalseにハードコードされており到達不能なデッドコードだった。さらに primary(リポジトリ本体)は常にルート行⌂として別枠で描かれるため、セッション行で primary を示す意味自体がない。この死んだ1文字スロットを、**セッションを最後に触ってからの経過時間(鮮度 / heat)**を示すインジケータに転用する。一覧が増えても「どれが生きているか」が一目で分かる。
変更内容
鮮度マッピング
●(緑)= 15分以内に触った /◐= 4時間以内 /○(淡色)= 4時間超。ルート行は従来どおり⌂。実装(層ごと)
domain:SessionRecord.last_active: Option<DateTime<Utc>>(#[serde(default, skip_serializing_if)]で後方互換)+last_active_or_created()(未設定ならcreated_atにフォールバック)。ui/panes.rs:Heat/heat_of(last_active, now)(純関数)/kind_dot(heat)。描画側は内部でUtc::now()を読む(heat は分粒度なのでフレーム内誤差は無害)。state/list.rs:session_rowのupdated_atをlast_active_or_created()に差し替え(死蔵していた枠を活用)。state/mod.rs: インメモリ bump(bump_last_active/touch_active/changed_roots)。enter_focus等の活性化時とapply_badgesの活動状態変化時に bump し、hot path に I/O を置かない。Wiring.save_last_active→ 新設usecase::session::persist_last_activeがstate.jsonへ一括マージ(変化が無ければ書かない)。再起動でも鮮度を復元。テスト・確認方法
cargo fmt/cargo clippy --all-targets -- -D warnings/cargo test(2034 passed)すべて green。document/design/05-home.md(鮮度ドットの定義・凡例・rail)、document/data/02-workspace.md(last_active行・JSON サンプル)。🤖 Generated with Claude Code