Skip to content

feat: jj workspace 並列セッション安全化 — ADR-045 改訂 + push -b 明示化 + stale/op 検証 hook (順位278/279消化) - #267

Merged
aloekun merged 5 commits into
masterfrom
parallel-session-safety
Jul 13, 2026
Merged

feat: jj workspace 並列セッション安全化 — ADR-045 改訂 + push -b 明示化 + stale/op 検証 hook (順位278/279消化)#267
aloekun merged 5 commits into
masterfrom
parallel-session-safety

Conversation

@aloekun

@aloekun aloekun commented Jul 13, 2026

Copy link
Copy Markdown
Owner

概要

jj workspace 並列セッション運用での lost-update incident (2026-07-12/13、2 コミット分の操作が op log に痕跡なく消失) の再発防止セット。jj 公式の lock-free 設計を尊重し、ロックではなく「危険操作の排除 + 早期検知」で防御する。todo 順位 278/279 を消化。

変更内容 (コミット単位)

  1. docs(adr) ADR-045 改訂 (順位 279 消化): 「並行操作は jj が安全にマージする」という不正確な記述を公式並行モデル (divergent op heads の自動マージ / stale working copy → update-stale → recovery commit / bookmark 競合) に即して是正。Known operational risks (stale / bookmark 競合 / colocated 未テスト / output corruption 事故記録)・並列運用の運用ルール (1 terminal = 1 session、--all 禁止等 7 項)・Operation Verification Checklist の 3 節を新設。再評価 trigger fix(hooks): extra_protected_files でパス付き指定をサポート #3 の発火を記録
  2. feat(push-runner) push の -b 明示化: push stage が bookmark_check の検出名から jj git push -b <name> を組み立て、--all を廃止 (他 workspace の bookmark 巻き込み防止)。jj 0.42 の -b は新規 bookmark を自動 track するため --all の存在理由 (新規 bookmark push) を代替。shell-safe 検証付き、--all を含む旧 config は従来挙動 (後方互換)。config + templates 更新
  3. docs(adr) ADR-015 追記 (順位 278 消化): 「push 戦略は hook 層 (対話操作 = jj-push-guard) と exe 実装層 (自動化経路) の 2 層で管理する」原則。ADR-011 (auto-track 戦略) との乖離整理を含む
  4. feat(session-start) workspace stale 検知 nudge (opt-in): SessionStart で working copy の stale を stderr 文言から検知し jj workspace update-stale を促す (自動実行しない、recovery commit の勝手な生成を避ける)
  5. feat(hooks) jj operation 検証 hook 新設 (opt-in): Bash PostToolUse (matcher: Bash) の新 crate hooks-post-tool-jj-op-verify。変更系 jj コマンド後に jj op log --limit 1 で operation の記録を確認し、無ければ「operation not recorded」警告。incident の「成功表示だが記録なし」クラスを即時検出する

設計判断

  • ロック導入は見送り: jj は意図的な lock-free 設計 (公式 Concurrency 文書) であり、上からロックを被せるのは設計に逆行。A〜G の「危険操作排除 + 早期検知」を先に dogfood し、再発時に条件付き再検討 (ADR-045 に記録)
  • hook 側の push block 追加は不要と判明: 既存 jj-push-guard preset が対話操作の jj git push を全 block 済み。ギャップは exe 層のみだった (ADR-015 の 2 層管理原則として記録)
  • 新 hook / stale 検知は ADR-039 準拠: source default-OFF + 本リポジトリ config で opt-in + kill-switch (enabled = false)

実地検証

  • 本 PR の push 自体が新ロジックの実地テスト: [push] jj git push -b parallel-session-safety で新規 bookmark が auto-track 付きで push 成功 (--all なし)
  • jj-op-verify hook は本セッションで稼働開始済み: jj bookmark create に対し「OK: operation を記録確認」を自動返答、偽 payload (実行されていない jj new) に対し「operation not recorded」警告を正しく発報
  • cargo clippy --workspace --all-targets -- -D warnings: clean / cargo test --workspace: 全 green (新規 24 テスト含む) / pnpm lint:docs: OK

kill-switch table (ADR-039)

機能 起動経路 停止 影響範囲
push の -b 組み立て push-runner-config.toml [push] command = "jj git push" command に --all を戻す (後方互換分岐で従来挙動) pnpm push の push stage のみ
stale 検知 nudge .claude/hooks-config.toml [session_start.staleness] stale_check_enabled = true false に戻す SessionStart の additionalContext のみ (non-blocking)
jj-op-verify hook [post_tool_use.jj_op_verify] enabled = true false に戻す Bash PostToolUse の additionalContext のみ (non-blocking)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 新機能
    • 並列ワークスペースで作業コピーが古い場合、更新手順を案内する通知を追加。
    • 変更操作後に記録状況を確認し、未記録時に警告を表示。
  • 改善
    • Push時の対象を検出したbookmarkに限定し、意図しない全bookmarkの送信を防止。
    • 明示的な対象指定がある場合は、従来どおりのPush動作を維持。
  • ドキュメント
    • 並列作業時のリスク、Push運用ルール、操作確認手順を更新。

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

JJのpush対象をbookmark単位に限定し、workspace stale通知とoperation記録検証hookを追加した。関連する設定、ビルド配線、ADR、TODO記録、テストを更新した。

Changes

Push対象の限定

Layer / File(s) Summary
Bookmark検出から対象指定pushまで
src/cli-push-runner/src/*, push-runner-config.toml, templates/push-runner-config.toml
検出したbookmark名をpush stageへ渡し、条件を満たす場合に-b <name>を付与する。
Push方針と履歴の更新
docs/adr/adr-015-push-runner-takt-migration.md, docs/adr/adr-045-jj-workspace-parallel-sessions.md, docs/todo-summary.md, docs/todo13.md
--allを使わないpush方針、並列運用ルール、検証手順、完了済みTODOを反映する。

Workspace stale通知

Layer / File(s) Summary
Stale検知とSessionStart通知
.claude/hooks-config.toml, src/hooks-session-start/src/*
設定が有効な場合にworking copyのstale状態を検知し、jj workspace update-staleの案内をSessionStart出力へ追加する。

JJ Operation検証フック

Layer / File(s) Summary
Operation検証hookの実装
src/hooks-post-tool-jj-op-verify/src/main.rs, src/hooks-post-tool-jj-op-verify/Cargo.toml
変更系JJ操作後に直近のjj op logを照合し、未記録時にnon-blocking警告をJSON出力する。
Hook設定とビルド配線
.claude/settings.local.json.template, Cargo.toml, package.json, .claude/hooks-config.toml
新規hookをworkspace、build:all、Bash PostToolUse設定へ登録し、検証を有効化する。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

Push対象の受け渡し

sequenceDiagram
  participant PushRunner
  participant BookmarkCheck
  participant PushStage
  participant JJ
  PushRunner->>BookmarkCheck: 非trunk bookmarkを検出
  BookmarkCheck-->>PushRunner: bookmark名一覧
  PushRunner->>PushStage: detected_bookmarksを渡す
  PushStage->>JJ: -b <name>付きjj git pushを実行
Loading

Operation記録検証

sequenceDiagram
  participant BashPostToolUse
  participant JjOpVerify
  participant JJ
  BashPostToolUse->>JjOpVerify: Bash実行結果を渡す
  JjOpVerify->>JJ: jj op log --limit 1を実行
  JJ-->>JjOpVerify: 直近operationを返す
  JjOpVerify-->>BashPostToolUse: OKまたは警告contextを返す
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PRの主変更である並列セッション安全化、ADR-045更新、pushの-b明示化、stale/op検証hook追加を的確に表しています。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch parallel-session-safety

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.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Monitor 分析 (GitHub Actions バックストップ)

  • トリガー: issue_comment (created) / 実行 run
  • CI: gh pr checks 267 は CodeRabbit の pending (Review in progress) のみを返し、他の GitHub Actions チェックは検出されず (mergeable: MERGEABLE, mergeStateStatus: UNSTABLE — CodeRabbit 未完了が要因と推定)
  • レビュー状況: CodeRabbit は "Currently processing new changes..." のプレースホルダコメントのみ (投稿 2026-07-13T03:00:13Z)、実指摘は未着。pulls/267/reviews pulls/267/comments はいずれも空。人間レビューも無し (reviewDecision 空)
  • Verdict: user_decision (CodeRabbit レビュー未完了のため applicable/not_applicable の判定材料が無く、CI・自動 verdict を確定できない)

Applicable Findings (Critical / High / Major)

(該当なし — レビュー指摘が 1 件も無いため省略)

Applicable Findings (Medium 以下)

(該当なし — レビュー指摘が 1 件も無いため省略)

Filtered (not applicable)

(該当なし)

Diff 概要 (軽量サマリー)

19 ファイル変更 (Cargo.lock は path filter 除外)。主な変更:

  • 新規 hook crate src/hooks-post-tool-jj-op-verify: Bash PostToolUse で変更系 jj コマンド (new/describe/abandon/rebase/squash/bookmark 変更系) 実行後に jj op log --limit 1 で operation 記録を検証し、未記録なら advisory 警告 (非 block)。ADR-045 の lost-update incident 対応。.claude/hooks-config.toml[post_tool_use.jj_op_verify] enabled = true で opt-in、.claude/settings.local.json.template に Bash matcher 追加、package.json/Cargo.toml にビルド対象追加
  • src/cli-push-runner: jj git push --all を廃止し、bookmark_check stage が検出した bookmark 名から -b <name> を組み立てて push (push.rsbuild_push_command)。shell-safe な bookmark 名のみ許可リストで検証、明示 push target 指定済みの base command はそのまま維持 (後方互換)。ユニットテスト 9 件追加 (shell injection 拒否ケース含む)
  • src/hooks-session-start: workspace stale (別 workspace の操作で working copy が取り残される状態) を jj log -r @ の stderr から検知し、セッション開始時に jj workspace update-stale を促す nudge。stale_check_enabled で opt-in、自動実行はしない
  • docs/adr/adr-045: 「並行操作は jj が安全にマージする」という不正確な記述を是正し、Known operational risks / 運用ルール / Operation Verification Checklist の 3 セクションを新設 (todo 順位 279 消化)
  • docs/adr/adr-015: push 戦略の hook 層/exe 層 2 層管理原則を追記 (todo 順位 278 消化)
  • docs/todo-summary.md docs/todo13.md: 消化した todo 279/278 のエントリ削除

CodeRabbit のレビューは未着 (処理中)。

次のアクション

  • CodeRabbit のレビュー完了後、改めて指摘の有無を確認する (本 workflow の次回起動、または人間による確認)
  • 新規 hook crate (hooks-post-tool-jj-op-verify) は .claude/hooks-config.toml.claude/ 配下ファイルであるため、指摘が出た場合は sensitive-file protection により auto-fix がブロックされる可能性がある点に留意

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/hooks-post-tool-jj-op-verify/src/main.rs (1)

61-95: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

変更系 jj コマンドの検出対象に漏れがあります。

以下の変更系コマンドが detect_last_mutating_jj_op で未検出です:

  • jj undo — 直前の操作取り消し (lost-update 再発リスクが高い)
  • jj restore — ファイル復元
  • jj split — commit 分割
  • jj bookmark movebookmark set の後継コマンド (jj バージョンによって set が非推奨化されている可能性あり)
  • jj bookmark track / untrack — remote bookmark 追跡設定の変更

bookmark move は特に重要です — プロジェクトの jj バージョンが setmove 移行済みの場合、bookmark move コマンドが検出されず検証対象から漏れます。現在 bookmark set に紐づけている "point bookmark" キーワードの妥当性も含めて確認が必要です。

♻️ 提案する拡張
         let detected = match *sub {
             "new" => Some(("new", "new empty commit")),
             "describe" => Some(("describe", "describe commit")),
             "abandon" => Some(("abandon", "abandon commit")),
             "rebase" => Some(("rebase", "rebase commit")),
             "squash" => Some(("squash", "squash")),
+            "undo" => Some(("undo", "undo operation")),
+            "restore" => Some(("restore", "restore")),
+            "split" => Some(("split", "split commit")),
             "bookmark" => match tokens.get(i + 2).copied() {
                 Some("create") => Some(("bookmark create", "create bookmark")),
                 Some("set") => Some(("bookmark set", "point bookmark")),
+                Some("move") => Some(("bookmark move", "point bookmark")),
                 Some("delete") => Some(("bookmark delete", "delete bookmark")),
                 Some("forget") => Some(("bookmark forget", "forget bookmark")),
                 Some("rename") => Some(("bookmark rename", "rename bookmark")),
+                Some("track") => Some(("bookmark track", "track bookmark")),
+                Some("untrack") => Some(("bookmark untrack", "untrack bookmark")),
                 _ => None,
             },
             _ => None,
         };

expected_op_keyword は実際の jj op log の description 文言と照合してください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks-post-tool-jj-op-verify/src/main.rs` around lines 61 - 95,
拡張された変更系コマンドを detect_last_mutating_jj_op で検出し、undo・restore・split と bookmark の
move・track・untrack を対応する expected_op_keyword とともに追加してください。bookmark set
の既存検出は維持しつつ、各キーワードが実際の jj operation log の description と一致する文言になるよう確認・調整してください。
src/hooks-session-start/src/hooks_config.rs (1)

93-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

stale_check_enabled のパーステストを追加してください。

既存テスト hooks_config_parses_session_start_staleness_sectionstale_check_enabled を含んでいません。新フィールドの TOML パースを検証するため、テスト TOML と assertion に追加することを推奨します。

✨ 提案するテスト拡張
 [session_start.staleness]
 enabled = true
 fetch_timeout_secs = 5
 default_branch = "main"
+stale_check_enabled = true
 "#;
     assert_eq!(staleness.enabled, Some(true));
     assert_eq!(staleness.fetch_timeout_secs, Some(5));
     assert_eq!(staleness.default_branch.as_deref(), Some("main"));
+    assert_eq!(staleness.stale_check_enabled, Some(true));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks-session-start/src/hooks_config.rs` around lines 93 - 116, Extend
hooks_config_parses_session_start_staleness_section to include a
stale_check_enabled entry in the test TOML and assert the parsed
staleness.stale_check_enabled value, preserving the existing field assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/hooks-post-tool-jj-op-verify/src/main.rs`:
- Around line 61-95: 拡張された変更系コマンドを detect_last_mutating_jj_op
で検出し、undo・restore・split と bookmark の move・track・untrack を対応する
expected_op_keyword とともに追加してください。bookmark set の既存検出は維持しつつ、各キーワードが実際の jj
operation log の description と一致する文言になるよう確認・調整してください。

In `@src/hooks-session-start/src/hooks_config.rs`:
- Around line 93-116: Extend hooks_config_parses_session_start_staleness_section
to include a stale_check_enabled entry in the test TOML and assert the parsed
staleness.stale_check_enabled value, preserving the existing field assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f854efb5-5754-4158-ba39-8b55a28a0e0e

📥 Commits

Reviewing files that changed from the base of the PR and between 24ce033 and 1db5d27.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • .claude/hooks-config.toml
  • .claude/settings.local.json.template
  • Cargo.toml
  • docs/adr/adr-015-push-runner-takt-migration.md
  • docs/adr/adr-045-jj-workspace-parallel-sessions.md
  • docs/todo-summary.md
  • docs/todo13.md
  • package.json
  • push-runner-config.toml
  • src/cli-push-runner/src/main.rs
  • src/cli-push-runner/src/stages/bookmark_check.rs
  • src/cli-push-runner/src/stages/push.rs
  • src/hooks-post-tool-jj-op-verify/Cargo.toml
  • src/hooks-post-tool-jj-op-verify/src/main.rs
  • src/hooks-session-start/src/hooks_config.rs
  • src/hooks-session-start/src/jj_helpers.rs
  • src/hooks-session-start/src/main.rs
  • src/hooks-session-start/src/staleness.rs
  • templates/push-runner-config.toml
💤 Files with no reviewable changes (2)
  • docs/todo13.md
  • docs/todo-summary.md

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Monitor 分析 (GitHub Actions バックストップ)

  • トリガー: pull_request_review (submitted) / 実行 run
  • CI: CodeRabbit チェックは SUCCESS (Review completed)。analyze (本 workflow 自身) は実行中。他の GitHub Actions ビルド/テスト系チェックは検出されず (mergeable: MERGEABLE, mergeStateStatus: UNSTABLE)
  • レビュー状況: CodeRabbit が COMMENTED レビューを提出 (2026-07-13T03:08:49Z、前回の PR Monitor コメント [03:01:44Z] より後 → 新情報あり)。Nitpick 2件 (severity: いずれも 🔵 Trivial)。インラインコメント (pulls/267/comments) は 0 件、指摘はレビュー本文内に格納。人間レビューなし (reviewDecision 空)
  • Verdict: approved (applicable 判定の指摘はいずれも Trivial = Info/Low 相当のみ。Critical/High/Major/Medium 該当なし)

Applicable Findings (Critical / High / Major)

(該当なし)

Applicable Findings (Medium 以下)

# File (Line) Reviewer Issue Recommended Action
1 src/hooks-session-start/src/hooks_config.rs (93-116) CodeRabbit (Trivial nitpick) 新規追加された stale_check_enabled フィールドが既存テスト hooks_config_parses_session_start_staleness_section の TOML/assertion に含まれておらず、パーステストが未カバー テスト TOML に stale_check_enabled = true を追加し、assert_eq!(staleness.stale_check_enabled, Some(true)) を追記

Filtered (not applicable)

# File (Line) Issue Filter Reason
1 src/hooks-post-tool-jj-op-verify/src/main.rs (61-95) detect_last_mutating_jj_opjj undo / restore / split / bookmark move / bookmark track / untrack を未検出 Intentional design: 実装は ADR-045 「Operation Verification Checklist」(docs/adr/adr-045-jj-workspace-parallel-sessions.md:120) が明示列挙する対象コマンド (new/abandon/describe/rebase/squash、+ 本 hook 独自追加の bookmark 変更系) と一致する意図的スコープ限定。fetch/push を除外する設計もモジュール doc に明記済み。ただし bookmark move が将来 bookmark set を代替する可能性への言及は将来的な再検討材料として妥当

次のアクション

  • Medium 以下 finding 1 件 (stale_check_enabled テスト未カバー) は Trivial だが対応コストが低いため、次回のローカルセッションで軽微修正として拾うことを推奨
  • Filtered finding の bookmark move 非推奨化懸念は、プロジェクトの jj バージョンが bookmark set を非推奨化した時点で ADR-045 checklist 側の再改訂検討事項としてメモしておく
  • 他の GitHub Actions ビルド/テストチェックが本 PR に存在しない点は前回コメント時から変化なし。マージ判断は人間の裁量に委ねる

@aloekun
aloekun merged commit 23e4551 into master Jul 13, 2026
2 checks passed
@aloekun
aloekun deleted the parallel-session-safety branch July 13, 2026 03:15
aloekun added a commit that referenced this pull request Jul 13, 2026
aloekun added a commit that referenced this pull request Jul 13, 2026
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