afk について
afkは、Firstmateのチームを監督する担当者が離席する際に使うスキルです。離席中の指示と復帰条件を記録しつつ、権限の境界と復帰時の報告手順を保ちます。
主な機能
- 01離席指示と復帰情報の記録
- 02不確かな判断を担当者に保留
- 03離席中の監督セッションに対応
- 04順序立てた復帰報告の作成
活用シーン
- 01離席中もチームの日常監督を継続
- 02担当者の判断が必要な事項を保留
- 03復帰後にチームの成果と阻害要因を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ kunchenguid/ firstmate --skill afkインストール後、Claude Code で/afkを入力して読み込まれたか確認します。
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
afk
離席モードは、1つの監督セッションにおける姿勢であり、別のアーキテクチャではありません。
離席によって変わるのは、キャプテンへの報告方法と、キャプテンが判断する場面での対応(戻るまで保留するか、キャプテンが離席時に残した言葉ですでに示した答えに従うか)の2点だけです。
権限の範囲は決して変わりません。
姿勢はファイル state/.afk-contract で管理され、/afk と同じターン内に bin/fm-afk-contract.sh だけがこのファイルを書き込みます。チャットから姿勢を推測することはありません。
静音モードを記録する(bin/fm-afk-contract.sh mode)レコードは、この姿勢とは異なります。キャプテンがその場にいるため、このスキルが定める「戻るまで保留」は適用されません(このモードは quiet スキルが管理します)。
/afk を入力すること自体が実行の合図です。キャプテンはその後、画面を再び見るとは限らないため、開始時に人間からの追加応答を待つことはなく、読み上げによる確認で開始を制限したり、実行の合図を求めたりすることもありません。
戻るまで保留する方法がデフォルトであり、このリリースで記録される唯一の到達プロファイルです。電話での連絡手段はなく、開始時のアナウンスでは毎回そのことを明示します。
開始:/afk [words]
- まず、このターン内に記録を書き込みます。
ほかの作業に取りかかる前に、
bin/fm-afk-launch.sh enter --words-file <path> [--expected-return <UTC ISO 8601>] [--spend <n>](または--words <text>)を実行します。 これは別途確認を挟まず、直ちにstate/.afk-contractに書き込み、その後、開始のアナウンスと記録の読み返しを出力します。 指示文全体が委任内容です。bin/fm-afk-contract.shは、節フィールド、動詞、ID、マージ許可リストを設けず、与えられたとおりに記録します。また、キャプテンの指示により、どのパーサー、トークナイザー、分類器、文法も、どこであれこの指示文を読み取りません。 フラグを暗記するのではなく、bin/fm-afk-contract.sh --helpを読んでください。 指示文を付けずに/afkを実行するのも有効です。この場合、委任内容はなく、アナウンスでは指示が記録されていないことを伝えます。 すでに離席中に新しい指示文を付けずに/afkを再実行すると、記録をそのまま維持して更新します。新しい指示文を付けた場合は、委任内容を直ちに置き換え、最初のセッション開始記録は維持し、置き換え前の指示文は復帰時の報告用にアーカイブします。 - 記録ができた後、ハーネスごとに対応します。
- Pi および pi-signed:起動するものはありません。アナウンスに進みます。
Pi では離席デーモンを起動しなくなりました。通常の監視セッション(
docs/pi-supervision-branch.md)は記録が存在する状態で動作し続けます。また、これらのハーネスではbin/fm-afk-launch.sh startは起動を拒否します。 記録が存在する間、メインは待機状態になります。監視ブランチは安全に実行可能なすべての起床要求を引き受け、キャプテンの判断結果を復帰時の報告用に蓄積します。メインの恒常的な権限は、ガード付きスクリプトを通じてブランチへ移管されます(docs/pi-supervision-branch.mdの「Postures」)。ブランチが対応を断った起床要求(ブランチの破損や安全でないスキャンを含む)、またはウォッチャーの障害が発生した場合にのみ、メインが起床します。 Pi では/quietに追加対応は不要です。対応中のブランチが定期的な起床要求をすでにこの会話に届かないようにしているため、記録がある間の静穏状態は、対応中の姿勢そのものです。 - 監視ホストを実行するホーム(
config/supervision-host-offで無効にしていない Claude ホーム、またはオプトアウト設定がなくconfig/supervision-hostがある Cursor、OpenCode、omp、Grok、Codex ホーム。docs/configuration.mdの「Supervision host」を参照):/afkでは起動するものはありません。アナウンスに進みます。 そのホームでは、監視ホスト(docs/supervision-host.md)が離席セッションになります。記録がある間、メインが待機状態になり、ヘッドレスエンジン上でブランチの委任内容を実行します。また、そのホームではbin/fm-afk-launch.sh startとstart-nativeは離席デーモンの起動を拒否します。enterの出力にSupervision host: no engine ...の行があった場合は、離席中のすべての起床要求がこの会話に届くことをアナウンスで伝えてください。 対応中の監視ホストが動作するホームでは/quietは何も起動しません。それ以外では下記のデーモンを引き続き起動します(起動するかどうかは quiet スキルのquiet-checkが判断します)。 - インペインのネイティブな追跡付きバックグラウンドツールを備えたハーネス(監視ホストを実行しないホームの claude と grok):
bin/fm-afk-launch.sh start-nativeを実行し、その後、ネイティブツールを使ってFM_AFK_STATE_PREPARED=1 bin/fm-afk-start.shを実行します。 これは意図的な、別ターミナルを使わない例外です。ハーネスがホストするジョブではターミナルもレイアウトも変更されず、シェルランチャーからハーネスネイティブのバックグラウンドツールを呼び出すこともできないためです。 ネイティブ起動に失敗した場合は、bin/fm-afk-launch.sh stopを実行して、準備したライフサイクルをロールバックします。nohup ... &で囲まないでください(Codex/herdr は、ツール呼び出しが返った後に、実行中のシェルの子プロセスを回収することがあります)。 - それ以外のすべてのハーネス(codex、opencode、omp、および監視ホストを実行しないホームの cursor、ならびに kimi):
bin/fm-afk-launch.sh startを実行します。 これはデーモン用ターミナルを一元管理します。現在のバックエンド用に非表示の追跡対象ターミナルを作成し、キャプテンのペインをFM_SUPERVISOR_TARGETとして渡します。これにより、デーモンは自分の新しいペインではなくキャプテンにメッセージを送ります(docs/herdr-backend.mdの「Away-mode supervisor support」を参照)。 どちらのデーモン起動方法でも、記録はenterが書き込んだものを使い、デーモンのエントリーポイントにはbin/fm-afk-start.shを共通して使います。 デーモンの動作は 在席状態に連動します。state/.afkが存在する間だけエスカレーションを送信し、それ以外は静かにしています。
- Pi および pi-signed:起動するものはありません。アナウンスに進みます。
Pi では離席デーモンを起動しなくなりました。通常の監視セッション(
- アナウンスしてから、開始後に記録を読み返します。
アナウンスでは、復帰まで保留すること、電話での連絡手段はないこと、指示は記録済みで、離席セッションが対応可能なものは実行すること、不明な点や本人の対応が必要なことは復帰まで待つこと、また、指示文の内容にかかわらず、破壊的、取り消し不能、またはセキュリティに関わる操作は事前に許可できないことを、趣旨を変えずに伝えます。
その後、
AGENTS.mdのセクション 9 の表現に沿って、指示文を自分の言葉で平易な文に書き直します。つまり、何を依頼されたと解釈したかを、番号付きフィールドの一覧ではなく、一文ずつ述べます。その際、予定している復帰時刻、支出上限、一文の連絡に関するアナウンスも併記します。 離席中に対応できない文がある場合は、それがどの文か(レッドマージ、破棄、never-set 上の項目、ローカル限定のランディングなど)を明言します。その文は復帰まで保留されます。 この読み返しは情報共有です。記録はすでに有効なので、許可を求めたり、返答を待ったりしてはいけません。解釈を変えたいキャプテンは、新しい指示文を付けて/afkを再実行します。 - デーモンが動作する場所では、
fm-watch.shを別途起動しないでください。 デーモンはウォッチャーを子プロセスとして管理します。シングルトンロックがあるため、誤って別途起動しても安全に何も行いません。 Pi では起動方法に変更はありません。監視セッションのサイクルが継続します。
外出中
- 記録が存在するため、どちらの監督形態でも、監視処理は船長の判断待ちになっている項目を再確認しません。代わりに、帰還時の報告にその項目が記載されます。
条件が明示された外部待機では、条件に応じた数時間おきの再確認間隔が維持されます(
bin/fm-watch.sh、bin/fm-classify-lib.sh)。 - 外出中のセッションは、船長の言葉に従って行動します。
起動するたびに末尾でその言葉を読み、目の前のイベントが船長の言及した状況に該当するかを独自に判断し、常設の権限のもとでガード付きスクリプトを通じてのみ行動します。類推による行動はせず、疑わしい場合は判定を captain として保留し、言葉に基づいて実行したアクションの結果をまとめる際は、必ず冒頭に "per your away instructions:" を付けます(実行ルールは
bin/fm-branch-prompt.shの「Postures」で規定されています)。 破壊的、不可逆、またはセキュリティ上重要なアクションは、どのような言葉があっても事前に許可できません。また、判断をユーザーに確認する必要がある案件では、言葉によってその具体的な判断が事前に回答されていない限り、ask-user-authorityポリシーが適用されます。それ以外で船長の判断が必要な事項は、帰還まで保留されます。 - Pi では、main は待機状態になり、監督ブランチが main の常設権限のもと、main が使用するものと同じガード付きスクリプトを通じて、安全に実行できるすべての起動時処理を担当します。現在のヘッドがグリーンのプルリクエストはどれでもマージできます(どれを指していたかは、ブランチが言葉を解釈します)。ブロッカーが解消されたキュー内の作業は、すでにキューに入っていたものでも、言葉で明示的に求められたためブランチが登録したものでも、支出上限内で実行に移されます。また、判断が必要な場合は、船長が事前に示した回答、または
ask-user-authorityに基づいて回答します。 それ以外は帰還まで保留されます。レッドのマージは外出中に決して進められず、ローカル限定の反映は必ず船長を待ちます。また、main を起動するのは、ブランチが処理を辞退した場合(ブランチの障害や安全性チェックの問題を含む)か、監視処理に失敗した場合のみです(docs/pi-supervision-branch.mdの「Postures」)。 - 監督ホストを実行する Pi 以外のホーム環境では、同じルールのもとでホストのエンジンがそのブランチとして動作し、ホストが引き渡した起動処理は、そのハーネス固有の起動経路を通じて main に届きます(Claude では
Stop hook feedback、Cursor、OpenCode、omp ではwatcherのフォローアップ、Grok ではアームのバックグラウンドタスク完了通知、Codex ではチェックポイントの出力)。その際はsupervision-host:行が付加されます。これは自動監督であり、船長の帰還ではないため、外出時のポスチャーに従って処理してください(監督プロトコル)。 - セッション開始時のダイジェストでは、AFK サブセクションにポスチャーが報告されます。そのため、再起動後は記憶ではなく記録に基づいてポスチャーに復帰します。
退出方法:帰還
/back は不要です。最初の通常のメッセージが帰還の合図です。
- 以下の内部形式のいずれにも該当せず、
/afkで始まらないメッセージ → キャプテンが戻ってきました。 キャプテンが戻ってくるきっかけとなったメッセージに対応する前に、bin/fm-afk-return.shを実行してください。 このスクリプトは、デーモンが動作していた場合の正しい順序でのデーモン停止、姿勢記録のアーカイブ、永続的な復帰通知と処理後の確認、エスカレーションと行き詰まりの証拠、復帰ブリーフ、復帰時のキャッチアップゲートを管理します。 復帰ブリーフのすべてのセクションを、出力された順序とセクション 9 の言語のまま伝えてください。その順序はbin/fm-afk-return.shが管理します。 ゲートでは、ブロック元の解決が確認されるまで、すべての未解決のblocked:イベントが保持されます。それぞれを通常のライフサイクルで直ちに解消するか、永続的な理由を添えて明示的に再分類し、判断キーをresolved [key=...]で閉じてから、bin/fm-afk-return.sh checkを実行してください。 キャプテンの判断が必要な結果は「waiting on you」の下に表示されますが、未解決のブロッカーが免除されるわけではありません。ブロッカーごとの根拠情報は担当者不在のまま保留され、ゲートは安全側に倒して未解決のブロッカーをすべて保持します。 記録がアーカイブされたら、ブロッカーへの対応と並行して、出力されたプライマリハーネスの監督プロトコルに従い、ウェイクごとの応答性を完全に再開してください。これにより、ゲートが応答不能な待ち状態を生み出すことはありません。 ゲートが開いている間も Bearings のリクエストには回答でき、ダイジェストには、保留要因を示す行として「Charted Next」(return-catchup)警告が表示されます。 フリートに関する作業(ディスパッチ、進路の調整、マージ、その他の通常のキャプテン業務)は、チェックが正常終了するまで待ってください。 正常終了したら、ブリーフの「Landed, cleanup due」に記載された各タスクを通常のティアダウン(bin/fm-teardown.sh <task>。強制実行は禁止)で完了させ、各ワーカーが閉じられたことを、結果を伝える形でキャプテンに知らせてください。拒否された場合は、作業を止めて調査してください。 - 現在の運用プレフィックス(
FM_OPERATIONAL_PREFIX、U+2063 INVISIBLE SEPARATOR の後にFIRSTMATE_OP:が続く)を伴うメッセージ、または旧形式の裸のFM_INJECT_MARKデーモンエスカレーション → 戻らず、受け取った内容に対応してください。 - 記録に基づく運用用ドアベルと完全に一致するメッセージ(
: Firstmate operational input waiting: read '<path>' ...)→bin/fm-operational-input.sh open '<path>'を実行してください。成功した場合は戻らず、出力されたエスカレーションに対応してください。 失敗した場合、そのドアベルは Firstmate のものではないため、通常の未マークメッセージと同様に扱ってください。 入力されたFIRSTMATE_OP:ラベルなど、Firstmate の入力に見えるだけの ASCII テキストを内部メッセージとして扱わないでください。 - Stop hook または監督ホストからの
Stop hook feedbackウェイク、または arm に関する Grok のバックグラウンドタスク完了通知 → 戻らず、受け取った内容に対応してください。これは自動監督であり、キャプテンからのメッセージではありません。 - すでに不在の状態で
/afkを再度実行した場合 → 不在のまま(更新)。これは退出のきっかけにはなりません。
曖昧な場合は退出する側に判断してください。キャプテンがその場にいることはトークン節約より優先され、誤って退出してもキャプテンが /afk を再実行すれば元に戻せます。
キャプテンが、その場にいて会話を続けながら同じトークン節約型の監督を望み、通常のメッセージでは退出しないようにしたい場合は、/afk ではなく /quiet(kunchenguid/firstmate#2356)を使います。
承認権限とは独立
afk が変えるのは、キャプテンへの報告方法と、キャプテンが所有する判断ポイントでの対応であり、何を誰が承認するかではありません。
「離席中」は、「より多く承認する」ことも「より少なく承認する」ことも意味しません。
マージ可能な状態の PR には引き続き AGENTS.md のセクション 7 に定められたマージ権限が適用され、判断が必要との検出結果には引き続き ask-user-authority ポリシーが適用されます。キャプテンの判断が必要なものは、キャプテンから明示的な指示があるまで待機します。
離席時の姿勢を記録したレコードが存在する間は、最新の状態で green になっているプルリクエストは、離席中の権限のもとでマージできます。キャプテンの言葉がどのプルリクエストを指していたかは、離席中のセッションが解釈します。その言葉が求めていないマージは、キャプテンが戻るまで保留されます。
離席中の権限によってキャプテンによる保留が解除されることはなく、離席時のレコードがアーカイブされると権限は失効します。
--allow-red、--allow-missing、--allow-no-pipeline は有人対応時のみ使用でき、離席時のレコードが存在する間は拒否されます。
離席中の権限によるマージは同期的に行う必要があります。離席時のレコードが存在する間、fm-pr-merge.sh は自動マージと、即時マージを保証できない GitHub のキュー状態を拒否します。
同じゲートは、操作を実行するすべてのアクターに適用されます。Pi では、待機中のメインの恒常的な権限は監督ブランチに移され、そこでもまったく同じルールが適用されます。また、記録された支出上限は、離席時のレコードが存在する間、両方のアクターに対して fm-spawn.sh によって適用されます。
キャプテンが離席時に残す言葉とは、離席前に与えた明示的な指示をそのまま記録したものです。イベントによってその指示が関係する状況になった時点で、離席中のセッションが判断して実行します。その言葉が対象とするのは、明示された内容だけです。類推によって適用されることはなく、アーカイブ時に効力を失います。
破壊的、不可逆、またはセキュリティ上重要な操作は、どのような言葉があっても事前に許可することはできません。
引き続き稼働するデーモン
引き続きデーモンを起動するハーネス(Pi と pi-signed を除く、検証済みのすべてのハーネス、および監督ホストが稼働するホームでの離席モード)では、以下の仕組みに変更はありません。
運用プレフィックスの契約
デーモンは、bin/fm-operational-input.sh が所有する away-supervisor 種別のレコードとして、現在のエスカレーションを構成します。そのエンベロープは FM_OPERATIONAL_PREFIX で始まり、FM_INJECT_MARK(U+2063 INVISIBLE SEPARATOR)に続いて、安定したラベル FIRSTMATE_OP: が置かれます。
従来のデーモンエスカレーションとのロールアウト中は、裸の FM_INJECT_MARK 形式も引き続き受け付けます。
U+2063 は通常のキーボードでは入力できず、端末での転送後も UTF-8 テキストとして保持されます。しかし Claude Code(2.1.280 で検証済み)は、入力、貼り付け、起動プロンプトとしての受け渡しのいずれの場合も、送信された各プロンプトから他のすべての不可視文字とともにこれを削除します。
マーカーを削除するものとして所有者リストに記載されているプライマリハーネス(Claude Code)では、デーモンは代わりに、このホームの state/operational-inbox にエンベロープをレコードとして書き込み、レコード名を示す所有者向けのプレーンな呼び出し通知だけを入力します。
open がこのホーム内のレコードを検証した場合に限り、その呼び出し通知は Firstmate によるものです。そのため、呼び出し通知の形式だけでは Firstmate によるものとは判断できません。ただし、レコードが存在する間に有効な呼び出し通知の行をそのままコピーして貼り付けた場合は、キャリアが消費状況を追跡しないため、Firstmate によるものとして扱われます。
この仕組みにより、firstmate はデーモンのエスカレーションと同じペイン内の実際のメッセージを区別できます。
その他のハーネスでは、運用プレフィックスはメッセージテキストとともに転送されます。どちらのキャリアも、ハーネスレベルで入力と注入を判別する仕組みには依存しません。
ビジーガードとコンポーザーガード
デーモンは使用中のペインには決して挿入しません。挿入の前に、bin/fm-backend.sh 経由でスーパーバイザー自身のバックエンド(tmux または herdr。「自動検出されるスーパーバイザーペイン」を参照)に処理を振り分け、次の 2 つのチェックを実行します。
- プライマリペインのビジーガード -
pane_is_busyは、利用可能な場合は Herdr ネイティブのbusyを信頼し、それ以外の場合は検出されたプライマリハーネスのシグネチャだけを使って、描画済みの出力を照合します。 この限定的な配信ガードは、記録済みのワーカータスクを判定せず、ベンダーのパターンを全体から寄せ集めて使用することもありません。 - コンポーザー状態ガード -
inject_msgはfm_backend_composer_stateからempty/pending/pending-unproven/unknownの完全な判定結果を読み取り、明確にemptyと判定された場合にのみ挿入します。 ペインを読み取れない場合、ジオメトリが曖昧な場合、識別されていない空白行がある場合、エージェントの終了後にシェルプロンプトだけが残っている場合も含め、その他のすべての判定結果や将来追加される判定結果では挿入を延期します。 各アダプターがフリート全体のスクリーンクラシファイア(bin/fm-composer-lib.sh)に提供するのは、キャプチャと機能に関する事実だけです。あらゆる形状と判定は、このクラシファイアが担います。 空であることが確認されたアイドル状態のコンポーザーはemptyのまま扱いますが、シェルのグリフには実際のコンテナーを必須とします。オペレーター向けの仕様については、docs/herdr-backend.mdの「コンポーザーと挿入の安全性」を参照してください。pane_input_pendingは、コンポーザーが安全でないかどうかを判定する必要がある呼び出し元向けにテスト済みのフェイルクローズ述語です。厳密にemptyと一致する結果以外はすべて、入力待ちとして扱います。
プライマリペインがビジー状態の場合、またはコンポーザーの判定結果が empty 以外の場合、挿入は延期されます。バッファーに保持されたエスカレーションは state/.subsuper-escalations に残り、次回のハウスキーピングのタイミングで再試行されます。
afk モードではコンポーザーガードは二重の安全策です(人が入力することはありません)が、キャプテンの復帰からメッセージが届くまでの競合期間、停止したシェル、デーモン自身が以前に挿入した未送信のメッセージから保護します。
最大延期時のエスケープ(デーモンが処理を黙って停止させることはありません)。
何らかのデータが FM_MAX_DEFER_SECS(デフォルトは 300)を超えてバッファーに残ると、デーモンは通常のフラッシュを 1 回試みます。この場合も、ペインがアイドル状態であり、コンポーザーが明確に空であることが必要です。
アラームは多層防御であり、実際にアイドル状態のサポート対象コンポーザーすべてで挿入を可能にしておくことの代わりにはなりません。
送信を確認できなかった場合、デーモンは大きく目立つ、頻度を制限した停止アラームを発します。具体的には、最後に発生した配信失敗を示すデーモンログの ERROR、永続的な state/.subsuper-inject-wedged マーカー(復帰ブリーフのヘルス行に表示されます)、該当する場合は tmux ステータス行の点滅、および設定可能なバックエンド非依存のアクティブアラートです。
アラートチャネルの設定は docs/wedge-alarm.md が、アクティブな証跡は docs/verification/supervision.md の「停止アラームのチャネル」が管理します。
そのため、ガードの誤検出は目に見える停止となり、際限なく黙って何もしない状態にはなりません。
モデルの送信
ダイジェストは 一度だけ 入力します(tmux では send-keys -l、herdr では pane send-text。どちらもリテラル送信で、送信は確定しません)。その後、Enter を送信し、選択したバックエンドの送信プリミティブを通じて確認します。
バックエンドが送信の成功を確認するまで、Enter のみを再試行します(再入力は決して行いません)。
送信に失敗した場合は、失敗した段階(初回送信、または Enter の送信。確認の再試行が行われず、herdr のように Enter を送れなかったバックエンドでは、テキストはすでに入力されている可能性があります。または Enter の確認)、ペイロードのバイト数、トランスポート固有のエラー出力を記録します。
tmux では通常、共有分類器によってコンポーザーがクリアされたことを確認します。正常に動作しているハーネスがコンポーザーを隠している場合は、この送信で Enter を押す前のアイドル状態からビジー状態へ移行したことも、ターンが開始された確認になります。
そのベースラインがない場合、ビジー状態であっても unknown のコンポーザーが確認済みに変わることはありません。
herdr では、アイドル状態をベースラインとする送信の場合、まずエージェントの実際のターンが開始されたことを示すネイティブのエージェント状態を確認し、ネイティブ状態がアイドルのままであれば共有分類器を使用します。コンポーザーがクリアされていれば送信を確認し、テキストが残っていれば Enter を再試行して、再試行の上限に達した後にのみ共有のビジーキュー判定に進みます。
このバックエンドがコンポーザー確認を使用する場合、枠線だけの空欄、またはゴーストテキストだけのコンポーザーは空として認識され、Enter が無視されたと誤判定されません。
fm-send.sh は入力されたテキストの送信に限って同じプリミティブを使用し、そのテキスト入力で Enter が確実に無視された場合はゼロ以外の終了コードで終了します。通常のローカルテキストによる誘導には永続的な受信トレイを使用し、ドアベル送信を配信の証明とはみなしません。
ビジーキューへの Enter 送信に関する例外(opencode 1.18.4)。 OpenCode ではターンの実行中もキューに入れられたテキストが表示されたままになるため、tmux と herdr は、表示されているテキストだけを根拠に Enter が無視されたと判断せず、最終的な送信判定を bin/fm-composer-lib.sh の fm_composer_queued_enter_verdict に委ねます。
デーモンがバッファーをクリアするのは、バックエンドが empty の成功判定を返した場合だけです。バックエンド固有の確認シグナルについては、docs/tmux-backend.md と docs/herdr-backend.md を参照してください。
分類ポリシー
デーモンは fm-watch.sh をラップし、ウォッチャーを子プロセスとして実行します。処理可能なウォッチャーの終了後ごとに永続的なウェイクアップをすべて提示し、提示された各レコードを bash で分類して、ルーティングの完了後にのみ提示した世代を確認します。
デーモンは、日常的なイベントの大半を自ら処理するため、firstmate のターンを消費しません。
以下のルーティングで選ばれたイベントは、事前に読み込まれた単一行のバッチ済みダイジェストとして、firstmate のコンテキストにエスカレーションされます。
ダイジェストはすべてのトランスポートで送信できるようバイト数に上限を設けています。イベントの途中で切れる場合や、上限のためにイベントが省略される場合は、バッファー内のすべてのイベントがそのまま記録された state/.subsuper-digests/ のファイル名を示します。したがって、途中で切れたイベントに対処する前にそのファイルを読んでください。
キャプテンに関連する動詞の一覧、宣言された待機状態の語彙、ステータス範囲の分類器、提示マーカーの規約は、共有の bin/fm-classify-lib.sh に定義されています。一方、各スーパーバイザーはこのポリシーを利用しながら、独自のルーティングとフリートのスキャンを担当します。
state/.afk が存在する間はデーモンがウォッチャーを管理するため、ウォッチャーはワンショット動作に戻り、トリアージはデーモンに任せます。両者が同時にトリアージを実行することはありません。
各ウェイクアップを次のように分類してください。ステータスに基づくルーティングの前に、ステアリング受信トレイの例外を適用します。
staleの詳細がunread firstmate instruction: stuck-busyまたはsteering-inbox busy bookkeeping unwritable:で始まる場合 -> 明示的なインボックスエスカレーションを、ワーカーのステータスを消費したり、一時的な stale リカバリーに入ったりせず、away モードと quiet モードで監督用にバッファリングします。bin/fm-task-inbox-lib.shが busy の予算と記録処理の契約を管理します。tests/fm-daemon.test.shでは、このコンシューマー境界をテストします。- 新たに分類されたステータス範囲に captain に関係するイベントが含まれる
signal-> すべてのイベントをソース順にエスカレーションします。 進行を表す非終端の動詞は、その説明文にPR ready、checks green、ready in branch、mergedなどの従来のフリーテキストトークンが含まれていても、非終端のままです。エスカレーションされるのは、そのようなトークンを含む単独の従来形式の行だけです。 範囲内に captain に関係するイベントがないその他のシグナルは、自身で処理します。 - 最新のステータスが、
paused:による外部待ち、または検証済みのcaptain-heldによる引き継ぎのいずれかの待機を宣言しているsignalまたはstaleは、ペインがアイドル状態か busy 状態かにかかわらず、停止ではなく一時停止として追跡します。 新たに分類された範囲に未報告の、対応が必要なイベントがあれば、現在の宣言が個別に一時停止の間隔を維持している場合でも、ただちにエスカレーションします。 未報告で対応が必要なイベントがない場合、ウェイクは自身で処理します。また、現在の宣言は、情報が付加された停止の可能性に関する理由よりも優先されるため、FM_STALE_ESCALATE_SECSの間隔でエスカレーションされることはありません。 宣言された外部待ちがFM_PAUSE_RESURFACE_SECS(デフォルトは4時間)を過ぎても継続して宣言されている場合、ハウスキーピングが再確認を1回送信し、一時停止の期間をリセットします。姿勢レコードが存在する間、captain-held による引き継ぎが再確認されることはありません。 期間はクルー自身の最新のステータス行を基準に経過するため、待機の宣言をやめるステータスの追記があった場合に限り、このルーティングが終了し、停止の検出が再開されます。 check-> 常にエスカレーションします。チェック用スクリプトは、firstmate が起動すべき場合にのみ出力します。- 終端ステータス、単独の従来形式の captain に関係する行、または
parked:などの認識されないステータス接頭辞を含むstale-> エスカレーションします。 進行中のステータスは、その説明文に従来のフリーテキストトークンが含まれている場合や、認識済みステータスのマーカーがすでに一致している場合でも、一時的な状態のままです。そのため、マーカーを記録して自身で処理します。 ペインがFM_STALE_ESCALATE_SECS(デフォルトは240秒)を過ぎてもアイドル状態である場合、ハウスキーピングが停止の可能性があるものとしてエスカレーションします。 これにより、停止の検出遅延はしきい値に1回のティックを加えた範囲内に収まります。遅延は発生しますが、見落としはありません。 詳細がblocked-on-prompt:とダイアログ名で終わる stale は、ペインにそのダイアログが表示されていることを意味します。そのため、誰かが応答するまでワーカーは処理を続けられません。 この経路ですでに送信済みのエスカレーションには、ステータスログとハウスキーピングのどちらに由来する場合でも、その名前が含まれます。 すでに報告済みの終端ステータスは、ダイアログ名のない stale と同様に、永続化マーカーをクリアします。 宣言された待機は一時停止の間隔を維持し、名前は引き継ぎません。 健全なクルーメイトは自律的に動作し、タスクの途中で firstmate を待ちません。 heartbeat-> 自身で処理します。 デーモンはFM_HEARTBEAT_SCAN_SECS(デフォルトは300秒)ごとに、低コストの Bash によるフリートスキャンを独自に実行します。これは、ウェイクごとの分類器がまだ読み取っていない、captain に関係するイベントをすべて拾うための仕組みです。- 不明なウェイク理由は、安全側に倒してエスカレーションします。 エスカレーションが配信された後、その正確に要約された行が確認済みとなり、同じ away セッション中に同一の識別情報が再度エスカレーションされることはありません。 新しい away セッションでは確認情報がないため、処理済みの識別情報がもう一度提示されることがあります。 配信されなかった識別情報はエスカレーションされます。 ステータス読み取りの不確実性には、以下の重複排除で説明する、位置を進めずに1回報告する共有契約が適用されます。
エスカレーションは FM_ESCALATE_BATCH_SECS(デフォルトは90秒、0 = 即時)までバッファリングされ、事前読み取りしたステータスの要約と推奨アクションを含む、1行のダイジェストとしてフラッシュされます。
1行形式により、各種ハーネスでの送信が明確になります。上記のキャリアによって、通常の captain メッセージと区別されます。
Injection hardening
- 単一行ダイジェスト - 埋め込まれた改行は注入前にリテラルの セパレーターへ折りたたまれるため、どのハーネスであっても送信は曖昧になりません。
- スーパーバイザーペインでのビジーガードとコンポーザーガード - 注入前に、デーモンは検出されたプライマリハーネスのレンダリング済みビジーガードを実行し、
fm_backend_composer_stateを直接読み取ります。 注入を許可するのはemptyのみです。pendingは入力途中または飲み込まれた入力を保護し、unknownは読み取れないペインと素のデッドシェルプロンプトを保護します。 その他のすべての結果ではバッファが保持されて再試行されるため、デーモンが自身のダイジェストをキャプテンの入力途中の行にマージしたり、シェルへ入力したりすることは決してありません。 - アクティブなバックエンドは、自身のキャプチャーと宣言的なスタイル・カーソル・アイデンティティ・行のケイパビリティを共有スクリーン分類器へ渡します。構造認識と判定ロジックはすべて
bin/fm-composer-lib.shに残ります。 スタイル付きキャプチャーにより、そのオーナーは dim/faint および暗い TRUECOLOR のゴーストまたはプレースホルダーテキストを除去でき、形状検出は ANSI 除去済みスクリーンを使用するため、暗いボーダーがゴーストコンテンツとともに失われることはありません。 したがって、claude の│ > ... │のようなゴーストのみ、またはアイドル状態の枠付きコンポーザーは empty と読み取られますが、枠のないシェルプロンプトが同様に扱われることはありません。FM_COMPOSER_IDLE_REは共有アイドルプレースホルダー正規表現を上書きしますが、マッチだけでは分類器の形状固有の位置および ANSI 非強調の安全ゲートを決してバイパスしません。FM_BUSY_REGEXはレンダリング済みの配信ガードに加えて Grok の分離されたタスク状態フォールバックを上書きします。 空白またはその他の理由で識別できない入力行は、コンテナであることの積極的な証明を持たないため注入を延期します。そのため、モーダルダイアログや再描画中のペインが注入対象になることは決してありません。 - 最大延期エスケープ - デーモンが黙って立ち往生してはなりません。何かが
FM_MAX_DEFER_SECS(デフォルト 300 秒)を超えてバッファリングされたままの場合、デーモンは通常のフラッシュを 1 回試みますが、これには依然としてアイドル状態のペインと確実に空のコンポーザーが必要です。それでも送信を確認できない場合、デーモンは大声でレート制限された立ち往生アラームを発します。ERROR ログ、永続的なstate/.subsuper-inject-wedgedマーカー、該当する場合は tmux ステータスラインのフラッシュ、そしてバックエンド非依存のアクティブアラートです。コンポーザーの誤検知は目に見える停滞として現れ、無制限のサイレントな no-op になることは決してありません。 - 検証済みの 1 回だけ入力する送信モデル - ダイジェストは 1 回だけ入力され(tmux では
send-keys -l、herdr ではpane send-text)、その後 Enter で送信され検証されます。 Enter は再試行されますが、あくまで Enter のみであり、再入力は行われません。これはバックエンドの送信プリミティブが呼び出し側に返す成功判定としてemptyを報告するまで続きます。 tmux の場合、その判定は通常、共有分類器がコンポーザーがクリアされたことを証明したことを意味します。ベースラインで制御されたアイドルからビジーへの遷移が、代わりにこの Enter がターンを開始したことを証明する場合もあります。 herdr のアイドルベースラインパスの場合、ネイティブのエージェント状態がターン開始を観測したか、共有分類器がコンポーザーがクリアされたことを証明したか、または共有のキュー済み Enter 判定がビジー中の配信を証明したことを意味します。 これにより、コンポーザーの読み取りがアクティブな確認シグナルである場合に、ゴーストのみまたは枠付きで空のコンポーザーを empty として数えることができます。 - マーカー除去 -
strip_injection_markerは分類またはリレーの前に現在の操作プレフィックスまたはレガシーのベアマーカーを除去するため、firstmate が見るダイジェストテキストはクリーンになります。openはレコードに基づくドアベルのダイジェストをすでに除去済みの状態で出力します。 - ポータブルなシングルトンロック - デーモンは
flock(macOS には存在しません)の代わりに、リポジトリのポータブルロックヘルパー(fm-wake-lib.sh)を使用します。 - シグナル/ステール/スキャン間の重複排除 - 3 つのパスすべてが
bin/fm-classify-lib.shで定義された共有ステータス提示マーカーを使用するため、正常に分類されたスパンが同じダイジェスト内の別のパスによって再エスカレーションされることはありません。 報告された読み取り不能状態を分類済みとして扱わないでください。共有ライブラリのヘッダーがそのマーカー契約を所有しており、このマーカーは非終端の進捗行に対する立ち往生の可能性のエージングをクリアまたは抑制しません。 - 自動検出されるスーパーバイザーペイン - デーモンは自身の BACKEND(tmux 対 herdr)と TARGET を独立して解決し、
bin/fm-backend.sh自身の実行時自動検出を反映します。バックエンド:FM_SUPERVISOR_BACKENDの上書き、次に$TMUX_PANEが設定されている場合(tmux)、次に$HERDR_ENV=1かつ$HERDR_PANE_IDが存在する場合(herdr)、次に tmux フォールバック。ターゲット:FM_SUPERVISOR_TARGETの上書き(tmux ターゲットまたは herdr の"<session>:<pane-id>"ターゲット)、次に$TMUX_PANE、次に herdr では"${HERDR_SESSION:-default}:${HERDR_PANE_ID}"、次に警告付きのfirstmate:0フォールバック。両方の解決ソースは起動時にログに記録されるため、誤っているものの解決はするフォールバックを検出できます。zellij、orca、cmux を含むその他の実行時バックエンドは、スーパーバイザーバックエンドとしてまだサポートされていません。デーモンは、tmux でないペインに tmux プリミティブを誤って適用するのではなく、起動時に大声で拒否します (docs/herdr-backend.md 「Away-mode supervisor support」)。
古いアーティファクトのライフサイクル
state/.subsuper-escalations、その .since サイドカー、state/.subsuper-inject-wedged、および state/.subsuper-unknown-acked は、永続的な作業記録ではなく、セッション単位の配信アーティファクトとして扱います。
新しいセッションへの移行時にのみ前のセッションのアーティファクトを消去し、更新時には現在のセッションのバッファーを保持する bin/fm-afk-launch.sh を必ず経由して開始します。
デーモンのシャットダウン時のフラッシュが完了するまで state/.afk を保持し、その後これを消去してから、最後に姿勢記録をアーカイブする bin/fm-afk-launch.sh stop を必ず経由して終了します。
現在の仕組みについては docs/herdr-backend.md の「アウェイモードのスーパーバイザーサポート」が、稼働中のエビデンスについては docs/verification/runtime-backends.md の「アウェイモードのトランスポート」が管理します。
信頼性の特性
以下の特性を満たす必要があります。
- キューへの公開後に何も失われません。 デーモンは、ルーティングが完了し、処理後の確認応答が成功するまで、提示されたすべてのウェイクを永続的に保持します。そのため、中断が発生しても、同じ作業がデーモンまたは後継プロセスに再生されます。
- ウェッジ検出は、遅延が上限内に収まるものであり、データ損失を伴いません。
- 明示された外部待機は、ウェッジと誤分類されないよう、別個の、上限付きで条件を考慮した間隔で再確認されます。姿勢記録が存在する間は、キャプテンの対応待ちの項目は再確認されません。
- キャッチオールスキャンは、キーワード分類器をバックアップします。
- デーモンは、ポータブルな単一インスタンスロック、クラッシュループ時のバックオフ、ペイン消失時のガード、および終了前にバッファーされたエスカレーションをフラッシュする、シグナルを捕捉したシャットダウンを保持します。
FM_INJECT_SKIP(デフォルトは heartbeat)は、一致する種類を強制的に自己処理し、分類を上書きします。
使用は控えめにしてください。