一键导入
org-suspend
組織を中断し、全状態をディスクに保存する。「中断」「保存して終了」 「閉じたい」「一旦やめる」「今日は終わり」と言われたときに使う。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
組織を中断し、全状態をディスクに保存する。「中断」「保存して終了」 「閉じたい」「一旦やめる」「今日は終わり」と言われたときに使う。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
ワーカーClaudeを派遣して作業を委譲する。窓口は司令塔であり、 手を動かす実作業は原則としてワーカーに任せる。 ユーザーから作業の依頼を受けたとき、ファイル編集・実装・調査等の 実作業が発生する場合に発動する。
組織の全ロール(窓口・ディスパッチャー・キュレーター・ワーカー)に必要な Claude Code の許可設定・環境変数を一括で配置・更新するスキル。 「設定して」「許可設定を更新して」「セットアップして」 「permissions設定」「org-setup」等で発動する。
open Issue を triage して「次の仕事候補(N 件 + 推奨 1 件)」を窓口が人間へ提示する。 決定的ツール tools/work_discovery_scan.py を 1 回実行し、その候補 JSON を 設計書 §5.2 の人間可読フォーマットでレンダリングするところで停止する(propose-only)。 起動主体は窓口に限定。手動 / イベント起動のみ(常駐 /loop なし)。 「次の仕事候補出して」「triage して」「次なにやる?」や PR マージ後の proactive next-dispatch で窓口が手動起動する。
蓄積された生の学び(knowledge/raw/)を整理・統合する。 ディスパッチャーが worker クローズ時の閾値チェック (tools/check_curate_threshold.py) 超過でオンデマンド起動した キュレーターから 1 回だけ呼び出される(常駐 /loop は廃止)。 手動で「知見を整理して」と言われたときにも使う。
委譲プロセスの振り返り。ワーカーへの作業委譲が完了したとき、 委譲の進め方自体を振り返り、プロセス改善の知見を記録する。 さらに、完了タスクの作業パターンをwork-skillとして蓄積すべきか判断する。 実作業の技術的な振り返りはワーカーが自動的に行うため、ここでは扱わない。
skill の棚卸し(廃止候補 / 重複統合 / owner 明記チェック)。 状態ベースで発火する: 候補キュー knowledge/skill-candidates.md の pending が 5 件以上、 または .claude/skills/ 配下の work-skill 数(org-* を除く)が 20 以上になった場合のみ実行。 時間ベースの /loop では起動しない(変化の無い日に raw ログを汚す副作用を避けるため)。
| name | org-suspend |
| description | 組織を中断し、全状態をディスクに保存する。「中断」「保存して終了」 「閉じたい」「一旦やめる」「今日は終わり」と言われたときに使う。 |
| effort | low |
| allowed-tools | ["Read","Bash(bash tools/journal_append.sh:*)","Bash(py -3 tools/journal_append.py:*)","Bash(python -m tools.state_db.importer:*)","Bash(python3 tools/secretary_queue_watcher.py:*)","Bash(py -3 tools/secretary_queue_watcher.py:*)","Bash(rm -f .state/attention_pane.json)","Bash(del .state\\attention_pane.json)","mcp__org-broker__check_messages","mcp__org-broker__close_pane","mcp__org-broker__inspect_pane","mcp__org-broker__list_panes","mcp__org-broker__list_peers","mcp__org-broker__poll_events","mcp__org-broker__send_keys","mcp__org-broker__send_message","mcp__org-broker__set_pane_identity","mcp__org-broker__set_summary","mcp__org-broker__spawn_claude_pane","mcp__org-broker__spawn_pane"] |
全ワーカーの状態を収集し、ディスクに保存し、全ペインを停止する。
curator 不在は正常系(オンデマンド化): キュレーターは常駐しない。state.db の
curator_pane_id/curator_peer_idは null が正常で、list_panes/list_peersに curator が見えないことは異常ではない。curator ペインが存在するのは「worker クローズ起点の オンデマンド curate が実行中に suspend が重なった」一時的なケースのみで、その場合だけ Phase 4 の停止対象に含める。
責務境界(/org-suspend と
/org-down): /org-suspend は 「状態保存 + ja 管理下の補助プロセス(dashboard / secretary_queue_watcher / attention watcher)とペインの停止」までを担い、claude-org-runtime org down(broker daemon の停止)は 呼ばない。suspend 単体は「また/org-startで再開する」前提の中断であり、broker daemon は 走らせたままにする(端末を閉じても daemon はすぐ再開できるよう生存する)。daemon ごと完全に 落とすのは/org-downの責務で、/org-down が suspend の成功を確認した 後にのみorg downを実行する。
ペイン操作は mcp__org-broker__* MCP ツール経由で行う。pane_exited
相当の lifecycle イベントは mcp__org-broker__poll_events で long-poll、画面スクレイプ
は mcp__org-broker__inspect_pane で取得、raw キー入力は mcp__org-broker__send_keys。
輸送層(transport)両系 — 既定
broker/ opt-inrenga: 本ファイル(および各スキル)のmcp__org-broker__*呼び出しは 既定broker(ORG_TRANSPORT無設定)で書いてあり、そのまま従えばよい(既定挙動)。ORG_TRANSPORT=renga(opt-in・切戻し可)では MCP サーバー名がrenga-peersになり、ツールの 完全修飾名がmcp__org-broker__*→mcp__renga-peers__*に機械置換される(引数形・セマンティクスは同一なので手順の論理は変わらない)。輸送依存で手順が変わる点だけ renga 併記する:
- 受信モデル: 既定 broker は push 一次(各ペイン同居の channel sidecar
server:org-broker-channelが broker キューを ~1 秒間隔で claim→notifications/claude/channelで idle セッションへ本文注入。pull = ナッジ +check_messagesは sidecar 不在 / unhealthy / channel 非対応ペイン(codex pull-peer)/ claude.ai login 不在時のフォールバック層)。ORG_TRANSPORT=renga時は dispatcher / worker メッセージが<channel source="renga-peers" …>として in-band で push される。- spawn 儀式: 既定 broker は
--mcp-config <broker>注入による Claude Code folder-trust プロンプトのsend_keys(enter=true)機械承認に加え、push 一次のため channel sidecar を--dangerously-load-development-channels server:org-broker-channelで load し dev-channel 承認プロンプトをsend_keys(enter=true)で機械承認する(2 段承認)。ORG_TRANSPORT=renga時は--dangerously-load-development-channels server:renga-peersの「Load development channel?」を Enter 承認する 1 段。- エラー分岐: 既定 broker は shared codes(
pane_not_found/last_pane/invalid-params)に加え broker 固有[token_invalid]/[session_invalid]/[tool_not_authorized]/[no_backend](= adapter_unavailable)/[nudge_failed]/[peer_not_found]/[name_taken]を返しうる(未知コードは default-branch で escalate)。ORG_TRANSPORT=renga時は broker 固有コードは発生しない。
new_tab/focus_paneは broker surface に無い(意図的除外)。契約面の正本はdocs/contracts/backend-interface-contract.mdSurface 8 + push-primary amendment(broker push 一次が 既定の契約、pull は fallback として retain)。opt-inrengaは削除せず常時有効な切戻しの安全装置として維持する。broker 実走(dogfood)は Epic #6 Issue G スコープで本ファイルの既定運用経路ではない(二フレーム注記(Refs #604): ここの「既定broker」はコード既定(tools/transport.py: DEFAULT_TRANSPORT、生成面はこれで render)。運用既定は broker dogfood が Epic #6 Issue G まで未活性のためrengaで、両者は指す対象が異なり矛盾しない。総説は rootCLAUDE.md。)
mcp__org-broker__list_peers で稼働中のピアを列挙するmcp__org-broker__send_message で以下を送信:
SUSPEND: 現在の状態を報告してください。
1. これまでに完了したこと
2. 変更したファイル(コミット済み/未コミット)
3. 次にやろうとしていたこと
4. ブロッカーや未解決の問題
mcp__org-broker__check_messages で応答を待つ(5 秒間隔でポーリング)応答がなかったワーカーについて:
.state/workers/ から該当ワーカーの状態ファイルを読み、Pane Name と Directory を取得mcp__org-broker__inspect_pane(target="worker-{task_id}", format="text")
画面表示だけでは不十分な場合は、次の Step 3 の git 情報で補完するgit statusgit diff --statgit log --oneline -5state-db cutover (M4, Issue #267):
.state/state.dbが唯一の SoT。 構造化セクション (Status / Updated / Suspended / Dispatcher / Curator / Worker Directory Registry / Active Work Items / Resume Instructions) は 必ず StateWriter 経由で書く。transaction()の post-commit hook が.state/org-state.mdを DB から自動再生成する (markdown 直接編集禁止 — drift_check で検出される)。free-form な session notes / Pending Lead / 学び等はnotes/配下に保存する (notes/README.md参照)。.state/journal.jsonlは M4 で廃止 (events テーブルが SoT)。 DB が古い場合はpython -m tools.state_db.importer --db .state/state.db --rebuild --no-strictで再構築する。
既存の org-state.md を org-state.prev.md にコピー(バックアップ)
DB に Status / Suspended を書く (StateWriter.transaction() 経由。post-commit hook が .state/org-state.md を自動再生成、regen 失敗時も DB は確定済みで stderr 警告のみ):
python -c "
from datetime import datetime, timezone
from pathlib import Path
from tools.state_db import connect
from tools.state_db.writer import StateWriter
ts = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%fZ')
conn = connect('.state/state.db')
with StateWriter(conn, claude_org_root=Path('.')).transaction() as w:
w.update_session(status='SUSPENDED', suspended_at=ts, updated_at=ts)
"
"..." 内の改行をそのまま透過するので multi-line でも cross-shell。Windows CMD は heredoc 不可なので py -3 -c "ts=...; conn=...; w=...; w.begin(); w.update_session(...); w.commit()" の単行 fallback を使う(その場合 transaction() の rollback / regen 自動 swallow は失われるので追加で try/except を書く).state/org-state.md の Status 行を SUSPENDED に切り替える (DB 由来で再生成)notes/ に保存する (notes/README.md 参照)。markdown 直接編集は drift_check で検出される。update_session(resume_instructions=...) は構造化セクションとして DB に書く各 Work Item の状態を更新する場合は upsert_run(task_id=..., status=...) を transaction() 内で呼ぶ
各ワーカーの .state/workers/worker-{id}.md を更新:
suspend イベントを DB に追記 (tools/journal_append.py は M4 で DB-only ルーティング。ts は自動付与):
py -3 tools/journal_append.py suspend \
reason=user_requested \
--json '{"active_workers": ["worker-xxx"], "pending_items": ["blog-redesign"]}'
event 名と payload key の規約は docs/journal-events.md を参照。
kill $(cat .state/dashboard.pid 2>/dev/null) 2>/dev/null || true
注: この blind kill は「/org-start で再開する前提の中断」なので簡素なまま残す。daemon ごと 落とす
/org-downでは、pid recycle による誤 kill を避ける stale-pid-safe な 停止(/proc/Get-CimInstanceの CommandLine 照合)に差し替える。
broker 面(ORG_TRANSPORT=broker)で org-start Block C3 が run_in_background で
常駐させた滞留 watcher を停止する。renga では watcher が存在しない(queue.jsonl 非依存)ので、
transport が renga なら本 Phase はまるごと skipする。
watcher は起動時に .state/secretary_queue_watcher.json へ自分の pid / cwd / cmdline / started_at /
broker_state_dir を記録している。停止は pid 単独で kill せず、(a) 記録された broker_state_dir が
現在の ORG_BROKER_STATE_DIR と一致し(別 org / 別 broker の watcher 誤停止防止)、かつ (b) pid が
生存し live argv(Linux/WSL は /proc/<pid>/cmdline、macOS/BSD は ps -p <pid> -o args= フォールバック)が
本 watcher であることを照合できたときだけ SIGTERM する。照合が外れたら kill せず sidecar を stale として
削除する(誤 kill 防止)。この照合ロジックは helper に入っているので、POSIX では 1 行呼ぶだけでよい:
Mac / Linux / WSL:
python3 tools/secretary_queue_watcher.py --stop # Windows で console python を使う場合は py -3 ...
出力の 1 行(STOP: ...)で結果を確認する(SIGTERM を送信し停止 / stale sidecar を削除 /
既に停止済み)。exit 0 が正常系(停止・stale 掃除・既停止のいずれも 0)。macOS は ps フォールバックで
identity 照合できるので --stop がそのまま効く。exit 2(identity 未確認)は /proc も ps も無い環境
(Windows native)でのみ出るシグナルで、その場合は次の PowerShell 手順を使う。
Windows native(PowerShell) — /proc が無く helper の argv 照合が使えないので、
Get-CimInstance Win32_Process の CommandLine で identity を照合してから Stop-Process する
(kill -0 / kill -TERM の直訳ではなく Windows 別手順):
$pf = ".state\secretary_queue_watcher.json"
if (Test-Path $pf) {
$rec = Get-Content $pf -Raw | ConvertFrom-Json
$wpid = [int]$rec.pid
$ownOk = $false
try {
if ($env:ORG_BROKER_STATE_DIR) {
$ownOk = ((Resolve-Path $rec.broker_state_dir).Path -eq (Resolve-Path $env:ORG_BROKER_STATE_DIR).Path)
} else {
$ownOk = ((Resolve-Path $rec.cwd).Path -eq (Get-Location).Path)
}
} catch { $ownOk = $false }
$proc = Get-CimInstance Win32_Process -Filter "ProcessId=$wpid" -ErrorAction SilentlyContinue
$idOk = $proc -and ($proc.CommandLine -match 'secretary_queue_watcher\.py')
if ($ownOk -and $idOk) {
Stop-Process -Id $wpid -Force
Write-Output "secretary_queue_watcher (pid=$wpid) stopped"
} else {
Write-Output "watcher pid stale / different org / not running; not killing, removing stale sidecar"
}
Remove-Item $pf -ErrorAction SilentlyContinue
}
attention watcher は dispatcher ペインの右 split に常駐する CLI ペインなので、Phase 4 のペイン 一括 teardown より前に停止する(dispatcher を先に閉じると attention ペインが孤児化 / pane_id recycle され、後続の識別を壊すため)。attention watcher を起動していないセッションでは sidecar も live pane も無く、本 Phase は no-op。
停止は /org-attention-stop と同じ identity 照合を使う
(sidecar の pane_id を無検証で close_pane しない。pane_id が別ペインへ再割当てされていると
無関係なペインを kill する — Issue #468):
mcp__org-broker__list_panes で name="attention" または role="attention" の live pane を
全て集める(= 確認済み attention ペイン集合。各 数値 pane_id を控える).state/attention_pane.json を Read で開けたら pane_id を読む(= sidecar pane_id)。無ければ
「sidecar 無し」mcp__org-broker__close_pane(target="<id>") する
(target="attention" の name 指定はしない — role だけ持つ孤児に当たらないため)。
[pane_not_found] / [pane_vanished] は既に閉じた扱いで skiprm -f .state/attention_pane.json # Windows native は del .state\attention_pane.json
reason=stale_sidecar にする(無関係なペインを停めた誤記録を防ぐ):
bash tools/journal_append.sh attention_watch_stopped pane_id=<N> # close した場合
bash tools/journal_append.sh attention_watch_stopped reason=stale_sidecar # close しなかった場合
分類別の詳細な挙動と報告文は /org-attention-stop を参照(本 Phase は
その要点を suspend フローに埋め込んだもの)。
停止順序が重要。ワーカー → ディスパッチャー → キュレーターの順で停止する。
mcp__org-broker__list_peers で稼働中のピアを列挙
ワーカーを先に停止: 全ワーカーピアに mcp__org-broker__send_message で終了を指示:
「SHUTDOWN: 作業を終了してください。」
ワーカーペインが閉じたことを確認 — 2-pass 構造で実施:
Pass 1 (polite shutdown の観察、最大 10 秒):
mcp__org-broker__poll_events で pane_exited を long-poll する。types=["pane_exited"] フィルタで他 type を除外しつつ、deadline 内でループして待機対象が全て閉じたら break:
pending_workers = {全ワーカーの name set}
cursor = None # 初回は since 省略
deadline = now + 10 秒
while pending_workers not empty and now < deadline:
remaining_ms = (deadline - now) ミリ秒
result = mcp__org-broker__poll_events(
since=cursor,
timeout_ms=min(remaining_ms, 10000),
types=["pane_exited"]
)
cursor = result.next_since
for ev in result.events:
if ev.role == "worker" and ev.name in pending_workers:
pending_workers.remove(ev.name)
# deadline 到達 or pending_workers が空で抜ける
since 省略で「今以降のイベントだけ」セマンティクス(過去の pane_exited を replay しない)types=["pane_exited"] filter は cursor を全 type で advance させるので重複 scan なしevents:[] + advanced cursor) するため、空応答時は deadline までループ継続Pass 2 (残留ワーカーへのフォールバック + 再確認、最大 5 秒):
mcp__org-broker__close_pane(target="worker-{task_id}")
でペインを明示破棄する。成功時は "Closed pane id=N." テキストが返る。[pane_not_found] / [pane_vanished] は既に閉じた扱いで skip(references/renga-error-codes.md 参照)。[last_pane] はワーカー停止段階では通常発生しない(窓口/ディスパッチャー/キュレーターが残っているため)poll_events ループを timeout_ms=5000 / deadline 5 秒で再度回し、close_pane 由来の pane_exited を消化するmcp__org-broker__list_panes で生存確認し、残存なら journal に記録して人間に報告(強制終了は現状未サポート)ディスパッチャーを停止: ディスパッチャーに mcp__org-broker__send_message で終了を指示:
「SHUTDOWN: 作業を終了してください。」
キュレーターを停止(存在する場合のみ): curator は常駐しないため、通常このステップは
no-op。mcp__org-broker__list_panes に name == "curator" のペインが存在する場合
(オンデマンド curate 実行中に suspend が重なったケース)のみ、send_message で終了を指示:
「SHUTDOWN: 作業を終了してください。」(curate は move-then-mark 設計のため途中停止でも
破壊的な中間状態は残らない)
ディスパッチャー(および存在した場合のみキュレーター)も (3) と同じ 2-pass 構造で確認(pending = {"dispatcher"}、curator が存在した場合は "curator" も集合に入れ、role == "dispatcher" または role == "curator" の pane_exited を待つ):
poll_events(types=["pane_exited"], timeout_ms=10000) 相当ループmcp__org-broker__close_pane(target="dispatcher")(curator 残存時は close_pane(target="curator") も)を送り、poll_events ループ (timeout_ms=5000) で再確認最後のペイン (窓口) の扱い: ディスパッチャー(と存在した場合のキュレーター)を閉じた時点でタブに残るのは窓口
ペインのみになる。窓口が自分自身を mcp__org-broker__close_pane(target="secretary") で
閉じようとすると [last_pane] (唯一のタブの唯一のペイン) が返るので、窓口は自分自身で
exit して自然終了させる (人間が端末を閉じる、または /exit でシェルに戻る)。
org-suspend は窓口ペインを閉じる責任を負わない。
組織を中断しました。
- 保存済み: {N}件の作業アイテム
- 状態ファイル: .state/org-state.md
/org-start で再開できます。