Pr Watch Pane
ASecurityPR の CI / マージ監視 (tools/pr-watch.sh) を broker tmux セッション内の専用ペイン pr-watch-<PR> で回す。窓口が PR 作成直後に `/pr-watch-pane <PR>` で起動すると、 ja-root cwd・sandbox 外で監視が走り、/clear や窓口セッション寿命と無関係に継続する。 pane name で冪等起動 (二重監視しない)、role=watcher で identity 登録、監視終了 (CI green / PR merged / timeout) で broker の tmux backend ならペイン自動 close (herdr / wezterm / renga のペインは tmux ペインでないため自動 close されず、窓口が 監視終端でイベント駆動 close する)。Bash tool の background は session 寿命依存で長時間 watcher には不適なので本 skill が推奨経路。 「CI 監視をペインで」「pr-watch をペインで回して」「P...
- 5 stars
- 0 votes
- 0 copies
- 2 views
- Added October 5, 2026
Works with
Security analysis
100/100Pro scans all 5 files and shows the line behind each finding
npx -y skills add suisya-systems/claude-org-ja --skill pr-watch-pane --agent claude-codeAre you the author of Pr Watch Pane?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/suisya-systems-pr-watch-pane)---
name: pr-watch-pane
owner: secretary
description: >
PR の CI / マージ監視 (tools/pr-watch.sh) を broker tmux セッション内の専用ペイン
pr-watch-<PR> で回す。窓口が PR 作成直後に `/pr-watch-pane <PR>` で起動すると、
ja-root cwd・sandbox 外で監視が走り、/clear や窓口セッション寿命と無関係に継続する。
pane name で冪等起動 (二重監視しない)、role=watcher で identity 登録、監視終了
(CI green / PR merged / timeout) で broker の tmux backend ならペイン自動 close
(herdr / wezterm / renga のペインは tmux ペインでないため自動 close されず、窓口が
監視終端でイベント駆動 close する)。Bash tool の background は
session 寿命依存で長時間 watcher には不適なので本 skill が推奨経路。
「CI 監視をペインで」「pr-watch をペインで回して」「PR <N> の CI を見張って」等で発動。
effort: low
allowed-tools:
- Read
- Bash(git rev-parse:*)
- Bash(gh repo view:*)
- Bash(bash tools/journal_append.sh:*)
- Bash(py -3 tools/journal_append.py:*)
- Bash(python3 tools/pick_watcher_anchor.py:*)
- Bash(py -3 tools/pick_watcher_anchor.py:*)
- mcp__org-broker__list_panes
- mcp__org-broker__spawn_pane
- mcp__org-broker__set_pane_identity
- mcp__org-broker__inspect_pane
- mcp__org-broker__close_pane
---
# pr-watch-pane: CI / マージ監視を専用ペインで回す
`tools/pr-watch.sh <PR> --repo <owner/repo> --merge-watch` を broker tmux セッション
内の専用ペイン (`name="pr-watch-<PR>"`) で起動する。Bash tool の background 起動は
session 寿命依存で、CI 監視のような長時間 watcher には不適(公式設計の対象外)。broker
ペイン spawn を経由することで **sandbox 外・窓口セッション非依存**(`/clear` や窓口の
context リセットと無関係)に監視が継続し、人間が tmux ペインで直接見えるので可視性も高い
(feedback-dispatcher-visibility 整合)。
監視結果は二経路で残る(どちらも `pr_watch.py` の既存挙動。本 skill は形を変えない):
- **`.state/state.db` events テーブル** … `ci_completed` / `pr_merge_watch_timeout` の
canonical event 行(payload 形・`CI_COMPLETED` / `PR_MERGED` / `PR_MERGE_WATCH_TIMEOUT`
のメッセージ形は不変)。**これが判定の canonical 記録**。
- **`.state/pr-watch-<PR>.log` + tmux スクロールバッファ** … 人間可読の生ログ二段。
> **peer push は best-effort**: `pr_watch.py` は CI 確定・マージ時に窓口へ `CI_COMPLETED` /
> `PR_MERGED` の peer message を送ろうとするが、これは `tools/peer_notify.py` 経由の
> best-effort(broker send CLI 不在 / 解決先 transport が未構成の pane では
> no-op)。daemon が非既定 state dir(herdr dogfood 等)で動く環境では、pane env に
> `ORG_BROKER_STATE_DIR` が無いと broker send が既定 `.state/broker` を掴んで push が欠落する
> (欠落しても canonical の events DB 行には影響しない)。**待つべき正路は上記 events DB 行と
> 可視ペイン**であり、push の到達を merge gate の
> 前提にしない(org-pull-request の CI/merge gate は events DB を一次ソースにする)。
> **輸送層(transport)両系**: 本文のツール参照は `mcp__org-broker__*`(`org-broker`)で書いてあり、
> active transport が既定面ならそのまま従えばよい。輸送層で手順が変わるのは **受信モデル /
> spawn 儀式 / エラー分岐** の 3 点だけで、opt-in 側の輸送層は削除せず切戻しの安全装置として
> 常時有効。両系の読み替え規則・契約の批准経緯・broker 固有エラーコードの一覧は
> [`.claude/skills/pr-watch-pane/references/transport-duality.md`](references/transport-duality.md)
> を参照(上記 3 分岐に入るまで読む必要はない)。
> **本 skill の spawn 対象は「汎用 CLI ペイン」**: 起動するのは `tools/pr-watch.sh`
> という shell コマンドであり、Claude セッション(`spawn_claude_pane`)ではなく
> **汎用 `mcp__org-broker__spawn_pane`** を使う。したがって輸送層の **spawn 儀式(broker:
> folder-trust + channel sidecar の 2 段承認 / renga: dev-channel の 1 段承認)は本
> skill では一切発生しない**(`--mcp-config` / `--dangerously-load-development-channels`
> の注入が無く、承認プロンプトが出ない)。attention watcher と同じ CLI ペイン扱いである
> ([`.claude/skills/pr-watch-pane/references/transport-duality.md`](references/transport-duality.md)
> 末尾の「attention watcher は ... 2 段承認の対象外」注記と同義)。両系で
> 切り替わるのは **ツール完全修飾名だけ**:
>
> - 既定 broker: `mcp__org-broker__spawn_pane`(`list_panes` / `set_pane_identity` /
> `inspect_pane` / `close_pane` も同様に `mcp__org-broker__*`)
> - opt-in renga: `mcp__renga-peers__spawn_pane`(同様に `mcp__renga-peers__*`)
>
> 以下の手順は `mcp__org-broker__` を active transport の完全修飾名に読み替えれば両系で論理同一。
> spawn 直後の identity 登録・起動コマンドも両系共通(CLI ペインなので Enter 承認は不要)。
## 前提
- 本 skill は **窓口(secretary)専用**。汎用 `spawn_pane` は broker の auth tier 上
secretary だけが持つ(dispatcher は `spawn_claude_pane` のみ。contract
[`docs/contracts/backend-interface-contract.md`](../../../docs/contracts/backend-interface-contract.md)
Surface 8 の ops tier 定義)。
- 窓口の cwd は ja-root(リポジトリ root)。spawn する pr-watch は `.state/` パスや
`tools/pr-watch.sh` を ja-root 基点で resolve する必要があるため、**cwd trap を skill
側で吸収する**(Step 1 で `git rev-parse --show-toplevel` の絶対パスを spawn_pane の
`cwd` に明示。窓口 cwd が何らかの理由で ja-root を外れていても正しく解決される)。
- **自己 close の実装は「watcher ペインが tmux ペインであること」前提**。Step 3 の `command` は
`bash` 実行と、自己 close の `tmux kill-pane -t "$TMUX_PANE"`(**自ペインを `$TMUX_PANE` で明示
指定して** kill。socket は `$TMUX` 継承をそのまま使い `-L` で固定しない = tmux 上に立つ
ペインであれば broker の既定 socket / 非既定 socket いずれでも正しい server に当たる。
Issue #647 提案 1 の「明示 target 指定」を実装した形)に依存する。**tmux ペインでない環境では
`$TMUX` / `$TMUX_PANE` がそもそも env に無く、`-t ""` へ展開されて `2>/dev/null || true` で
無言失敗する**(下記の分類を参照)。
- **自己 close は tmux ペインの低遅延経路であり、watcher ペインの実体が tmux ペインかどうかで
効き方が変わる(herdr ゾンビ残留の根治, Issue #751 / renga 残留, Issue #911)**。broker は
backend として tmux / herdr / wezterm を取りうる(解決済み backend は `daemon.json` sidecar が
持つ。契約は
[`docs/contracts/backend-interface-contract.md`](../../../docs/contracts/backend-interface-contract.md)
Surface 8)。**opt-in `renga` のペインは tmux ペインではない**ので、transport の綴りではなく
「ペインの実体」で次の 2 分類に読み替える:
- **自己 close が効く = broker の tmux backend**: Step 3 末尾の `tmux kill-pane -t "$TMUX_PANE"`
が実ペインを即座に消す = **監視終端で watcher ペインが自動 close される低遅延経路**
(従来挙動。温存する)。
- **自己 close が効かない = broker の herdr / wezterm backend(Windows native broker の別 GUI
ウィンドウ・tmux 非経由を含む)、および opt-in `renga`**:
watcher ペインは tmux ペインではないため `tmux kill-pane` が **no-op**(`|| true` で握り潰され
silent)。self-close が効かず、**監視終了後もペインがゾンビとして残留する**(herdr / renga
それぞれの実測ログは [`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md)
§1)。この分類では自己 close に頼れないため、
**監視終端で窓口がイベント駆動で watcher ペインを close する経路が正路**になる
([`.claude/skills/org-pull-request/SKILL.md`](../org-pull-request/SKILL.md) の post-merge
cleanup / `PR_MERGE_WATCH_TIMEOUT` / CI 失敗確定の各終端で窓口が発火。掃除手順は下記 Step 5 の
(a)/(b) split に従う = live pane は list_panes 確認済みの数値 pane_id で close、stale binding
のみ broker 条件付き allowlist で name 指定)。`close_pane` は transport 抽象上 tmux / herdr /
renga いずれでも呼べ、broker の tmux backend で既に
self-close 済みなら `[pane_not_found]` が返る(自己クローズ済みで正常)。
- **renga では窓口 close も無条件には撃てない**: Step 5 (a) の自タブ確立は **(i) backend が
Group B を自身の single-tab モデル内で解決する(= `org-broker`)/ (ii) `caller_scope` を
確立できている**のいずれかを要し(契約 T-§4.2「Fail-safe consequence for Group B」/ T-§cap)、
renga では (i) が成立しないため **(ii) を確立できない限り close を撃たず、watcher ペインが
残る旨を報告して人手掃除に委ねる**(相対セレクタへはフォールバックしない)。
Windows native の手動起動経路
(人間が `tools/pr-watch.ps1 <PR>` を `!` 経由で起動)も従来どおり遮断しない(既存経路は不変)。
## Step 1: 引数解決と cwd / repo の確定
1. PR 番号 `<PR>` を引数から取る(必須・正の整数)。省略時はユーザーに PR 番号を尋ねて中断。
2. ja-root の絶対パスと owner/repo を決定的に解決する(cwd trap 吸収 + repo 明示):
```bash
git rev-parse --show-toplevel # -> JA_ROOT(絶対パス)
gh repo view --json nameWithOwner -q .nameWithOwner # -> OWNER/REPO
printenv ORG_TRANSPORT ORG_BROKER_STATE_DIR PATH # -> transport env(Refs #653 #658)
```
- `gh repo view` が失敗する場合はユーザーに「リポジトリを自動解決できません。
`--repo OWNER/REPO` を指定してください」と報告して中断。pr-watch.sh 自身も `--repo`
省略時は auto-resolve するが、ここで明示することで **pane の cwd に依らず repo を固定**
する(cwd trap が repo 解決にも波及しないようにする)。
- **transport env の捕捉(Refs #653 #658 — env trap 吸収)**: `printenv` で窓口
(secretary)ペインの `ORG_TRANSPORT` / `ORG_BROKER_STATE_DIR` / `PATH` を確定させる。
`mcp__org-broker__spawn_pane` は **汎用 CLI ペイン**を env 注入なしで立てるため(本 skill 上部の
注記)、これらを Step 3 の `command` に**前置注入しないと** spawn されたペインの
`tools/peer_notify.py` が `ORG_TRANSPORT` 未設定で silent no-op に落ちる。
`cwd` が cwd trap を吸収するのと同じ理屈で、この env 捕捉が **env trap** を吸収する。
`ORG_TRANSPORT` が空 / 未設定なら Step 3 で `export ORG_TRANSPORT` を**省く**。
これは**窓口ペインの解決結果をそのまま鏡写しにする**ための省略である(PR #73 障害の
経緯と、未設定の意味が renga → broker に変わった Refs #941 の経緯は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §3)。
`ORG_BROKER_STATE_DIR` も set のときだけ前置する。
## Step 2: 冪等チェック(同一 PR の二重監視を防ぐ)
`mcp__org-broker__list_panes` を呼び、`name="pr-watch-<PR>"` の live pane が既に存在するか確認する。
- **存在する** → 既に監視中。**spawn せず**「PR #<PR> の CI 監視ペイン
(`pr-watch-<PR>`, id={N}) は既に稼働中です」と報告して終了。再起動したい場合は先に
Step 5 の手順でそのペインを close してから再実行するよう案内する。
- **存在しない** → Step 3 へ。
> pane name `pr-watch-<PR>` が冪等キー。`<PR>` は数字だが `pr-watch-` プレフィックスで
> 英字を含むため許可文字 `[A-Za-z0-9_-]` を満たし、全桁数字(= id 扱いで曖昧化)にもならない。
## Step 3: 監視ペインの spawn
### Step 3-0: 張り先(アンカー)を幾何で決める(Refs #335)
spawn の前に、**どのペインを split 起点にするか**を決定的ツールで求める。target は
固定しない(旧版の `target="dispatcher"` 固定が生んだ実害の経緯は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §2)。
1. `mcp__org-broker__list_panes` を呼び、返却された `panes` 配列(`id` / `name` / `role` /
`x` / `y` / `width` / `height`)をそのまま JSON として控える。
2. その JSON を `tools/pick_watcher_anchor.py` に stdin で流し、候補リストを得る
(既定入力が stdin なので中間ファイルを作らない。ファイル経由なら `--panes-json <path>`):
```bash
python3 tools/pick_watcher_anchor.py --format text <<'PANES'
{"panes": [ ... list_panes の返却をそのまま貼る ... ]}
PANES
```
(Windows は `py -3 tools/pick_watcher_anchor.py ...`。POSIX 側は `python` エイリアスが
無い環境があるため `python3` で呼ぶ。transport は `ORG_TRANSPORT` から自動解決される
ので通常は指定不要。明示するなら `--transport {broker|renga}`。)
3. 出力の `candidates` が **rank 1 から順に試す張り先**。各候補は `target`(pane name)と
`direction`(`vertical` / `horizontal`)を持つので、**両方をそのまま次の
`spawn_pane` 引数に使う**(direction も候補ごとに変わる。`vertical` 固定ではない)。
direction は「両方向を評価し、親側に残る子が大きい方を採る」規則(runtime の
`_split_options` と同一。同値性は unit test で固定)。**窓口が direction を自分で
決めない**(実害の経緯は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §2)。
4. `candidates` が空(exit code 2 / `capacity_exhausted: true`)のときだけ、**このタブに
watcher を置く余地が本当に無い**。spawn を試みず、`rejected` の各行(どのペインが
どの床値でどう落ちたか)を添えて人間に報告し、指示を仰ぐ。
出力の `pane_cap_reached` は**助言であって判定ではない**: 「このタブのペイン数が renga の
per-tab 上限(`RENGA_MAX_PANES` = 16)に達している」という事実で、renga ではこれ以降の
spawn が幾何によらず拒否される。既定の broker には per-tab 上限が無い(各ペインが独立
セッション)ので、`capacity_exhausted` はこの値では動かない。`[split_refused]` が続いた
ときの人間報告に添える材料として使う。
ツールが守る床値(`MIN_PANE` 20x5 / `SECRETARY_MIN` 120x30 / `DISPATCHER_MIN_WIDTH` 80)は
`claude_org_runtime.dispatcher.runner` の定数を **import して** 使う(skill 側にも
ツール側にも値を写経しない)。優先度は **dispatcher →(既存 watcher ペイン。dispatcher
隣接を先)→ secretary**、dispatcher が自身の comfort 幅を割っている場合だけ最後尾へ降格。
secretary を張り先に使うのはユーザー承認済みで、`SECRETARY_MIN_*` を
満たす split のみ候補になる。既存 watcher には attention watcher(`role="attention"`)も
含む。worker / curator ペインは候補に入れない(稼働中の作業ビューポートを watcher が
食わないため)。
### Step 3-1: spawn
`mcp__org-broker__spawn_pane` で CLI watcher ペインを起動する(`<...>` は Step 1 / 3-0 / 引数で確定した値に置換):
```
mcp__org-broker__spawn_pane(
target="<Step 3-0 の候補 target>",
direction="<Step 3-0 の候補 direction>",
role="watcher",
name="pr-watch-<PR>",
cwd="<JA_ROOT 絶対パス>",
command="nocorrect true 2>/dev/null || true; export ORG_TRANSPORT='<ORG_TRANSPORT>'; export ORG_BROKER_STATE_DIR='<ORG_BROKER_STATE_DIR>'; export PATH='<PATH>'; mkdir -p .state; bash tools/pr-watch.sh <PR> --repo <OWNER/REPO> --merge-watch --no-detach 2>&1 | tee -a .state/pr-watch-<PR>.log; tmux kill-pane -t \"$TMUX_PANE\" 2>/dev/null || true"
)
```
- **`nocorrect true 2>/dev/null || true;` 前置(Issue #825 — zsh correctall 無言停止の根治。必須・置換禁止)**:
`command` は対話シェルに打鍵される形で実行されるため、pane の login shell が zsh で
スペル自動訂正(`setopt correctall`)が有効だと、残留 `.state/pr-watch-*.log` に類似した
新規ログ名が `zsh: correct '...' to '...' [nyae]?` の確認プロンプトを発火させ、
**パイプライン全体が一度も走らないまま無言停止**する。行頭の `nocorrect` は zsh の
precommand modifier(reserved word)で、パース前に解釈され**その行全体の全 word のスペル
訂正を無効化**する(`;` 連結の後続コマンドにも効く)。実発生ログと実機確認の記録は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §4。
- **payload を持たない犠牲文として独立させる理由(非 zsh 互換)**: `nocorrect` は zsh 以外の
シェルにコマンドとして存在しない。`nocorrect export ...` と payload に直結すると、bash 等が
login shell の pane では `nocorrect: command not found` で **export 文ごと失敗**し、transport
env 注入(次項)が silent に失われる。単独文
`nocorrect true 2>/dev/null || true;` なら zsh では行全体の訂正抑止・bash 等では犠牲文
だけが無音で失敗し、`;` 以降の後続は全て実行される。非対話シェル実行(`zsh -c` 等)でも
no-op で副作用はない。
- **`2>/dev/null` は省略不可(Step 4 の誤殺防止)**: 非 zsh シェルでは犠牲文が
`nocorrect: command not found` を stderr に出す。この行が画面に残ると Step 4 の
negative-signal 判定(`command not found` = 起動失敗)に誤マッチし、**正常起動した
watcher を健全なまま close する false positive** になるため、犠牲文の stderr は行内で
捨てる。
- **`|| true` も省略不可(errexit 耐性)**: 非 zsh シェルの rc で `set -e`(errexit)が
有効だと、犠牲文の失敗(status 127)でシェルごと終了し **export / mkdir / watcher 本体が
一切走らないまま pane が死ぬ**。`|| true` で犠牲文を非致命化する。
- `<...>` placeholder ではない**固定文字列**であり、窓口は値に置換せずそのまま残す。下記の
条件付き前置で export 文を省いた場合も、`nocorrect true 2>/dev/null || true;` は
**常に行頭に残す**。
- **env 前置注入(Refs #653 #658 — 必須。PR #73 障害の根治)**: 犠牲文に続く
`export ORG_TRANSPORT=...; export ORG_BROKER_STATE_DIR=...; export PATH=...;` は Step 1 で
`printenv` 捕捉した窓口ペインの実値に置換する。これが無いと汎用 spawn ペインは transport
env を継承せず、`peer_notify` の broker/renga 経路がどちらも未設定分岐に落ちて **push が
silent no-op** になる(events テーブルへの `ci_completed` 書き込みは成功するのに窓口へ届かない)。
`PATH` 注入は broker 経路が shell out する `claude-org-runtime
broker send` CLI(venv 内)を pane の PATH で解決可能にするため。
- **条件付き前置(窓口ペインの解決を鏡写しにする)**: `ORG_TRANSPORT` が空 / 未設定なら
`export ORG_TRANSPORT=...` を**丸ごと省く**。未設定を渡された watcher ペインは窓口ペインと
同じ `resolve()` を通って同じ transport(既定は `broker`)に着地するので、省略は
「窓口と同じ解決結果を継がせる」ことを意味する。`ORG_BROKER_STATE_DIR` も
set のときだけ前置する。空値を `''` で明示 export すると broker 経路が既定 state dir を
掴む誤動作を招くため、**空なら export 文自体を書かない**。
- **多層防御の位置づけ**: この env 注入は **path A(低遅延 push)の修理**であって単独の保証では
ない。注入漏れ / push 失敗が起きても (B) ディスパッチャーの relay と `notify_failed` の
fail-loud 記録が「見逃しゼロ」を担保する(PR #73 障害の経緯・Refs #941 の理由付け変更・
多層防御の内訳は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §3)。
- `target` / `direction`: **Step 3-0 のツールが返した候補**をそのまま使う。broker では
各ペインが detached 独立セッションだが、addressing scope(同一タブ MUST、contract
Surface 4.2)を満たすため既存ペインを起点に取る点は不変。
- **なぜ固定アンカーをやめたか(Refs #335)**: 旧版は `target="dispatcher"` 固定だった。
2026-08-30、幅 24 まで細った dispatcher に張ろうとして `[split_refused]` になり、
397x53 の secretary ペインが丸ごと空いているのに窓口が「タブ満杯」と誤読して worker
派遣を待機させる実害が出た。`[split_refused]` は**その target を割れないという局所の
事実**であって、タブ全体の容量を語らない。よって張り先は毎回 `list_panes` の幾何から
決定的に選び直す(renga 側のコード分離は suisya-systems/renga#335)。
- `role="watcher"`: list_panes で監視ペインを識別する表示ラベル(attention watcher の
`role="attention"` と同じく canonical 4 role 以外のラベル。broker では token の auth tier
は spawn 時に固定で、role ラベルは tier を変えない — Surface 8)。
- `cwd`: **Step 1 で解決した JA_ROOT 絶対パス**。これにより pane 内の `tools/pr-watch.sh` /
`.state/pr-watch-<PR>.log` が ja-root 基点で resolve される(cwd trap 吸収)。
- **`--no-detach` 必須(Issue #650)**: `tools/pr-watch.sh` は Issue #641 対策で既定
setsid + nohup の自己 detach をするため、`--no-detach` を付けないと spawn 直後に親 bash が
exit して broker pane が即時掃除され、watcher が孤児化する(pane が無いので `/org-attach` /
`Ctrl-b s` でも覗けない)。`--no-detach` で前景動作させ、`tee` と末尾 self-close の
自己終了サイクルを成立させる。
- **`Ctrl-b s` は tmux prefix の既定値前提**: prefix を変更している場合は設定した prefix に
読み替える。さらに、**覗く端末が renga の場合はこの打鍵が届かない** — renga の org
サイドバーは既定で有効なあいだ `Ctrl+B`(tmux prefix `Ctrl-b` と同じ物理入力)を消費して
PTY へ渡さないため、pane が生きていても `Ctrl-b s` でセッション切替できない。回避策
(renga 設定 `[ui] org_sidebar = "off"` または tmux prefix の変更)は
[`docs/operations/dispatcher-view.md`](../../../docs/operations/dispatcher-view.md) の
「外側フレームが renga の場合」を参照。
- `command`: pr-watch を前景実行し、stdout/stderr を `.state/pr-watch-<PR>.log` に `tee -a`
(tmux スクロールバッファにも出る二段)。先頭 `mkdir -p .state` で fresh clone でも tee の
出力先を確保する。pr-watch 終了後に `tmux kill-pane -t "$TMUX_PANE"`
で **ペインを自己 close**(broker の tmux backend でのみ効く低遅延経路。`|| true` は tmux ペイン
でない環境 = herdr / wezterm / renga で失敗を握り潰すためのもので、**そこでは自動 close されず
窓口のイベント駆動 close が正路**になる。前掲「前提」節の 2 分類)。
- **`$TMUX_PANE` は placeholder ではなく実行時 env**: `<PR>` / `<OWNER/REPO>` と違い
`$TMUX_PANE` は窓口が値に置換してはならない。tmux ペインとして spawn された場合に shell へ
自動露出する自ペイン id(例 `%16`)で、self-close 時に **その pane 自身**を明示 target 解決する。
旧形 `tmux kill-pane`(target 無指定)は現在ペインを暗黙推定するが、`-t "$TMUX_PANE"` で
明示することで曖昧さを排す(Issue #647 提案 1 の「明示 target 指定」)。
- **tmux ペインでなければ未設定で無言失敗する(Issue #911)**: renga のペインでは
`printenv TMUX TMUX_PANE` がどちらも未設定を返すため、この行は `tmux kill-pane -t ""` に
展開され `2>/dev/null || true` で無言失敗する(herdr / wezterm も同様に tmux ペインでない)。
**この失敗はエラーとして表に出ないので、残留の検知を self-close の成否に依存させない。**
- **socket は `$TMUX` 継承をそのまま使う(`-L` で固定しない)**: `tmux` を `-L` 無しで
起動すると、ペインが属する tmux server の socket を `$TMUX` から自動解決する。broker では
それが `claude-org-broker` socket、非既定 socket 構成では別 socket になるが、いずれも
`$TMUX` が正しい server を指すので kill が当たる。ここで `-L claude-org-broker`
と固定すると非既定 socket 下で **別 server に当たって self-close が無言で失敗**
するため、socket は固定しない(renga では `$TMUX` 自体が無いので、そもそもこの経路に乗らない)。
- **self-close は(効いた場合も)tmux 層だけを掃除する**: `kill-pane` は broker socket 上の実 tmux ペイン
を消すので、直後から `list_panes` には現れなくなる。ただし broker daemon の pane 登録簿
(name binding)は self-close では pop されず **stale に残りうる**(daemon は自 pane の外部
kill を検知しないため)。stale binding が残ると同名 `pr-watch-<PR>` の再 spawn が
`[name_taken]` で弾かれる(`list_panes` には出ないのに、が症状)。この掃除は Step 5 の
手動 fallback で行う。**そこで撃つ `mcp__org-broker__close_pane(target="pr-watch-<PR>")` は、
数値 pane_id を列挙から取り直せないこの状態に限って裸 name を許可する transport 条件付きの
allowlist 経路**であり、無条件の name 指定ではない(3 条件と broker 以外での扱いは Step 5 の
(b) が SoT)。
- `--merge-watch`: CI green で `CI_COMPLETED` を出した後もマージまで poll し続け(最大
24h)、マージで `PR_MERGED`、timeout で `PR_MERGE_WATCH_TIMEOUT` を出してから自己 close を
試みる。CI 確定だけで止めたい場合は呼び出し時に `--merge-watch` を外す(その場合は CI green
/ failed 確定で自己 close を試みる)。いずれも実際に閉じるのは broker の tmux backend のみで、
herdr / wezterm / renga では窓口のイベント駆動 close が掃除する。
- pr-watch.sh の既存メッセージ形・event payload 形は **本 skill では一切変更しない**(不変条件)。
既存の手動 `tools/pr-watch.sh` 起動経路(人間の `!` 経由など)も従来どおり動作する。
戻り値 `"Spawned pane id=N."` の N を控える。
**spawn 失敗時の分岐**(MCP 結果テキストの `[<code>]` で判定。詳細は
[`.claude/skills/org-delegate/references/renga-error-codes.md`](../org-delegate/references/renga-error-codes.md)):
- `[split_refused]` → **候補リストを rank 順に 1 段ずつ降りて再試行する(各候補は 1 回だけ)**。**このコードは「その target を
今の幾何では割れない」というターゲット局所の失敗を含む**(free-pane 不足だけでなく、
細ったアンカー 1 枚の MIN_PANE 割れでも返る)。**1 件の拒否からタブ満杯と結論しない —
容量判断は Step 3-0 の幾何計算(`list_panes` × 床値)だけが行う**:
1. Step 3-0 の `candidates` から**次の rank** を取り、その `target` / `direction` で
Step 3-1 の spawn を **1 回だけ**再試行する。
2. 再試行も `[split_refused]` なら、さらに次の rank へ進む(`candidates` の末尾まで)。
レイアウトが動いた疑いがあるときは Step 3-0 を 1 度だけ引き直してよい。
3. **`candidates` を使い切ったときだけ**「監視ペインを作る空きがありません(ターミナルが
狭い / pane 上限)。ターミナルを広げるか不要ペインを閉じてから再実行してください」と
報告して中断する。報告には試した target 一覧と Step 3-0 の `rejected` 行(どの床値で
落ちたか)を添える。
- `[pane_not_found]`(候補 target が既に消えている)→ レイアウトが spawn 前後で動いた
race。Step 3-0(`list_panes` → ツール)を **1 度だけ**引き直して最新の rank 1 で再試行する。
引き直しても候補が空 / 同じく `[pane_not_found]` なら、`/org-start` 未実行を含む想定外
として状況を人間に報告して中断。
- `[name_in_use]` / `[name_taken]` → **live pane と stale 登録簿を切り分ける**(前 watcher の
self-close で tmux ペインは消えたが broker 登録簿に name binding が残る「二層の不整合」を
自己回復する):
1. `mcp__org-broker__list_panes` で `name="pr-watch-<PR>"` の **live pane が実在するか**再確認する。
2. **live pane が在る** → 冪等チェックを取りこぼした真の race。既に監視中として Step 2 の
「既に稼働中」報告に倒す(新規 spawn しない)。
3. **live pane が無い**(`list_panes` に出ない)→ self-close 済みの **stale 登録簿 binding**。
この状態は列挙にペインが出ないため **数値 pane_id を取得できず**、Group B の
「数値 pane_id で撃つ」原則をそのまま適用できない。よってこの掃除だけは **transport 条件付きの
allowlist** として裸 name の `close_pane` を許可する(契約
[`docs/contracts/backend-interface-contract.md`](../../../docs/contracts/backend-interface-contract.md)
T-§4.2 の Group B 台帳が stale-binding 行に求める「使った mechanism」がこれ。条件の並びと
根拠の SoT は下記 Step 5 の (b))。**以下 3 条件がすべて成立するときだけ許可される**:
- **(1) いま Group B を駆動している backend が `close_pane` / `set_pane_identity` を自身の
single-tab モデル内で解決する**(= `org-broker`)— 誤タブ hazard が構造的に生じない
(契約 §8.1 / §8.10)。**判定は「いま Group B を撃つのに使っている MCP ツールの
完全修飾名が `mcp__org-broker__*` である」という積極的な証拠で行う**。
**`DEFAULT_TRANSPORT` から推定してはならない** — 判定規則と根拠の SoT は下記 Step 5 の (b)。
確定できない場合は不成立として扱う
- **(2) 再 spawn が `[name_in_use]` / `[name_taken]` で弾かれている** — stale binding の症状
(本分岐の発火条件そのもの)
- **(3) その name が `mcp__org-broker__list_panes` に現れない** — live pane 不在(上記 1. の再確認結果)
- **3 条件が揃う場合**: `mcp__org-broker__close_pane(target="pr-watch-<PR>")` で name 解決させて登録簿を
pop し(`ok closed=%N` が返る。`[pane_not_found]` は既に掃除済みで OK)、**Step 3 の spawn を
1 度だけ再試行**する。再試行でも `[name_taken]` が続く場合はユーザーに報告して中断
(想定外の登録簿状態)。
- **broker 以外に解決する場合(`ORG_TRANSPORT=renga` の opt-in など)では close せず
報告して中断する**(「live pane が無い」という前提が renga の legacy 解決では偽になりうる
ため。機序は [`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md)
§7)。自動再試行もせず、
stale binding を検出したが transport が broker でないため自動掃除しない旨をユーザーに
報告して指示を仰ぐ。
- broker 固有(`[no_backend]` / `[token_invalid]` / `[session_invalid]` /
`[tool_not_authorized]` / `[peer_not_found]` 等)/ その他未知コード → 状況をユーザーに
報告して中断(default-branch escalate)。
## Step 4: identity 登録と起動 health check
1. **identity 確定(role=watcher の登録)**: spawn_pane の `name` / `role` が反映されたか
`mcp__org-broker__list_panes` で確認する。`name="pr-watch-<PR>"` かつ `role="watcher"` が付いて
いれば登録済み。万一いずれかが欠ける backend では
`mcp__org-broker__set_pane_identity(target=<N>, name="pr-watch-<PR>", role="watcher")` で補修する。
- **補修も Group B なので自タブ確立が先(契約 T-§4.2「Fail-safe consequence for Group B」。
[`docs/contracts/backend-interface-contract.md`](../../../docs/contracts/backend-interface-contract.md))**:
`set_pane_identity` は `close_pane` と同じ Group B で、宛先は「**自タブと独立に確立済みの
列挙**から得た数値 pane id」に限られる。数値であることは MUST の**片方**にすぎず、**id が
spawn の戻り値として手元にあることも免除にならない**(未確立の列挙では、直前の `name` /
`role` 確認の結果そのものを信用できないため)。確立手段は 2 つだけで、いずれか 1 つが成立
すればよい: **(i) backend が Group B を自身の単一タブモデル内で解決する**(`org-broker`。
契約 §8.1 / §8.10)/ **(ii) `caller_scope` を確立できている**(契約 T-§cap。
`caller_scope_close_identity` から導出しない)。**どちらも成立しないなら補修を撃たず**、
identity が未登録のまま監視が走っていること(Step 2 の冪等チェックと Step 5 の cleanup が
`name` / `role` で引けなくなること)をユーザーに報告する。`target="focused"` や裸 name の
相対セレクタへは**フォールバックしない** — `set_pane_identity` の `target` は既定が
`"focused"` なので、人間がフォーカスを移していれば**別ペインを改名する**。
- 本ペインは Claude セッションではなく CLI プロセスなので **Claude peer(peer_id)は
持たない**。ここでの「peer 登録」= pane registry への name + role=watcher の登録
(spawn_pane / set_pane_identity が行う)を指す。MCP peer / dev-channel 登録は発生しない。
2. **即時クラッシュ / 対話プロンプト停止の検出(negative-signal のみ)**:
`mcp__org-broker__inspect_pane(target=<N>, format="text", lines=<ペイン高さ以上>, include_cursor=true)`
で出力を**全画面**読む(Issue #825)。`lines` は `mcp__org-broker__list_panes` の geometry で分かる
ペイン高さ以上、高さが取れなければ余裕を取って `lines=200` を指定する。末尾 15-40 行だけの
読み取りは、画面**上部**に出た確認プロンプト + 下部空白を「静かな正常起動」と誤読する
(見逃した実例は [`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md)
§5)。`include_cursor=true` は下記
「行末 `?` + 入力待ち」判定に必要なカーソル位置を返させるため必須(既定 false では
カーソル情報が返らず、ブロック中のプロンプトと通常出力を区別できない)。
以下のいずれかを検出した場合のみ「起動失敗」と判定:
- `command not found` / `is not recognized` / `No such file or directory`
- `gh: ... not found` 等 gh 不在 / `Traceback (most recent call last)` / `ModuleNotFoundError`
- 出力末尾に shell prompt(`$ ` / `% ` 末尾露出)= command が即時終了して shell に戻った
- **対話プロンプト形跡(Issue #825 で追加)**: `[nyae]?`(zsh correctall の
`zsh: correct '...' to '...' [nyae]?`)/ `(y/n)` / `[y/N]` のリテラル、または行末が `?` で
終わる行に `cursor` が乗ったまま(= その行で入力待ち)後続出力が無い。いずれもコマンドが
**一度も走らないまま**シェル層の確認プロンプトで停止している形跡で、放置すると監視ゼロの
無言死になる(correctall 停止なら Step 3 の `nocorrect` 前置漏れを疑う)。
- 上記いずれも無ければ(pr-watch の watch ループ出力 / 空 / 起動直後の静止)**起動成功扱い**
とし、固定 sleep を入れて再 inspect する経路は持たない(健全な quiet start を誤殺しない)。
- 起動失敗時は死んだペインを掃除し、原因(`tools/pr-watch.sh` / `gh` の導入、cwd、対話プロンプト
停止)をユーザーに報告して中断する。掃除は **自タブ確立 → identity 再確認 → 数値 close** の
順で行う:
1. **自タブ確立**(契約 T-§4.2「Fail-safe consequence for Group B」。
[`docs/contracts/backend-interface-contract.md`](../../../docs/contracts/backend-interface-contract.md)):
**(i) backend が Group B を自身の単一タブモデル内で解決する**(`org-broker`。契約
§8.1 / §8.10)/ **(ii) `caller_scope` を確立できている**(契約 T-§cap)のいずれか 1 つが
成立すればよい。**どちらも成立しないなら close を撃たず**、死んだペイン (id=`<N>`) が
残る旨を報告に含めて手動掃除に委ねる(相対セレクタへはフォールバックしない)。**id が
spawn の戻り値として手元にあることは免除にならない** — 未確立の列挙では次の identity
照合の結果そのものを信用できないため
2. **identity 再確認(pane_id recycle 対策。他の全経路と揃える)**: `mcp__org-broker__list_panes` で
`<N>` のレコードを引き、`name="pr-watch-<PR>"` かつ `role="watcher"` を**なお指している**
ことを確かめる。別ペインへ再割当て済み / 列挙に現れない場合は **close せず**、その旨を
報告に含める(本 Step の「identity 確定」で補修を撃てなかった backend ではこの照合が
通らないので、同じく close せず報告に倒す)
3. 両方を通ったときだけ `mcp__org-broker__close_pane(target=<N>)` する(`[pane_not_found]` /
`[pane_vanished]` は直前に消えた扱いで skip)
3. **生存確認は副作用ベースで行う(`pgrep -f` 単独判定の禁止、Issue #825)**: 起動後に
「監視が本当に走っているか」を確かめるときは、プロセス一覧ではなく**副作用**を見る:
- **`pgrep -f "pr-watch"` 単独を生存判定に使わない**。spawn されたペインのラッパーシェルの
argv にはコマンド全文(`pr-watch.sh` を含む)が乗るため、確認プロンプト停止中で
パイプラインが一度も走っていなくても**シェル自身にマッチして偽陽性**になる(誤認の実例は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §5)。
- 一次の副作用は **`.state/pr-watch-<PR>.log` の生成**: Step 3 の `tee -a` はパイプライン
開始と同時にログファイルを open/生成するため、fresh なログ名なら「ファイルが出来ている」=
パイプラインが実際に走った確証になる(プロンプト停止ではコマンド自体が実行されないので
ログは生成されない)。同名の残留ログがある再監視では生成有無で判別できないため、上記 2 の
全画面 inspect(プロンプト形跡なし)と組み合わせて判定する。
- 判定確定の副作用は `.state/state.db` events テーブルの `ci_completed` 等の canonical
event 行(本 skill 冒頭の二経路)。なお `pr_watch.py` は起動 banner を出力しないため、
ログが空のまま静止していても quiet start でありうる(誤殺しない)。
## Step 5: 監査記録と報告 / 手動 close
1. journal に起動を best-effort で記録する:
```bash
bash tools/journal_append.sh pr_watch_pane_started pr=<PR> repo=<OWNER/REPO> pane_id=<N>
```
Windows native では `py -3 tools/journal_append.py pr_watch_pane_started pr=<PR> repo=<OWNER/REPO> pane_id=<N>`。
**この行は監査ログではなく、watcher 生存判定の一次証拠である(Refs #978)**: 記録を落とすと
[`tools/watcher_restart_guard.py`](../../../tools/watcher_restart_guard.py) は「watcher なし」
(`missing`)と判定する(画面にペインが見えていてもである — ペインの存在は監視の生存を意味
しない、が同ガードの前提)。best-effort とは「失敗しても spawn 自体は巻き戻さない」の意味
であって、省略してよいという意味ではない。
記録したら、それが判定に反映されたことをその場で確認する:
```bash
python3 tools/watcher_restart_guard.py check --task <task_id>
```
exit 0(`live`)なら「最後の push より後に開始された watcher がある」ことが events の時系列
から機械的に確認できた状態。exit 3 が返る場合は 1. の記録が入っていないか、この watcher が
最後の push より前に起動している(=立て直しが必要)。cross-repo で task が引けない場合は
`check --pr <PR> --repo <OWNER/REPO>` でもよい(run 行から baseline を逆引きする)。
2. ユーザーに報告する:
```
PR #<PR> の CI / マージ監視ペイン pr-watch-<PR> (id={N}) を起動しました。
- ログ: .state/pr-watch-<PR>.log(tmux スクロールバッファにも出力)
- 監視終了(マージ / CI 失敗確定 / timeout のいずれか)で、broker の tmux backend では
ペインが自動で閉じます。herdr / wezterm backend と renga では自己 close が効かず残留する
ため、窓口が監視終端でイベント駆動 close します(org-pull-request の各終端処理)。
確定した CI 判定は `.state/state.db` の `ci_completed` 行とログに残るので、
ペインが閉じても判定は失われません(merge gate はそこを読む)。
- tmux で直接見るには `/org-attach` のコマンドを使ってください。
```
3. **監視終端クローズ / 手動 close(Issue #647 提案 3 / Issue #751 / Issue #911)**: self-close の
効き方は watcher ペインの実体が tmux ペインかどうかで決まる(前掲「前提」節の 2 分類)。
**herdr / wezterm backend と opt-in renga では self-close が no-op で watcher
ペインが必ず残留する**ため、監視終端(PR_MERGED / PR_MERGE_WATCH_TIMEOUT / CI 失敗確定)で
窓口がイベント駆動で watcher ペインを掃除するのが正路になる
([`.claude/skills/org-pull-request/SKILL.md`](../org-pull-request/SKILL.md) の各終端処理で発火。
renga では下記 (a) の自タブ確立が `caller_scope` 依存で、確立できなければ close を撃たず
残留を報告する = 無言残留を可視な残留に変えるところまでが本経路の効果)。
broker の tmux backend では self-close が tmux ペインを消すが登録簿の name binding は残りうる
(前掲「self-close は(効いた場合も)tmux 層だけを掃除する」)。掃除は下記 (a)/(b) の split に従う。**窓口の
イベント駆動 close(監視終端)では、下記に加えて「spawn 時に控えた pane_id + 監視対象 head に束縛し、
終端イベントの head が追跡中 instance と一致するときだけ close する」freshness gate を必ず併用する**
(終端イベントが遅延 / 重複配送されて同一 PR の watcher が既に再起動済みの場合、`name` で live pane を
再導出すると新 watcher を解決してその数値 pane_id を close しても replacement monitor を誤 close する。
束縛と freshness gate の SoT は
[`.claude/skills/org-pull-request/references/watcher-cleanup.md`](../org-pull-request/references/watcher-cleanup.md))。
人間が現ペインを手動 close する (a)/(b) は現 instance が対象で自明なので freshness gate は不要:
- **(a) tmux ペインが live のまま残った / 監視を途中で止めたい**: **まず照合に使う
`mcp__org-broker__list_panes` の列挙を自タブのものと確立する**(契約
[`docs/contracts/backend-interface-contract.md`](../../../docs/contracts/backend-interface-contract.md)
T-§4.2「Fail-safe consequence for Group B」)。確立手段は 2 つだけで、いずれか 1 つが成立
すればよい: **(i) backend が Group B を自身の単一タブモデル内で解決する**(`org-broker`。
契約 §8.1 / §8.10)/ **(ii) `caller_scope` を確立できている**(契約 T-§cap。
`caller_scope_close_identity` から導出しない)。**どちらも成立しないなら close を撃たず**、
watcher ペインが残る旨をユーザーに報告して停止する(相対セレクタへはフォールバックしない)。
確立できたら `name="pr-watch-<PR>"` の live pane を確認し、その **数値 pane_id** で
`mcp__org-broker__close_pane(target=<N>)` する(`[pane_not_found]` / `[pane_vanished]` は既に
閉じた扱いで skip)。name 指定ではなく list_panes で identity を確認した数値 pane_id を
使う(id recycle 時の誤 close を避ける)。
- **(a) は「live pane が列挙に出るから安全」ではない**: (b) が carve-out を要するのは
*列挙から数値 id を取り直せない*ためであって、(a) が数値 id を取れることは MUST の
**片方**(相対セレクタでないこと)を満たすにすぎない。もう片方の「その列挙が自タブの
ものか」は (a) でも別に確立しなければならず、未確立の列挙では `name` / `role` 照合の
**結果そのもの**を信用できない(renga の legacy 解決が作る誤 close hazard の機序は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §7)。
- **(b) stale 登録簿 binding(`list_panes` には出ないのに再 spawn が `[name_taken]`)**:
self-close で tmux ペインは消えたが broker 登録簿に name binding が残っている状態。
ペインが列挙に出ないので **数値 pane_id を取得できず**、(a) の「list_panes で identity 照合
した数値 pane_id で撃つ」形が原理的に取れない。この一点に限り **transport 条件付きの
allowlist** として裸 name の `close_pane` を許可する(**本節が 3 条件と根拠の SoT**。契約
[`docs/contracts/backend-interface-contract.md`](../../../docs/contracts/backend-interface-contract.md)
T-§4.2。契約からこの mechanism が導かれる経緯は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §6)。
**以下 3 条件がすべて成立するときだけ許可される**:
- **(1) いま Group B を駆動している backend が `close_pane` / `set_pane_identity` を
自身の single-tab モデル内で解決する**(= `org-broker`)— そのモデル内で name も
解決されるため誤タブ hazard が構造的に生じない(契約 §8.1 / §8.10)。
**判定は積極的な証拠でのみ行う(MUST)**: いま Group B を撃つのに使っている MCP ツールの
**完全修飾名が `mcp__org-broker__*` であること**。これは呼び出しの直前に必ず確定している
(`mcp__org-broker__` は起動時に片方へ解決済み)ので、常に判定できる。
> **`DEFAULT_TRANSPORT` から推定してはならない(MUST NOT)**。`ORG_TRANSPORT` 無設定は
> **運用既定 renga の構成でもありうる**のに
> [`tools/transport.py`](../../../tools/transport.py) の `resolve()` は無設定を
> コード既定 `broker` に解決するため、推定すると **renga が Group B を駆動している環境で
> 裸 name の close を撃ち、別 org の同名 watcher を不可逆に閉じうる**(失敗方向の非対称性・
> 二フレームとの関係・Step 1 の `printenv` 省略が別論点である理由は
> [`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §6)
- **確定できないときは carve-out を取らない**(fail-safe): `ORG_TRANSPORT` に未知値が
入っていて解決が `ValueError` になる等で「いま何が駆動しているか」を確定できない場合は、
条件 (1) を**不成立**として扱い、下の「broker 以外」と同じくユーザーに報告して指示を仰ぐ
- **(2) 再 spawn が `[name_in_use]` / `[name_taken]` で弾かれている** — stale binding の症状
- **(3) その name が `mcp__org-broker__list_panes` に現れない** — live pane 不在(=列挙から数値
pane_id を取れない、この allowlist が必要になっている当の条件)
- **3 条件が揃う場合**: `mcp__org-broker__close_pane(target="pr-watch-<PR>")` する(broker が name →
stale pane_id を解決し登録簿を pop、`ok closed=%N` が返る。`[pane_not_found]` は既に
掃除済みで OK)。掃除後は同名 spawn が通る。Step 3 の `[name_taken]` 分岐はこの (b) を
自己回復するが、手動でも同手順で掃除できる。
- **broker 以外に解決する場合(`ORG_TRANSPORT=renga` の opt-in など)では裸 name に
フォールバックしない**(「live pane が無いので誤 close の余地が無い」という前提が renga の
legacy 解決では偽になりうるため。機序は
[`.claude/skills/pr-watch-pane/references/rationale.md`](references/rationale.md) §7)。
この経路では close せず、stale binding を検出した旨と `pr-watch-<PR>` の
再 spawn が弾かれる状態であることをユーザーに報告して指示を仰ぐ。
- **控えた pane_id での close にも倒さない**: `list_panes` で再確認できない retained id を
close に使うのは (a) が防いでいる pane_id recycle hazard を素通りさせるため、本 skill は
採らない(`[name_taken]` が続く場合と同じくユーザー報告に倒す)。
Files in this skill
- SKILL.md
- SKILL.md.in
- references/rationale.md
- references/transport-duality.md
- references/transport-duality.md.in
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.