Skip to content

chore: open PR 11 件をまとめて取り込み (#216 〜 #236)#239

Merged
MocA-Love merged 29 commits intomainfrom
chore/consolidate-open-prs
Apr 16, 2026
Merged

chore: open PR 11 件をまとめて取り込み (#216 〜 #236)#239
MocA-Love merged 29 commits intomainfrom
chore/consolidate-open-prs

Conversation

@MocA-Love
Copy link
Copy Markdown
Owner

@MocA-Love MocA-Love commented Apr 16, 2026

概要

現時点で MocA-Love/superset に open している 11 件の PR をひとつのブランチに統合しました。
それぞれの機能・修正は維持したまま、merge commit ベースで時系列順に取り込んでいます。
個別 PR をひとつずつマージする手間を省くためのまとめ PR です。マージ後に各元 PR は不要になります。

取り込んだ PR

# タイトル 元ブランチ
#216 fix(desktop): PR返信ダイアログの返信元をMarkdownレンダリング対応 fix/reply-dialog-markdown-rendering
#218 fix(desktop): スケジュール作成ダイアログの横幅を広げる fix/215-schedule-dialog-width
#221 fix(desktop): Agent Manager 設定ダイアログでマネージャが閉じる問題を修正 fix/217-agent-manager-settings-dialog
#223 fix(desktop): Todo セッションに ScheduleWakeup 待機ステータスを追加 fix/todo-waiting-status
#224 fix(desktop): TODO の maxConcurrentTasks を尊重しキュー消化する fix/todo-max-concurrent-tasks
#225 fix(desktop): Agent Manager の タスク/スケジュール タブの UI 統一 magenta-spectroscope
#227 fix(desktop): AgentManager 右サイドバーにセッション全体の差分を表示 fix/agent-manager-changes-sidebar
#229 feat(desktop): TODO 詳細の添付画像を chip 化+プレビュー対応 feat/todo-attachment-chip-preview
#231 fix(desktop): TODOボタンのインジケーターをステータス別に表示 fix/todo-button-status-indicators
#233 fix(desktop): AgentManager の preparing 状態でも description/goal を編集可能に fix/todo-preparing-editable
#236 feat(desktop): TODO ライブストリームをサブエージェント入れ子 + スタイリッシュ UI に刷新 feat/todo-live-stream-revamp

コンフリクト解消メモ

3 箇所でコンフリクトを解消しました(merge commit message にも記録)。

検証

  • bun run typecheck
  • bun run lint ✅(rg 不在による check-git-ref-strings.sh の警告のみで biome 本体は pass)

マージ後タスク

  • 元の 11 PR は close(branch 削除)して問題ありません

Summary by CodeRabbit

リリースノート

  • 新機能

    • TODOのやってほしいこととゴール欄に添付されたイメージを表示。クリップ形式のチップで表示され、クリックすると画像プレビューダイアログが開きます
    • セッションが自動実行を一時停止できるようになりました(指定時刻に自動再開)
    • 複数タスクの同時実行に対応。設定で上限を調整可能
    • セッション内で変更されたファイルの詳細表示
    • スケジュール検索フィルター追加
  • 改善

    • TODOマネージャーのUIを改善。タスク状態をより詳しく表示
    • ストリーム表示を再構成。ツール呼び出しのネストされた構造を明確化

- ReplyDialog の返信元プレビューが getCommentPreviewText でプレーンテキスト化されていたため、画像・リンク・コードブロック等が表示されていなかった
- ReviewPanel 内の CommentBody をコンポーネント化し、ReplyDialog でも再利用することで GFM/リンク/コードハイライト/GitHub blockquote alert を含むフルレンダリングに統一
- リンククリックは ReviewPanel の handleOpenUrl を経由し、ブラウザタブで開く挙動を維持
max-w-2xl (672px) から max-w-5xl (1024px) に拡大し、狭い画面にも対応できるよう w-[92vw] を併用。
2カラムレイアウトの各列がフォーム入力に十分な幅を確保できるようにする。
PresetsDialog を DialogContent の外側(Dialog の兄弟)に置いていたため、
Radix の DismissableLayer が兄弟同士のネストを認識できず、設定ダイアログ
内のクリックが「外側クリック」と判定されて Agent Manager が閉じていた。
正しく動作している ScheduleEditorDialog と同じく DialogContent 内部で
描画するよう修正した。

Closes #217
Claude Code の ScheduleWakeup (/loop 動的モード) が呼ばれたあと子
プロセスが一旦終了する。supervisor はそれを「処理完了」とみなして
セッションを done にしてしまうため、再開待ちの間も並列実行数の
カウントから外れ、UI では完了済みとして誤表示されていた。

- 新しい status "waiting" と waitingUntil / waitingReason カラムを
  追加し、Claude の tool_use ストリームから ScheduleWakeup を検知
  したときに done ではなく waiting に遷移させる
- scheduler の tick で waitingUntil を過ぎたセッションをアトミック
  にキューへ戻して自動再開する
- isSessionActive と TodoButton/TodoManager の表示を waiting に対応
  させ、同時実行数・バッジ・ドットで並列中として扱う
- trpc start を waiting からの再開にも対応させ、手動「即時起動」を
  許可する
Claude の assistant メッセージに `text` と `ScheduleWakeup` tool_use が同じ
`message.content` 配列で来る場合、text で早期 return してしまい
ScheduleWakeup が落ちて done 誤遷移していた。`classifyStreamJson` の
`type === "assistant"` 分岐で text/tool/wakeup を前段で揃えてから返し、
どちらのイベントでも `scheduledWakeup` を propagate するよう修正。
`claimWaitingForResume` で status を queued に進めた後で supervisor.start
が失敗すると、waiting のタイマーも消えているため scheduler tick の次回以降
でも取り戻せず、セッションが永続的に queued のまま取り残されていた。
catch 内で現在の status を確認し、まだ queued(=我々が claim したまま)の
場合に限り failed へ遷移させ、原因メッセージを verdictReason に残すように
した。
supervisor がシングルスロット (`active: ActiveRun | undefined`) だったため、
設定の `maxConcurrentTasks` が完全に無視され、常に 1 セッションしか走らず
残りは永久キュー待ちになっていた。加えて設定変更時に supervisor へ通知が
飛ばないので、ユーザーが 1→2 に上げても pending のまま動き出さなかった。

- `active` を `Map<string, ActiveRun>` に変更し、複数同時実行を可能に
- `start()` をキュー登録 + `drain()` 呼び出しに変更
- 各 runSession の `finally` で slot を解放し `drain()` を再実行
- `handleSettingsChanged()` を追加し、settings.update のミューテーションから呼ぶ
- abort() も Map ベースに書き換え、対象セッションだけを停止
- スケジュールタブに検索機能を追加
- タスクタブにスケジュールと同じ形式の「新規」ボタンを追加
- 「新しい TODO」押下時の Composer をインライン表示から Dialog 表示に変更
Issue #226。

- `git log startHeadSha..HEAD` は HEAD が startHeadSha の子孫でない場合
  (ブランチ切替・reset・rebase)無音で0件を返し、`gitOut` が例外を
  握りつぶしていたため「新規コミット無し」と「開始点が失われた」を
  区別できなかった。`gitRevExists` で解決可能性を確認し、
  `startHeadUnreachable` としてUIへ通知する。
- `git diff --name-status -z startHeadSha HEAD` で2コミット間のファイル
  差分を `sessionFiles` として追加。divergent な履歴でも累積デルタを
  表示できるようにした。
- ChangesSidebar に「セッション全体」セクションと、開始HEAD喪失時の
  注意表示を追加。選択中スコープのラベル切替も session / commit を
  考慮する。
- supervisor: resume のたびに `startHeadSha` を上書きすると初回ランの
  コミットが埋もれてしまうため、既に記録済みの場合は維持する。
`git diff <start>..HEAD -- <path>` は削除ファイルでも有効な patch を
返すため、「セッション全体」セクションでは `code === "D"` を無効化
せず、削除の差分も閲覧できるようにする。ワーキングツリー側の
`D` 無効化はファイルが worktree から既に失われているため維持する。
AgentManager のタスク詳細画面では「やってほしいこと」「ゴール」
フィールドが whitespace-pre-wrap の素テキストだったため、添付画像が
`![](/path/.../todo-agent/attachments/xxx-image.png)` という長い
マークダウン文字列のまま剥き出しで見えていた。コンポーザ
(`ImagePasteTextarea`) のチップ UI と詳細表示の体験を揃える。

- `todoAgent.readAttachment` tRPC procedure を追加。
  `userData/todo-agent/attachments/` 配下のパスのみ読み取りを許可し、
  base64 + MIME を返す。それ以外のパスは FORBIDDEN で拒否。
- 添付参照を抽出する `extractAttachmentRefs` / `stripAttachmentRefs`
  ユーティリティを追加(POSIX/Windows 両対応、UUID プリフィックス除去)。
- `AttachmentChips`(読み取り専用 chip 一覧)と `AttachmentPreviewDialog`
  (ネスト Dialog で画像表示)を追加。
- SessionDetail の description / goal 表示を、本文(strip 済み) +
  チップ列にレイアウト。チップクリックでプレビューを開く。
  AgentManager ダイアログは閉じない(ネスト Dialog として動作)。
Running / Queued / Failed / Paused を色分けされた独立したバッジとして
並べて表示し、Manager を開かなくても各ステータスの件数を把握できる
ようにする。配色は TodoManager の StatusDot と揃えた。

Closes #230
`preparing` は supervisor が Claude プロセスを spawn する前の
準備状態で、この時点での編集は `prepareArtifacts` が goal.md を
書き直すため安全に反映される。キュー待ちで `preparing` 停滞中の
セッションも編集できるようにする。

キュー待ちセッションの番が回ってきて編集中に `running` / `verifying`
に遷移した場合は、フロント側の useEffect で編集モードを自動解除し
toast で通知する。バックエンドも `queued` / `preparing` / `failed` /
`aborted` / `escalated` のみ許可する二重ガードを維持。

Closes #232
#234 — AgentManager の TODO 詳細で、Claude Code のサブエージェント (Task/Agent
ツール) の tool_use/tool_result が親 Agent ブロック外にフラット表示される
不具合を修正し、併せて全体のビジュアルを改善する。

- supervisor: stream-json の `parent_tool_use_id` と tool_use/tool_result
  ブロックの id を抽出して TodoStreamEvent に `parentToolUseId` /
  `toolUseId` として伝搬。
- types: TodoStreamEvent に optional な id フィールドを追加。旧 jsonl
  (id 無し) は renderer 側の legacy 位置ペアリングで従来通り動作する。
- renderer: pairStreamEvents を id ベース + 親子ツリー化した
  buildStreamTree に差し替え。ToolCallCard はツリー再帰表示・
  lucide-react のツール別アイコン/パレット・実行中 ShinyText シマー・
  子件数バッジを持つカード型に刷新。子がいる場合は初回に自動展開。
- globals.css: pure CSS の `.animate-shine` キーフレームを追加
  (currentColor + --shine-peak で theme 対応)。
PR #219 で追加された `waiting` ステータス (ScheduleWakeup で一時停止中)
が本 PR の新インジケーターで拾えていないため、queued バケットに追加する。
scheduler が waitingUntil 経過後に自動で queued に戻す挙動から、slot を
占有している扱いとして queued と同じバッジで集計する。
Conflict resolution: keep composer Dialog inside the parent DialogContent
(per #221 fix for Issue #217) instead of as a sibling, to prevent the
outer Manager Dialog from closing.
Conflict resolution: take #231's status-grouped badge implementation
which already covers waiting/queued/preparing as well as failed/paused,
superseding the simpler running+queued+waiting counters from #223.
Conflict resolution: combine #236's parentToolUseId/toolUseId event
fields with #223's ScheduleWakeup detection (scheduledWakeup) so live
stream nesting and waiting-state detection both work, and keep the
existing extractScheduledWakeup helper alongside the renamed
extractToolResultDetails.
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

Warning

Rate limit exceeded

@MocA-Love has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 45 minutes and 27 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 45 minutes and 27 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c41c230a-beb5-4524-a794-0d19c47998b2

📥 Commits

Reviewing files that changed from the base of the PR and between 7015bb8 and dcbf774.

📒 Files selected for processing (5)
  • README.md
  • apps/desktop/src/main/todo-agent/scheduler.ts
  • apps/desktop/src/main/todo-agent/supervisor.ts
  • apps/desktop/src/renderer/globals.css
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/CommentBody/CommentBody.tsx
📝 Walkthrough

Walkthrough

TODO タスクにおける待機状態管理、添付ファイルのレンダリング、並行実行制御の新機能を実装しました。セッションの自動再開、ScheduleWakeup による自己ペース制御、git変更ファイルの表示、添付画像のプレビュー、ストリームイベントツリー構造化などが追加されました。

Changes

Cohort / File(s) Summary
Waiting Session Management
apps/desktop/src/main/todo-agent/scheduler.ts, session-store.ts, types.ts, packages/local-db/src/schema/todo-sessions.ts
新しい waiting 状態を追加し、期限切れ待機セッションの自動再開、DB スキーマ更新(waitingUntil, waitingReason 列)を実装。
Concurrent Task Execution
apps/desktop/src/main/todo-agent/supervisor.ts, trpc-router.ts
active をシングルスロットから Map<string, ActiveRun> に変更し、並行実行数制御、ScheduleWakeup による自己ペース制御、設定変更フック、セッション再開時の startHeadSha 保持を追加。
Git & Session State
apps/desktop/src/main/todo-agent/git-status.ts
SessionGitChangedFile インターフェースと sessionFiles フィールド追加、startHeadUnreachable フラグ追加、git diff --name-status -z パース処理を実装。
Attachment Handling
apps/desktop/src/renderer/features/todo-agent/TodoManager/utils/attachmentRefs/*, components/AttachmentChips/*, components/AttachmentPreviewDialog/*, trpc-router.ts
マークダウン画像参照の抽出・削除ユーティリティ、添付ファイルチップ表示コンポーネント、プレビューダイアログ、readAttachment tRPC エンドポイント(パストラバーサル防止)を追加。
TODO Manager UI
apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx
セッション説明/ゴールの添付ファイル表示対応、ストリームツリー構造化(ID ベースのツールペアリング)、ネストされたツール表示、待機状態の UX 改善(ラベル、編集制限)を実装。
UI Components & Display
apps/desktop/src/renderer/features/todo-agent/TodoButton/TodoButton.tsx, ChangesSidebar/ChangesSidebar.tsx, SchedulesSection/SchedulesSection.tsx, ScheduleEditorDialog/ScheduleEditorDialog.tsx
バッジ統計の複数カテゴリ化(running, queued, failed, paused)、セッション全体ファイル差分セクション、スケジュール検索フィルタ、ダイアログ幅拡張を追加。
Comment Rendering Refactor
apps/desktop/src/renderer/screens/main/.../ReviewPanel/ReviewPanel.tsx, CommentBody/CommentBody.tsx, ReplyDialog/ReplyDialog.tsx
CommentBody コンポーネントを新規抽出し、markdown レンダリング(remark/rehype プラグイン)と URL ハンドラを集約、ReplyDialogonOpenUrl プロップを追加。
Styling & Animation
apps/desktop/src/renderer/globals.css
@keyframes shine シマーアニメーション、.animate-shine ユーティリティクラス、ライトテーマ対応を追加。
Database Migration
packages/local-db/drizzle/0057_todo_session_waiting.sql, drizzle/meta/0057_snapshot.json, drizzle/meta/_journal.json
待機セッション用列の追加、スキーマスナップショット、マイグレーション日誌を更新。
Documentation
README.md
TODO フィールド添付画像のチップレンダリングと readAttachment tRPC エンドポイント追加を記載。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 添付のチップがクリックでふわり、
待機の朝、セッションがパッと目覚める。
ツール同士つながり、ツリーに揺らめく、
並行の流れ、スムーズに泳ぎながら。
画像プレビュー、シマー光る ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed タイトル「chore: open PR 11 件をまとめて取り込み (#216#236)」は、11 件の個別 PR を統合するまとめ PR という主要な変更内容を正確に反映しており、変更セットの目的が明確です。
Description check ✅ Passed PR 説明は「概要」「取り込んだ PR」「コンフリクト解消メモ」「検証」「マージ後タスク」の各セクションを含みており、必須テンプレートの「Description」と「Related Issues」に該当する情報が充実しています。ただし、テンプレートの「Type of Change」「Testing」「Screenshots」のセクションは記載されていません。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/consolidate-open-prs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MocA-Love
Copy link
Copy Markdown
Owner Author

@codex review

@MocA-Love
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e836a730d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/main/todo-agent/supervisor.ts Outdated
Comment thread apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx Outdated
Comment thread apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx Outdated
…ult 重複描画

- supervisor.start: 直前 abort で active から脱落途中の場合、
  以前の早期 return で再開リクエストが捨てられ session が
  preparing で固着する問題を修正。abort 済みなら queue に積み、
  drain で再起動する。
- TodoManager canEditFields: waiting (ScheduleWakeup 待機) を
  除外。バックエンド updateFields が waiting を許可せず保存時
  に PRECONDITION_FAILED で確定失敗する不整合を解消。
- buildStreamTree: イベントが順序逆転して tool_result が先に
  到着した場合、standalone とツリー両方に出てしまう重複を排除。
  事前パスで tool_use の id 集合も収集し、同じ id を持つ
  tool_result は standalone レンダリングをスキップする。
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/renderer/features/todo-agent/TodoManager/SchedulesSection/SchedulesSection.tsx (1)

73-96: ⚠️ Potential issue | 🟡 Minor

ヘッダー件数とプレースホルダーのズレ

  • Line 75-77: ヘッダーの 〜 件のスケジュール は常に schedules?.length(全件)を表示しており、絞り込み中でも件数が変わりません。フィルタリング時は filteredSchedules.length / schedules.length のように一致件数を併記した方が UX として分かりやすいです。
  • Line 93: プレースホルダーは 名前 / タイトル / プロジェクト ですが、実際は descriptionワークスペース名 もマッチ対象に含まれています(Line 54-55)。案内文と実装を揃えるか、プレースホルダーを 名前 / タイトル / 説明 / ワークスペース / プロジェクト 等へ更新することを検討してください。
💡 提案例
-				<span className="text-xs text-muted-foreground">
-					{(schedules?.length ?? 0) > 0
-						? `${schedules?.length} 件のスケジュール`
-						: "スケジュールなし"}
-				</span>
+				<span className="text-xs text-muted-foreground">
+					{(schedules?.length ?? 0) === 0
+						? "スケジュールなし"
+						: filter.trim()
+							? `${filteredSchedules.length} / ${schedules?.length} 件`
+							: `${schedules?.length} 件のスケジュール`}
+				</span>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/features/todo-agent/TodoManager/SchedulesSection/SchedulesSection.tsx`
around lines 73 - 96, Update the header count to reflect filtering: in
SchedulesSection replace the hard-coded display of schedules?.length with a
conditional that shows filteredSchedules.length and the total (e.g. "X / Y
件のスケジュール" or just "Y 件のスケジュール" when no filter) so the header matches the current
filtered list (use the existing filteredSchedules and schedules variables and
the filter state to decide format). Also update the Input placeholder text in
the same component to accurately list searchable fields (include "説明" and
"ワークスペース" so it reads like "名前 / タイトル / 説明 / ワークスペース / プロジェクト") so the UI
guidance matches the matching logic referenced around filteredSchedules.
🧹 Nitpick comments (5)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/ReplyDialog/ReplyDialog.tsx (1)

93-118: プレビュー領域の Markdown 化は妥当、ただし長文コメントの縦方向占有に注意

getCommentPreviewText による 1 行プレビューから CommentBody によるフル Markdown 描画へ切り替え、高さ上限を max-h-48 に広げた変更は、返信時の文脈確認という観点で良い改善です。一方で、コードブロックや表を含む長いコメントだと max-h-48(約 12rem)でも内部スクロールが頻発し、返信テキストエリアが画面下に押し込まれるケースがあり得ます。実機で長大なレビューコメントに対する返信ダイアログを確認し、Textarea が隠れないか軽く触れておくと安心です。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/ReplyDialog/ReplyDialog.tsx`
around lines 93 - 118, The preview area now renders full Markdown via
CommentBody inside the div with class "max-h-48 overflow-y-auto..." which can
push the reply Textarea off-screen for very long comments; reduce the preview's
vertical impact by either lowering the hard cap (e.g. change max-h-48 to a
smaller max height), or make the preview collapsible/expandable (show first line
or getCommentPreviewText by default with a "Show more" toggle that expands to
render CommentBody), and ensure the dialog/container uses a flex-column layout
that allows the reply Textarea to stay visible (use flex, flex-col and allow the
preview to overflow-y-auto while giving the Textarea a stable min-height) so the
ReplyDialog layout (the preview div and the reply Textarea) never hides the
input.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/CommentBody/CommentBody.tsx (1)

24-35: onOpenUrl 未指定時にリンクの既定ナビゲーションが発生する

onClickonOpenUrl?.(href, e) を呼ぶだけなので、onOpenUrl が未指定だと preventDefault が走らず、<a href> の既定動作で Electron のレンダラ内ナビゲーションが起きる恐れがあります(ワークスペース状態を丸ごと失う典型的な足元の罠)。現状の呼び出し元では常に handleOpenUrl を渡しているので実害はないですが、将来の利用で破綻しないよう、コールバック未指定時は target="_blank" rel="noopener noreferrer" 相当にフォールバックするか、常に e.preventDefault() してから任意でコールバックを呼ぶ形が安全です。

♻️ 防御的な修正例
-				a: ({ href, children }) =>
-					href ? (
-						<a
-							href={href}
-							className="text-primary underline"
-							onClick={(e) => onOpenUrl?.(href, e)}
-						>
-							{children}
-						</a>
-					) : (
-						<span>{children}</span>
-					),
+				a: ({ href, children }) =>
+					href ? (
+						<a
+							href={href}
+							className="text-primary underline"
+							target="_blank"
+							rel="noopener noreferrer"
+							onClick={(e) => {
+								if (onOpenUrl) {
+									e.preventDefault();
+									onOpenUrl(href, e);
+								}
+							}}
+						>
+							{children}
+						</a>
+					) : (
+						<span>{children}</span>
+					),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/CommentBody/CommentBody.tsx`
around lines 24 - 35, The anchor in CommentBody's custom renderer can trigger
default navigation when onOpenUrl is undefined; update the onClick for the <a>
in CommentBody.tsx to always call e.preventDefault(), then if onOpenUrl exists
call onOpenUrl(href, e), otherwise open the URL safely as an external window
(e.g. window.open(href, '_blank') with noopener/noreferrer) and also add
target="_blank" rel="noopener noreferrer" as a defensive fallback attribute so
unidentified callers cannot cause renderer navigation.
packages/local-db/src/schema/todo-sessions.ts (1)

95-102: waitingUntil へのインデックス検討(運用アドバイス)

session-store.ts#listWaitingDue は scheduler tick から定期的に呼ばれ、status = "waiting" AND waiting_until <= now で走査されます。現状は todo_sessions_status_idx の前方一致でフィルタ後にメモリ上で絞り込まれる形ですが、waiting セッションが増えても O(waiting件数) で済みます。当面は問題ありませんが、waiting セッションが多数になる運用が見込まれる場合は (status, waiting_until) の複合インデックスを追加するとスキャン範囲をさらに絞れます。現段階では必須ではありません。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/local-db/src/schema/todo-sessions.ts` around lines 95 - 102, The
current schema defines waitingUntil (waiting_until) but lacks a composite index
with status; to optimize session-store.ts#listWaitingDue queries that filter
WHERE status = 'waiting' AND waiting_until <= now, add a composite DB index on
(status, waiting_until) (e.g., create or declare an index named
todo_sessions_status_waiting_until_idx) so the database can use the index for
both predicates instead of scanning all waiting rows; update the schema
definition in todo-sessions.ts to declare that composite index and run
migrations or adjust the table/index creation accordingly.
apps/desktop/src/renderer/features/todo-agent/TodoManager/ChangesSidebar/ChangesSidebar.tsx (1)

477-488: scopeLabel の網羅性について

DiffScope の 4 ケースすべてを switch で返しており、TypeScript の flow analysis により末尾 return 不要で成立します。将来 DiffScope に値が追加された際は本関数で TS エラーが出るため、現状のままで網羅性チェックが効きます。必要に応じて default: const _exhaustive: never = scope; return _exhaustive; を追加するとさらに明示的になりますが、必須ではありません。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/features/todo-agent/TodoManager/ChangesSidebar/ChangesSidebar.tsx`
around lines 477 - 488, The switch in scopeLabel(scope: DiffScope) currently
covers all known DiffScope cases but to make exhaustiveness explicit and cause a
compile error if DiffScope grows, add a default branch that asserts never (e.g.,
assign scope to a never-typed variable and return it) so the compiler will catch
any unhandled new variants; update the switch in function scopeLabel to include
this exhaustive check referencing the symbol scope (and function scopeLabel /
type DiffScope) so future additions to DiffScope produce a type error until
handled.
apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx (1)

2234-2254: サイドバー行の残り時間表示はリアルタイムに更新されません(任意)。

SessionDetail 側には 1 秒おきの setTick がありますが、SessionRow 側では再レンダの起点が listAll の 2 秒ポーリングだけなので、waiting 行に表示される「N 秒後 / N 分後」が最大 2 秒ラグで跳ねて見えます。秒単位表示が目立つケースはそれほど多くないので急ぎの実害はないですが、「残りが少ないほど表示もカクつく」印象は気になる人もいるかもしれません。

気になるようなら SessionRowsession.status === "waiting" のときだけ短周期の再レンダ Hook を足す手があります。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx`
around lines 2234 - 2254, Sidebar "waiting" rows use listAll's 2s poll so
formatWaitingRemaining (used in SessionRow) can lag; add a short-interval
re-render only when session.status === "waiting". In the SessionRow component,
create a local tick (e.g. useState or useReducer) and useEffect that sets a
setInterval at ~1s when session.status === "waiting" and clears it on status
change/unmount; ensure the effect depends on session.status and
session.waitingUntil so formatWaitingRemaining(session.waitingUntil) updates in
real time, and keep SessionDetail/listAll unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/main/todo-agent/scheduler.ts`:
- Around line 226-244: The catch on supervisor.start() is dead code because
TodoSupervisor.start (supervisor.start) never rejects; either make start
legitimately throw on validation failures so this catch is reachable or remove
the catch and centralize stranding-handling in the drain/runSession path.
Concretely: either modify TodoSupervisor.start (the async function referenced as
supervisor.start) to validate session existence/state (using
sessionStore.get/session id checks) and throw a descriptive Error on invalid
conditions, or delete the .catch block in scheduler.ts and ensure
runSession()/drain() performs the same sessionStore.update(...) to mark
failed/stranded sessions; keep references to supervisor.start,
TodoSupervisor.start, runSession, drain, sessionStore.get, and
sessionStore.update to locate places to change.

In `@apps/desktop/src/main/todo-agent/supervisor.ts`:
- Around line 1363-1369: The code currently clamps delaySeconds into clamped and
waits, which contradicts the comment that out-of-range values are malformed;
change the behavior to follow the comment: in the ScheduleWakeup handling
(variables delaySeconds, reason, currently using clamped) validate that
delaySeconds is finite and inside [60, 3600] and if it is outside that range
treat it as malformed (continue/return null) instead of clamping; preserve the
reason extraction logic (typeof inp.reason === "string") and, when valid, return
delayMs computed from Math.floor(delaySeconds) * 1000; also update the
surrounding comment to clearly state that out-of-range values are rejected as
malformed.

In `@apps/desktop/src/renderer/globals.css`:
- Around line 533-559: In the .animate-shine rule, add a blank line immediately
before the background-image declaration to satisfy
declaration-empty-line-before, and replace all occurrences of the CSS keyword
currentColor with lowercase currentcolor (e.g., in background-image stops) to
satisfy value-keyword-case; target the .animate-shine selector and its
background-image value updates (and any other uses of currentColor inside that
rule) to make these changes.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/CommentBody/CommentBody.tsx`:
- Around line 21-22: The remarkAlert output classes are being stripped by
rehypeSanitize's default schema; update CommentBody.tsx to pass a custom
sanitize schema to rehypeSanitize that preserves the alert classes. Import the
default schema from rehype-sanitize (or clone its object) then extend its
attributes to allow className values like "markdown-alert",
"markdown-alert-title", and "markdown-alert-content" (assign these to the '*' or
to relevant elements such as 'div'/'p') and pass the extended schema into
rehypeSanitize(...) in the rehypePlugins array so the alert markup keeps its
classes and the existing CSS (.review-comment-body .markdown-alert...) applies.

In `@README.md`:
- Line 93: The date in the README table row for "**TODO 詳細の添付画像 chip 化+プレビュー**"
is inconsistent (shows 2026-04-17); update that cell to match the PR creation
date 2026-04-16 (same as PR `#239` and `#229`) so all rows use the same JST PR date;
locate the table row text "**TODO 詳細の添付画像 chip 化+プレビュー**" and replace the date
value to 2026-04-16.

---

Outside diff comments:
In
`@apps/desktop/src/renderer/features/todo-agent/TodoManager/SchedulesSection/SchedulesSection.tsx`:
- Around line 73-96: Update the header count to reflect filtering: in
SchedulesSection replace the hard-coded display of schedules?.length with a
conditional that shows filteredSchedules.length and the total (e.g. "X / Y
件のスケジュール" or just "Y 件のスケジュール" when no filter) so the header matches the current
filtered list (use the existing filteredSchedules and schedules variables and
the filter state to decide format). Also update the Input placeholder text in
the same component to accurately list searchable fields (include "説明" and
"ワークスペース" so it reads like "名前 / タイトル / 説明 / ワークスペース / プロジェクト") so the UI
guidance matches the matching logic referenced around filteredSchedules.

---

Nitpick comments:
In
`@apps/desktop/src/renderer/features/todo-agent/TodoManager/ChangesSidebar/ChangesSidebar.tsx`:
- Around line 477-488: The switch in scopeLabel(scope: DiffScope) currently
covers all known DiffScope cases but to make exhaustiveness explicit and cause a
compile error if DiffScope grows, add a default branch that asserts never (e.g.,
assign scope to a never-typed variable and return it) so the compiler will catch
any unhandled new variants; update the switch in function scopeLabel to include
this exhaustive check referencing the symbol scope (and function scopeLabel /
type DiffScope) so future additions to DiffScope produce a type error until
handled.

In `@apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx`:
- Around line 2234-2254: Sidebar "waiting" rows use listAll's 2s poll so
formatWaitingRemaining (used in SessionRow) can lag; add a short-interval
re-render only when session.status === "waiting". In the SessionRow component,
create a local tick (e.g. useState or useReducer) and useEffect that sets a
setInterval at ~1s when session.status === "waiting" and clears it on status
change/unmount; ensure the effect depends on session.status and
session.waitingUntil so formatWaitingRemaining(session.waitingUntil) updates in
real time, and keep SessionDetail/listAll unchanged.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/CommentBody/CommentBody.tsx`:
- Around line 24-35: The anchor in CommentBody's custom renderer can trigger
default navigation when onOpenUrl is undefined; update the onClick for the <a>
in CommentBody.tsx to always call e.preventDefault(), then if onOpenUrl exists
call onOpenUrl(href, e), otherwise open the URL safely as an external window
(e.g. window.open(href, '_blank') with noopener/noreferrer) and also add
target="_blank" rel="noopener noreferrer" as a defensive fallback attribute so
unidentified callers cannot cause renderer navigation.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/ReplyDialog/ReplyDialog.tsx`:
- Around line 93-118: The preview area now renders full Markdown via CommentBody
inside the div with class "max-h-48 overflow-y-auto..." which can push the reply
Textarea off-screen for very long comments; reduce the preview's vertical impact
by either lowering the hard cap (e.g. change max-h-48 to a smaller max height),
or make the preview collapsible/expandable (show first line or
getCommentPreviewText by default with a "Show more" toggle that expands to
render CommentBody), and ensure the dialog/container uses a flex-column layout
that allows the reply Textarea to stay visible (use flex, flex-col and allow the
preview to overflow-y-auto while giving the Textarea a stable min-height) so the
ReplyDialog layout (the preview div and the reply Textarea) never hides the
input.

In `@packages/local-db/src/schema/todo-sessions.ts`:
- Around line 95-102: The current schema defines waitingUntil (waiting_until)
but lacks a composite index with status; to optimize
session-store.ts#listWaitingDue queries that filter WHERE status = 'waiting' AND
waiting_until <= now, add a composite DB index on (status, waiting_until) (e.g.,
create or declare an index named todo_sessions_status_waiting_until_idx) so the
database can use the index for both predicates instead of scanning all waiting
rows; update the schema definition in todo-sessions.ts to declare that composite
index and run migrations or adjust the table/index creation accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1dc41012-d760-46ae-b277-140b5509d911

📥 Commits

Reviewing files that changed from the base of the PR and between 8c082df and 7015bb8.

📒 Files selected for processing (27)
  • README.md
  • apps/desktop/src/main/todo-agent/git-status.ts
  • apps/desktop/src/main/todo-agent/scheduler.ts
  • apps/desktop/src/main/todo-agent/session-store.ts
  • apps/desktop/src/main/todo-agent/supervisor.ts
  • apps/desktop/src/main/todo-agent/trpc-router.ts
  • apps/desktop/src/main/todo-agent/types.ts
  • apps/desktop/src/renderer/features/todo-agent/TodoButton/TodoButton.tsx
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/ChangesSidebar/ChangesSidebar.tsx
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/SchedulesSection/SchedulesSection.tsx
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/SchedulesSection/components/ScheduleEditorDialog/ScheduleEditorDialog.tsx
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/TodoManager.tsx
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/components/AttachmentChips/AttachmentChips.tsx
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/components/AttachmentChips/index.ts
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/components/AttachmentPreviewDialog/AttachmentPreviewDialog.tsx
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/components/AttachmentPreviewDialog/index.ts
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/utils/attachmentRefs/attachmentRefs.ts
  • apps/desktop/src/renderer/features/todo-agent/TodoManager/utils/attachmentRefs/index.ts
  • apps/desktop/src/renderer/globals.css
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/ReviewPanel.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/CommentBody/CommentBody.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/CommentBody/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/components/ReplyDialog/ReplyDialog.tsx
  • packages/local-db/drizzle/0057_todo_session_waiting.sql
  • packages/local-db/drizzle/meta/0057_snapshot.json
  • packages/local-db/drizzle/meta/_journal.json
  • packages/local-db/src/schema/todo-sessions.ts

Comment thread apps/desktop/src/main/todo-agent/scheduler.ts
Comment thread apps/desktop/src/main/todo-agent/supervisor.ts Outdated
Comment thread apps/desktop/src/renderer/globals.css
Comment thread README.md Outdated
- scheduler.ts: supervisor.start は同期 wrap で実際には reject しない
  ため、'.catch で failed に倒す' という docstring が嘘だった。docstring
  を実態(不慮の throw を console に出すだけの保護的 catch)に合わせ、
  status 書き換え経路は drain 側の責務に一本化。
- supervisor.ts (extractScheduledWakeup): 範囲外の delaySeconds を
  silent clamp していたが、Claude が想定した再開時刻と実際の再開が
  ずれて挙動が読めなくなる。コメント通り malformed 扱いで wait に
  遷移させない(done の通常終了に倒す)よう修正。
- globals.css (.animate-shine): Stylelint の declaration-empty-line-before
  と value-keyword-case を解消(currentColor → currentcolor、宣言前空行)。
- CommentBody.tsx: rehype-sanitize の defaultSchema が className を
  剥がして remark-github-blockquote-alert の markdown-alert スタイル
  が当たらない問題を修正。markdown-alert / markdown-alert-title /
  octicon クラスのみ明示許可するカスタムスキーマを渡す。
- README.md: #229 の追加日 2026-04-17 → 2026-04-16(他行と同じ
  PR 作成日 UTC 基準)に揃える。
@MocA-Love MocA-Love merged commit 703b976 into main Apr 16, 2026
14 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