OxideTerm ノードセッション所有権

SSHノード、ターミナルペイン、SFTP、ポートフォワーディング、再接続、ジャンプホスト、ヘルスチェック、NodeRouter、長期バックエンドタスクの実装やレビューにおいて、OxideTermのランタイム所有権ルールを適用します。

OxideTerm ノードセッション所有権 とは?

このスキルは、OxideTermベースのアプリケーションにおけるリモートセッションとバックグラウンドジョブの所有権とライフサイクルを管理するための明確なルールセットを提供します。コアとなる不変条件は、接続されたSSHノードはそれを消費するターミナルペインから独立していること、つまりUIのライフタイムがバックエンドのライフタイムを暗黙的に決定してはならないということです。このスキルは、NodeRouterや接続レジストリを使用して明示的に所有権を管理し、ターミナルペインを閉じても共有ノードが切断されないようにし、すべての長時間実行タスクに明確なキャンセルパスとクリーンアップパスがあることを保証します。これは、Claude Code、Cursor、CodexなどのAIエージェントで使用できる、厳格な設計パターンを強制し、Node.jsまたはRustのバックエンドを持つ開発ツール向けに設計されています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/AnalyseDeCircuit/oxideterm/tree/HEAD/.agents/skills/oxideterm-node-session-ownership

Installed? Explore more 生産性&コラボレーション skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

OxideTerm ノードセッション所有権 は何をしますか?

このスキルは、変更がリモートセッションやバックグラウンドジョブを作成、共有、クローズ、再接続、または監視するコンポーネントを変更する可能性がある場合に使用します。

コア不変条件

接続されたSSHノードは、それを消費するターミナルペインから独立しています。UIのライフタイムがバックエンドのライフタイムを暗黙的に決定してはなりません。

flowchart TD
    W["ワークスペースまたはアプリケーションのライフタイム"] --> R["NodeRouter と接続レジストリ"]
    R --> N["物理SSHノード接続"]
    N --> T["ターミナルコンシューマ"]
    N --> S["SFTPコンシューマ"]
    N --> F["フォワーディングコンシューマ"]
    R --> H["ヘルスチェックと再接続ジョブ"]

必須ルール

  • ノードの活性は接続レジストリ、NodeRouter、または明示的なノード切断操作に属します。
  • ターミナルペインを閉じると、そのターミナルコンシューマが削除されます。共有ノードを切断してはなりません。
  • SFTPは、実際のノードによってバックアップされたSFTPセッションを取得する必要があります。ファイル転送を模倣するシェルコマンドは、文書化された互換性フォールバックとしてのみ許可されます。
  • ポートフォワーディングは、自身のリスナーとブリッジタスクを所有します。これらのタスクは、ターミナルペインが開いていなくても存続し、フォワーディングルールまたは所有するノードが停止したときに停止する必要があります。
  • 再接続、ヘルスチェック、グレース期間、子プロセスブリッジには、ノード、ワークスペース、またはアプリケーションのライフタイムに結びついた明示的な所有者とキャンセルパスが必要です。
  • 長時間実行される作業は、コマンドハンドラが戻ったときにドロップされるワンショットランタイム上で実行してはなりません。
  • ジャンプホストを介して接続された子ノードは、子トランスポートが必要とする間、親接続を保持する必要があります。
  • UIコンポーネントは、ルーターまたはレジストリのイベントを通じてランタイム状態を監視します。ターミナルの存在からノードの活性を推測してはなりません。
  • 所有権の移行(作成、共有、無効化、再取得、キャンセル、UI破棄後の意図的な存続)には、簡潔な英語のコメントを追加してください。

禁止される回避策

  • ノードバックアップのAPIが不便だからといって、管理されていない2番目のSSHトランスポートを開かないでください。
  • ホストに関連付けられた最初のターミナルペインを選択して接続を見つけないでください。
  • 長時間実行されるタスクを一時的なダイアログ、コマンドハンドラ、またはターミナルビューにのみ保存しないでください。
  • 1つのチャネル、ペイン、SFTPリクエスト、またはフォワーディングコンシューマが閉じただけで、ノードを切断済みとマークしないでください。
  • 生成された子プロセスやTokioタスクを、シャットダウンシグナルと制限付き完了パスなしで切り離したままにしないでください。

推奨プラクティス

  • バックエンドの依存関係をそれぞれ、偶発的な Arc の保持に依存するのではなく、レジストリ内のコンシューマまたは所有者として表現します。
  • 物理トランスポートの状態は接続エントリに保持し、論理トポロジは NodeRouter に保持します。
  • 切断カスケードは、ホスト文字列を照合するのではなく、記録された親子接続IDに従うようにします。
  • タスクハンドルまたはキャンセル送信側は、そのライフタイムがジョブを定義するオブジェクトに保持します。
  • ターミナル状態のポーリングよりも、イベント駆動型のUI更新を優先します。

互換性パス

互換性フォールバックは、明示的で、制限付きで、正確に報告される場合にのみ許可されます。それらをネイティブのSFTP、フォワーディング、またはノードセッション実装として説明してはなりません。一時的なフォールバックであっても、所有者とクリーンアップパスを記録してください。

例

不正:

// ペインを閉じると、共有ノードの唯一の所有者が誤って破棄される。
struct TerminalPane {
    ssh_transport: SshTransport,
}

正しい形:

// ペインは自身のコンシューマ登録のみを所有し、レジストリがトランスポートの活性を所有する。
struct TerminalPane {
    connection_id: String,
    terminal_consumer: ConnectionConsumer,
}

不正:

tokio::runtime::Runtime::new()?.spawn(run_forward_listener());
// ランタイムはコマンドが戻ったときにドロップされる。

正しい形:

// フォワーディング所有者は、キャンセルハンドルと完了ハンドルの両方を保持する。
struct ForwardingJob {
    shutdown_tx: Option<oneshot::Sender<()>>,
    worker: JoinHandle<()>,
}

レビューチェックリスト

  1. 物理接続の所有者を特定します。
  2. すべてのターミナル、SFTP、フォワーディング、再接続、ヘルスチェック、子ノードコンシューマをリストアップします。
  3. 1つのコンシューマを閉じても、関連しないコンシューマが閉じないことを確認します。
  4. 明示的なノード切断が、依存するジョブと子トランスポートを停止することを確認します。
  5. 生成されたすべてのタスクまたはプロセスについて、保持されている所有者、キャンセルシグナル、およびクリーンアップパスを検査します。
  6. UI状態が、ターミナルから派生した活性ではなく、ノードイベントを消費することを確認します。
  7. 残っている互換性フォールバックを正確に記述します。

検証

  • 最後のターミナルを閉じ、他の登録されたコンシューマがノードを使用できるままであることを確認します。
  • ターミナルペインを必要とせずにSFTPを開きます。
  • ローカル、リモート、動的フォワーディングを開始し、リスナーがペインクローズ後も生き残ることを確認します。
  • 親ノードを切断し、依存する子ノードとジョブが一貫して遷移することを確認します。
  • グレース期間内に再接続し、関連しないUI状態が失われないことを確認します。
  • タスク/プロセスのクリーンアップが、明示的な切断後およびアプリケーションシャットダウン後に完了することを確認します。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

関連スキル