org-attention-start: attention watcher の常駐起動
claude-org-runtime attention watch を dispatcher ペインの右側に split で常駐起動し、
pane_id を .state/attention_pane.json に sidecar として記録する。停止は
/org-attention-stop を使う。
輸送層 両系(ORG_TRANSPORT: 既定 renga / opt-in broker): 本スキルの mcp__renga-peers__*(spawn_pane / list_panes / inspect_pane / close_pane)は 既定 renga で書いてあり、ORG_TRANSPORT 無設定ならそのまま従えばよい(既定挙動不変)。ORG_TRANSPORT=broker(opt-in・切戻し可)では完全修飾名が mcp__renga-peers__* → mcp__org-broker__* に機械置換される(引数形・セマンティクスは同一なので spawn / 監視操作の論理は変わらない)。attention watcher は Claude ペインではなく claude-org-runtime CLI なので dev-channel / folder-trust の承認は両系とも不要(spawn 儀式の差は Claude ペイン spawn にのみ効く)。エラーは broker 追加コード([no_backend](= adapter_unavailable)/ [token_invalid] 等、.claude/skills/org-delegate/references/renga-error-codes.md の broker 節)が加わる。new_tab / focus_pane は broker surface に無いが本スキルは使わない。契約面は docs/contracts/backend-interface-contract.md Surface 8(ratified 2026-06-14)、設計 SoT は transport-lab docs/design/ja-migration-plan.md §5.2(ii)。既定 renga の手順は不変(broker は加算)。(既定の二フレーム注記(Refs #604): ここでの「既定 renga」は運用既定(broker 実走 dogfood が Epic #6 Issue G まで未活性)の意。別にコード既定として tools/transport.py: DEFAULT_TRANSPORT が runtime 0.1.28 (Epic #586) で broker にフリップ済みで、ja 生成器・transport.resolve() はこのコードフレームで render するため生成面は「既定 broker」と表示する — 両フレームは指す対象(運用経路 vs コード定数)が異なり矛盾しない。総説は root CLAUDE.md「輸送層(transport)両系」節。)
前提: この skill は窓口(Secretary)の cwd(= claude-org-ja リポジトリ root)から呼ばれる。
attention watcher 自体は claude-org-runtime の console_scripts entrypoint で、--state-dir .state /
--config .state/attention.json の相対パスが repo root から resolve される必要がある。
dispatcher ペインの cwd は .dispatcher なので、spawn_pane では cwd="." を明示して
Secretary 側の cwd(= repo root)にバインドする。
pane_id は .state/state.db ではなく sidecar JSON(.state/attention_pane.json)に記録する
(理由は .claude/skills/org-attention-start/references/rationale.md)。
Step 1: 二重起動チェック
二重起動の判定は sidecar の有無と live pane の両方 を見る必要がある(sidecar 不在でも
過去の手動 spawn / クラッシュ後の孤児 name="attention" ペインが live で残るケースがあり、
sidecar だけ見ると Step 3 の spawn_pane(..., name="attention") が [name_in_use] で失敗する)。
mcp__renga-peers__list_panes を呼び、name="attention" / role="attention" の pane が
live で存在するか確認する
.state/attention_pane.json が存在するか確認:
test -f .state/attention_pane.json && echo exists || echo absent
- 分岐:
Step 2: 設定ファイルの配置(未配置時のみ)
.state/attention.json の有無を確認:
test -f .state/attention.json && echo exists || echo absent
- 未配置の場合: ja 既定テンプレートを copy する(
.state/ は gitignored、fresh clone
直後だと未作成のことがあるので mkdir も同時に走らせる):
mkdir -p .state
cp tools/templates/attention.example.json .state/attention.json
Windows native (PowerShell) で実行する場合は copy コマンドでも可:
if (!(Test-Path .state)) { mkdir .state }
copy tools\templates\attention.example.json .state\attention.json
- 既に配置されている場合: 上書きしない(ユーザーの個別調整を尊重する)。Step 3 へ進む
Step 3: dispatcher を split して watcher を起動
まず broker の state dir を確定する(duplicate_sidecar 通知の入力。未設定なら runtime 既定の <state-dir>/broker = .state/broker):
echo "${ORG_BROKER_STATE_DIR:-}"
dispatcher ペインの右半分(vertical split)に attention watcher 用の pane を作る:
mcp__renga-peers__spawn_pane(
target="dispatcher",
direction="vertical",
role="attention",
name="attention",
cwd=".",
command="claude-org-runtime attention watch --state-dir .state --config .state/attention.json"
)
-
上の echo が空でない値を返した場合だけ、command の末尾に --broker-state-dir <その値> を
リテラルで足す。値は必ずシングルクォートで囲む(例:
... --config .state/attention.json --broker-state-dir '/srv/org/broker')。空白や $ などを
含むパスを裸で埋めると、ペインのシェルが分割・展開して別のパスが argparse に渡る。値自体に
' が含まれる場合は '\'' へ置換してから埋める。空なら足さない(runtime 既定の
.state/broker に解決される)
-
${ORG_BROKER_STATE_DIR:+--broker-state-dir "$ORG_BROKER_STATE_DIR"} のようなシェル展開を
command 文字列に埋め込まないこと。ペインの login shell が zsh だと既定 SH_WORD_SPLIT off で
1 引数に潰れ、argparse error で watcher が起動しない(#829 と同型の罠)。値は呼び出し側で解決して
リテラルに埋める
-
attention watcher は ORG_BROKER_STATE_DIR env を自分では読まない(解決順は flag →
<state-dir>/broker のみ)。非既定 state dir で broker を動かしている環境でフラグを省くと、
duplicate_sidecar だけが黙って鳴らない(他の kind は .state/state.db 経由なので影響を受けない)
-
target="dispatcher": org-start Block A の手順 1 で付けた安定名で解決
-
direction="vertical": dispatcher ペイン = 左、attention ペイン = 右
-
cwd=".": Secretary の cwd(= repo root)基点で相対 resolve され、.state/ パスが正しく当たる。
省略すると dispatcher の cwd (.dispatcher) を継承して .state が .dispatcher/.state に解決され
watcher が空の state を見ることになる
-
name="attention": 後続の /org-attention-stop が「どのペインが
watcher か」を identity 照合するためのラベル(list_panes が返す name / role から
「確認済み attention ペイン集合」を組む)。close 自体は照合済みの数値 pane_id で行う
(target="attention" のような name 指定は使わない)
-
戻り値: "Spawned pane id=N." テキスト。N が attention watcher の pane_id
失敗時の分岐:
[split_refused]: dispatcher pane が分割下限 (MIN_PANE_WIDTH=20) を下回っている。
ユーザーに「dispatcher ペインが分割不能サイズです。secretary 側を縮めるか、ターミナル幅を
広げてから再実行してください」と報告して abort
[pane_not_found]: dispatcher pane が存在しない(org-start 未実行 or dispatcher 落ち)。
ユーザーに「dispatcher pane が見つかりません。/org-start を先に実行してください」と
報告して abort
[name_in_use]: Step 1 の二重起動チェックが取りこぼした live pane が直前に再出現した race。
ユーザーに「attention pane が並走で先に立ち上がりました。/org-attention-stop で掃除して
ください」と報告して abort
- その他
[<code>]: renga-error-codes.md を参照
Step 4: 起動 health check(即時クラッシュの negative-signal 検出のみ)
spawn_pane の成功は「shell が立ち上がって command を発火した」までしか保証しない。
claude-org-runtime 未導入 / 設定不正 / import error で watcher 本体が即時終了すると、
sidecar に stale pane_id が記録されて以後の判定を壊す。一方、watcher が 正常起動時に
何を出力するか は claude-org-runtime 側の契約で固定されておらず(polling loop に入って
静かに待機する実装もあり得る)、「起動バナーが見えるまで待つ」「無出力なら fail」と扱うと
正常な quiet start を誤って kill する経路になる。よって本 skill は 明示的な失敗
シグナルだけを fail と判定し、それ以外(空出力 / 不明な出力)は「起動成功扱い」とする:
mcp__renga-peers__inspect_pane(target="attention", format="text", lines=60)
inspect 自体のラウンドトリップ(数百 ms)で shell が即時終了するケースは pty buffer に
残った prompt や error が cap される。以下のいずれかに該当した場合のみ「起動失敗」:
- 出力末尾に shell prompt が露出している(
PS C:\...> / $ / % / > の末尾露出)
→ command が即時終了して shell に戻った
- 出力に以下のいずれかの文字列を含む:
command not found / is not recognized / not recognized as an internal or external command
ModuleNotFoundError / ImportError / Traceback (most recent call last)
[error] / [ERROR] / FATAL / fatal:
上記いずれも検出されない場合(空出力 / 起動バナー / polling 待機 / 不明な行のみ等)
→ 起動成功扱い で Step 5 に進む。固定 sleep を入れて再 inspect する経路は持たない
(quiet な健全起動を誤殺する経路を作らないため)。
起動失敗時:
- 死んだペインを 自タブ確立 → identity 再確認 → 数値 close の順で掃除する:
- 自タブ確立を先に判定する。契約 T-§4.2「Fail-safe consequence for Group B」は
close_pane の宛先を「自タブと独立に確立済みの列挙から得た数値 pane id」に限っており、
id が spawn の戻り値として手元にあることは免除にならない(未確立の列挙では、close 直前の
identity 照合の結果そのものを信用できないため)。確立手段は 2 つで、いずれか 1 つが成立すれば
よい: (i) backend が Group B を自身の単一タブモデル内で解決する(org-broker。契約
§8.1 / §8.10)/ (ii) caller_scope を確立できている(契約 T-§cap)。どちらも成立
しないなら close を撃たず、死んだペインが残っている旨を 4 の報告に含めて手動掃除に委ねる
(相対セレクタへはフォールバックしない)。詳細は
docs/contracts/backend-interface-contract.md T-§4.2
- identity 再確認(pane_id recycle 対策):
mcp__renga-peers__list_panes を呼び、
spawn 返り値の pane_id が name="attention" または role="attention" をなお指して
いることを確かめる(/org-attention-stop が組む
「確認済み attention ペイン集合」と同じ判定。spawn 時に渡した name は信用せず、いま
list_panes が返す name/role で判定する)。その id が別ペインへ再割当て済み(recycled)/
列挙に現れない(gone)なら close せず、死んだペインが残っている旨を 4 の報告に含める
- 1 と 2 の両方を通ったときだけ
mcp__renga-peers__close_pane(target="<spawn 返り値の pane_id>") で掃除する
([pane_not_found] / [pane_vanished] は直前に消えた扱いで skip)
- sidecar は 書き込まない
- journal に
attention_watch_start_failed を記録:
bash tools/journal_append.sh attention_watch_start_failed pane_id=<N> reason=immediate_exit
- ユーザーに「watcher が起動直後に終了しました(出力: <inspect 抜粋>)。
claude-org-runtime --version で導入を確認し、.state/attention.json の構文も
claude-org-runtime attention scan --state-dir .state --config .state/attention.json --dry-run --json
で検査してください」と報告して abort
Step 5: pane_id を sidecar に記録
返り値からパースした pane_id を .state/attention_pane.json に書き出す:
{
"pane_id": "<N>",
"name": "attention",
"started_at": "<ISO8601 UTC>",
"config_path": ".state/attention.json"
}
Write ツールで上書き保存する(既存ファイルは Step 1 で削除済み)。
journal event を 1 行追記する:
bash tools/journal_append.sh attention_watch_started pane_id=<N> config=.state/attention.json
bash が使えない環境では Mac/Linux は python3 tools/journal_append.py attention_watch_started pane_id=<N> config=.state/attention.json、Windows native では py -3 tools/journal_append.py attention_watch_started pane_id=<N> config=.state/attention.json。
Step 6: 報告
attention watcher を起動しました(pane id={N}、dispatcher の右側)。
設定: .state/attention.json
停止するときは /org-attention-stop を実行してください。
WSL / Windows の通知センター連携 (powershell.exe の WinRT toast) や OS 別の backend 挙動、トラブル
シューティングは docs/operations/attention-watch.md
を参照。