cpm-planner について
cpm-plannerは、タスクグラフからクリティカルパス法でエージェント作業をスケジュールするMCPサーバーです。制約を特定し、ファイル集合が重ならない成果物を並行作業用に割り当て、計画比較、リスク分析、出来高管理、任意のAIレビューにも対応します。
主な機能
- 01クリティカルパスとスラックの算出
- 02ファイルが重ならない並行コホートの割り当て
- 03プラン・アズ・コードの保存と比較
- 04リソース平準化とモンテカルロリスク分析
- 05ベースラインに対する出来高管理
- 06スケジュール改善案のレビュー
活用シーン
- 01エージェント作業の計画とボトルネック特定
- 02ファイル競合を避けた並行ワーカーへの割り当て
- 03計画案の比較とスケジュールリスクの評価
- 04進捗、コスト、スケジュール実績の追跡
MCP 対応
stdio経由で、計画、スケジュール、ステータス、出来高管理のツールをMCPクライアントに提供します。クライアントはコマンドとしてサーバーに接続し、エージェント作業を調整できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
docker run -i --rm ghcr.io/praxec/cpm-planner:0.5.0ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ghcr.io/praxec/cpm-planner:0.5.0stdioツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
cpm-planner
cpm-planner は、エージェントの作業向けのクリティカルパスメソッド(CPM)プランナーで、MCP サーバーとして提供されます。タスクグラフを送信すると、最早・最遅の開始時刻と終了時刻、余裕時間、クリティカルパス、完了を妨げるボトルネックタスクを含むスケジュールを計算します。さらに、ファイルセットが互いに重複しない、準備完了済み成果物のロックを考慮したコホートをリースするため、複数のワーカーが衝突せずに並行して作業できます。計画は、分岐・比較可能なバリアントを持つ plan-as-code ファイルとしてリポジトリに保存できます。読み取り専用ツールで、リソース容量に基づくリントやレベル調整、モンテカルロリスク分析を実行できます。アーンドバリュー用ツールでは、固定ベースラインに対する PV、EV、AC、SPI、CPI を追跡できます。また、オプションの AI レビューにより、検証済みのスケジュール改善案を提案できます。任意の MCP クライアント(Claude Code、Cursor、VS Code、Codex、カスタムオーケストレーター、または praxec ワークフロー)から、stdio 経由で操作できます。praxec に依存しないスタンドアロンツールです。
目次
- インストール
- クイックスタート:plan-as-code
- クイックスタート:アーンドバリュー
- AI エージェントで使用する
- MCP ツール
- ライブラリとして使用する
- Praxec
- 環境変数
- ドキュメント
- コントリビュート
- ライセンス
インストール
事前ビルド済みバイナリ(推奨)
Linux、macOS、Windows 向けに、x86_64 および ARM64 用の事前ビルド済みパッケージを公開しています。
インストーラーは OS と CPU を判別し、対応するアーカイブをダウンロードします。インストール前に、リリースの checksums.sha256 と照合して SHA-256 を検証し、ユーザー専用ディレクトリ内のバイナリをアトミックに置き換えます。チェックサムが一致しない場合は、ゼロ以外の終了コードで中断し、何もインストールしません。インストーラーを再実行すると、その場でアップグレードされます。
# Linux / macOS -> ~/.local/bin/cpm-planner
curl -fsSL https://github.com/praxec/cpm-planner/releases/latest/download/install.sh | sh
# Windows (PowerShell) -> %LOCALAPPDATA%\Programs\cpm-planner\cpm-planner.exe
irm https://github.com/praxec/cpm-planner/releases/latest/download/install.ps1 | iex
インストーラーはインストール先の絶対パスを表示します。GUI クライアントにサーバーを登録する際は、そのパスを使用してください。
インストーラーの詳細:スクリプトの確認、PATH、アップグレード、直接ダウンロード
実行前にスクリプトを確認したい場合は、ダウンロードして内容を確認してから実行してください(<version> についてはバージョンの固定を参照してください)。
# Linux / macOS
curl -fsSLO https://github.com/praxec/cpm-planner/releases/latest/download/install.sh
less install.sh
sh install.sh --version <version>
# Windows
irm https://github.com/praxec/cpm-planner/releases/latest/download/install.ps1 -OutFile install.ps1
Get-Content install.ps1
.\install.ps1 -Version <version>
PATH。 インストールディレクトリが PATH に含まれていない場合、インストーラーは追加すべき正確な行を表示します。--add-to-path(Windows では -AddToPath)を渡すと、ユーザーレベルに限って自動で追加できます。sudo は使用しません。
Linux と macOS では、以下のファイルに行を追記します。ただし、すでに存在する場合は追記しません。
- zsh の場合は
~/.zshrc; - bash の場合は、
~/.bash_profileがあればそこに、なければ~/.bashrcに追記します; - その他のシェルの場合は
~/.profile。
fish の場合は、ファイルに書き込む代わりに、実行するコマンド fish_add_path <dir> を表示します。
ダウンロード。 インストーラーが受け付けるダウンロード URL は https:// のみです。
アップグレード。 アップグレード後は、新しいバイナリが起動されるように MCP クライアントを再起動してください。Windows では、古い exe の名前が cpm-planner.exe.old に変更され、次回の実行時に削除されます。
直接ダウンロード。 アーカイブを自分でダウンロードし、checksums.sha256 と照合することもできます。機械可読な release-manifest.json も公開しています。すべてのアセットは https://github.com/praxec/cpm-planner/releases/latest にあります。
| プラットフォーム | アセット |
|---|---|
| Linux x86_64 | cpm-planner-x86_64-unknown-linux-gnu.tar.gz |
| Linux ARM64 | cpm-planner-aarch64-unknown-linux-gnu.tar.gz |
| macOS x86_64 | cpm-planner-x86_64-apple-darwin.tar.gz |
| macOS Apple Silicon | cpm-planner-aarch64-apple-darwin.tar.gz |
| Windows x86_64 | cpm-planner-x86_64-pc-windows-msvc.zip |
| Windows ARM64 | cpm-planner-aarch64-pc-windows-msvc.zip |
バージョンの固定
この README のコマンドで使う <version> は、v0.2.0 のようなリリースタグです。リリースページから選択してください。
# Linux / macOS
curl -fsSL https://github.com/praxec/cpm-planner/releases/latest/download/install.sh | sh -s -- --version <version>
# Windows (PowerShell): the piped form cannot take parameters, so use the environment variable...
$env:PRAXEC_VERSION = '<version>'; irm https://github.com/praxec/cpm-planner/releases/latest/download/install.ps1 | iex
# ...or a script block
& ([scriptblock]::Create((irm https://github.com/praxec/cpm-planner/releases/latest/download/install.ps1))) -Version <version>
npm
Node 18 以降では、npm から cpm-planner コマンドをインストールできます。
npm install -g @matthew-cochran/cpm
cpm-planner --version
このパッケージは小さなランチャーです。プラットフォームに対応したリリースバイナリをダウンロードしてチェックサムを検証し、インストール時、または npm がインストールスクリプトをスキップする場合は初回実行時にキャッシュします。パッケージのバージョンはリリースのバージョンと同じなので、npm install -g @matthew-cochran/[email protected] のように指定してバージョンを固定できます。インストールせずに実行するには、npx -y @matthew-cochran/cpm を使用してください。詳細と環境変数については、npm/README.mdを参照してください。
ソースからのインストール
Cargo でタグ付きリリースをビルドしてインストールします(Rust 1.99 以降)。
cargo install --git https://github.com/praxec/cpm-planner --tag <version> --locked
crates.io の掲載内容は、次回の cargo publish まで GitHub のリリースより古いままです。そのため、cargo install cpm-planner ではまだ最新バージョンをインストールできません。上記のようにタグからインストールしてください。
Docker
docker pull ghcr.io/praxec/cpm-planner
docker run -i --rm -v cpm-planner-data:/data ghcr.io/praxec/cpm-planner
-i は stdio トランスポート用に標準入力を開いたままにします。
イメージは CPM_PLANNER_DB=/data/cpm-planner.db を設定し、特権を持たない app ユーザーが所有するボリュームとして /data を宣言します。そのため、名前付きボリュームを使うと、実行をまたいで計画の状態を保持できます。バインドマウント(-v "$PWD:/data")を使う場合は、ディレクトリを書き込み可能にするため、自分のユーザーとして実行してください:--user "$(id -u):$(id -g)"。パスを変更する場合に限り、-e CPM_PLANNER_DB=... を渡してください。
クライアントにイメージを登録するには、command に docker を設定し、残りを args に指定します。たとえば、Claude Code では次のようにします。
claude mcp add cpm-planner --scope user -- docker run -i --rm -v cpm-planner-data:/data ghcr.io/praxec/cpm-planner
インストールの確認
cpm-planner --version
cpm-planner <version> が出力されます。クライアントを使わずに MCP 側を確認するには、リポジトリからスモークテストスクリプトを実行します。このスクリプトは MCP の initialize と tools/list のハンドシェイクを実行し、plan.submit、plan.status、plan.get のいずれかが欠けている場合は失敗します。
node scripts/mcp-smoke.mjs /absolute/path/to/cpm-planner
クイックスタート:コードとしてプランを作成する
.cpm-planner/plans/<name>/<variant>.json にプラン(PlanGraph)を記述します。
plan.lint {path: ".cpm-planner/plans/checkout/main.json"}— 状態を書き込まずに静的チェックを行います。plan.sync {path: ".cpm-planner/plans/checkout/main.json"}— バリアントを登録し、そのplan_idを返します。plan.status {plan_id}— スケジュール、クリティカルパス、準備完了セット、ロックを確認します。
plan.sync はコンテンツハッシュでファイルを追跡します。追跡中のファイルと保存されている最新のグラフが一致しない場合、plan.status は definition_drift を報告します。
クイックスタート:アーンドバリュー
ベースラインを確定し、進捗を記録してからレポートを確認します(earning_rule: "weighted" では earned_pct は比率に応じて計上されます。fifty_fifty では成果物が進行中になるか、報告された earned_pct がある時点で 50%が計上され、デフォルトの zero_hundred では完了時に計上されます)。
plan.baseline {plan_id}— CPM スケジュールと予算をベースライン 1 として確定します。plan.mark_status {plan_id, deliverable_id, caller_id, status: {"status": "in_progress"}, earned_pct: 50, actual_effort_hours: 4}— 進捗と実コストを報告します。plan.ev {plan_id}— PV、EV、AC、SV、CV、SPI、CPI、EAC、アラートを確認します。plan.snapshot {plan_id, format: "markdown"}— レポートを追記し、Markdown テーブルとしてエクスポートします。
分母がゼロの比率は null となり、undefined で説明されます。アラート(SPI_BELOW_0_9、CPI_BELOW_0_9)は、保存されている直近 2 件の測定値を比較します。
AI エージェントでの使用
任意の MCP クライアントで、stdio 経由で cpm-planner を実行できます。cpm-planner バイナリをコマンドとして登録するか、Node 18 以降では npx -y @matthew-cochran/cpm を使用します。GUI クライアントでは、インストーラーが出力した絶対パスを使用してください。
cpm-planner skills install --target <tool> --user(または --project <dir>)を実行して、エージェントスキル(/cpm-plan など)をインストールします。<tool> には claude、codex、cursor、copilot、gemini、all、agents-md(プロジェクトのみ)を指定できます。
docs/AGENT-INSTALL.md に、クライアントごとの手順(Claude Code、Claude Desktop、Codex、Cursor、VS Code、Gemini CLI など)、env ブロック、確認方法、トラブルシューティングが記載されています。llms.txt では、LLM 向けのドキュメントを案内しています。
MCP ツール
| ツール | 内容 |
|---|---|
plan.submit | タスクグラフを送信し、プラン ID を返します(グラフと呼び出し元が同じ場合は冪等です)。前提条件には、成果物 ID の文字列、またはオブジェクト {id, consumes?, kind?: artifact|interface, lag_hours?} を指定できます。どちらの形式も plan.get で取得できます。成果物には milestone: true(受け入れポイント。見積もりまたは期間が指定されない限り長さはゼロで、plan.status の milestones に報告されます)を設定できます。任意の earning_rule(デフォルトの zero_hundred:完了時のみ 100%、fifty_fifty:進行中になるか earned_pct が報告された時点で 50%、weighted:報告された earned_pct)は、部分的な進捗に対する出来高の計上方法を設定し、プランの識別情報の一部となります。成果物の任意の duration_hours(暦時間)は、スケジュール上の長さとして工数に代わり、前提条件の lag_hours は依存する成果物の開始を遅らせます。工数は引き続きコストの基準です。任意の estimate {optimistic, likely, pessimistic}(0 <= optimistic <= likely <= pessimistic)は、3 点の工数見積もりです。スケジュール上の長さの優先順位は、duration_hours > estimated_effort_hours > estimate.likely > マイルストーンの場合は 0 > 推定器のデフォルトです。Monte Carlo は、duration_hours と estimated_effort_hours のどちらも設定されていない場合に限り、見積もりをサンプリングします。制限:成果物は最大 5000 件で、すべての時間値(工数、期間、ラグ、見積もり)は有限かつ 0~1000000 の範囲内である必要があります(INVALID_GRAPH)。name(任意の project/variant。variant のデフォルトは main)を指定すると、名前のないプランではなく、名前付きの variant として登録されます。 |
plan.acquire_cohort | 相互にファイルセットが重複しない、準備完了済みの成果物を最大 N 件、アトミックに取得します(owned_files のエントリには {path, mode: "append"} を指定できます。同じパスへの append クレームは共同リースでき、shared_paths に表示されます。複数の成果物が同じファイルを所有できるのは、前提条件によって順序付けられている場合、またはすべてのクレームが append の場合に限ります)。任意の ttl_seconds はリースの TTL を設定します(サーバーの最大値に制限されます)。任意の ids と filter.metadata で成果物を対象指定できます。metadata.kind = "manual" の成果物はリースされません。応答の blocked には未リースの候補が一覧表示されます(blocked_count、needs_operator を含みます)。 |
plan.heartbeat | 保持中のロックの TTL を更新します。任意の ttl_seconds で新しい TTL を設定します(サーバーの最大値に制限されます)。 |
plan.mark_status | 成果物を完了/失敗としてマークし、ロックを解放します。ロックがない場合、完了にはすべての前提条件の完了が必要です(PREREQUISITES_INCOMPLETE)。ロックなしでのマークはすべて監査されます。ロックなしの in_progress(所有者による作業または手動作業)はサーバーの再起動後も維持され、リース対象になりません。ロックなしで ready(またはその他のステータス)にマークすると、作業を返却できます。任意の出来高進捗:earned_pct(整数 0~100。in_progress の場合のみ指定可能で、complete と併用した場合は受け入れられますが無視されます)、actual_effort_hours(現時点までの累計工数。有限で 0~1000000。リース時間に代わる実コストとして扱われます)、evidence(最大 2048 文字。成果物のエビデンス一覧に追加され、最大 100 件を保持します)。負数、小数、または 100 超の earned_pct を含む違反は INVALID_ACTUALS になります。plan.select は、引き継ぐ完了ステータスを持つ各成果物の実績値をコピーします(リース時間は合算され、引き継ぐ成果物の報告済み割合と時間が優先され、最新のエビデンス 100 件が保持されます)。終了したリース(完了、失敗、強制解放、期限切れ、受け入れによる上書き、強制的な revise/select/archive)はすべて、その時間を成果物のリース時間に加算します。期限切れになったリースは、期限までの時間が加算されます。 |
plan.status | プランとそのロックの読み取り専用スナップショットを返します。critical_path は常に __start__ から __finish__ までです(合成された工数ゼロの終点です。これらの schedule 行には synthetic: true が付き、__start__/__finish__ は予約済みの成果物 ID として INVALID_GRAPH で拒否されます)。リースを無効にする強制的な改訂では superseded_revision が報告されます。前提条件の完了後に再取得できますが、古い所有者は完了としてマークできません。すべての成果物が完了すると plan_complete が true になり、その時点で plan.completed 監査イベントが一度だけ発生します。milestones には、milestone: true(または従来形式の metadata.milestone == true)を持つ成果物ごとに、id、critical_path(__start__ からその成果物までの最長経路)、hours(最早終了時刻)、complete の行が 1 つずつ含まれます。名前付き variant の場合は、さらに name、variant、selected、archived、active_plan(variant がアーカイブされている場合の、プロジェクト内の唯一のアクティブなライン名)も報告されます(名前のないプランでは archived と active_plan は null です)。definition_drift は、variant のプロジェクトにプロジェクトルートがない場合、追跡対象のプランファイルがない場合、またはファイルが存在しない、読み取り不能、あるいは 8 MiB を超える場合は null(不明)です。それ以外の場合、ファイルのバイト列が最後に同期またはエクスポートされたハッシュと一致するか、ファイルのグラフがヘッドグラフと一致すれば(再フォーマットはドリフトではありません)false、ファイルのグラフがヘッドと異なる場合(または解析できない場合)は true です。そのため、ファイルに紐付いた variant に対してインラインで plan.revise/plan.sync を実行すると、ファイルを再エクスポートまたは再同期するまで true が報告されます。 |
plan.get | plan_id、plan ライン名、または active: true で選択したプランの保存済みグラフを返します(送信した内容を読み戻します)。 |
plan.force_release | オペレーター用の緊急解除手段です。所有者や TTL に関係なくロックを解放します。reset_counters: true を指定すると、期限切れ/失敗のカウンターもクリアされます。ロックなしの in_progress にはロックがないため、plan.force_release を実行しても状態は変わりません。ロックなしで plan.mark_status を実行して返却してください。 |
plan.accept | マネージャー/所有者による受け入れです。リースを保持せずに成果物を完了としてマークします(エビデンス付きで監査されます)。 |
plan.lint | 送信せずに静的チェックを実行します。サイクル(ループを含む)、冗長なエッジ、根拠のないエッジ、コントラクトを対象としていないインターフェースエッジ、いずれのマイルストーンにもつながらない成果物、順序付けされていないファイルの重複(#20)を検出します。 |
plan.schedule | リソース容量(デフォルトでは metadata.owner)に合わせてグラフの負荷を平準化します。総所要時間、成果物ごとの開始/終了時刻、リソースごとの負荷、駆動チェーン(依存関係による待ち時間と名前付きリソースによる待ち時間)、プロジェクトバッファ/フィードバッファを返します(#19)。成果物は metadata.resources: {"agent":1,"builder":1} により複数のプールをアトミックに要求できます。要求するプールごとに十分な容量が必要です。metadata.wall_clock_only: true を指定した duration_hours は、依存先をブロックするものの容量を消費しない CI/観測時間をモデル化します。project_buffer_pct は 0~100 です(デフォルトは 25)。 |
plan.simulate | グラフ、保存済みプラン、またはプランファイルに対する読み取り専用の what-if シミュレーションを実行します(何も保存しません)。lint、クリティカルパス、スケジュール、マイルストーン、任意のリソーススケジュール(schedule。plan.schedule と同じ入力および INVALID_CAPACITIES: ルール)と Monte Carlo(monte_carlo:iterations は 1~50000、デフォルトは 2000、seed のデフォルトは 0xC0FFEE、iterations × (成果物数 + 前提条件エッジ数) は 200000000 以下)を実行し、スコアカードも返します(#23)。 |
plan.release.compile | バージョン管理された制限付きのワークフロー/昇格メタデータを、lint を通過する通常のプランにコンパイルします。保護された PR、並列チェック/結合、所有者による待機/承認/マージ、生成側の再試行レシート、保持されたアーティファクト、ネイティブの固定費統合ウェーブ/エビデンス再利用、中央での受け入れに対応します。バッチ処理と変更ごとのゲートのコスト効率および優位性に関する警告を報告します。オフラインで実行され、作業の実行や受け入れは行いません(リリースワークフロー)。 |
plan.release.diff | 保持された生成済み graph と現在の workflow メタデータを比較し、プランの改訂またはベースライン化の前に、ポリシー/見積もりのドリフトと追加、削除、変更された ID を報告します(リリースワークフロー)。CLI の同等コマンド:cpm-planner release compile、release lint、release diff。 |
plan.sync | プランファイル(形式は .cpm-planner/plans/<name>/<variant>.json の path)またはインラインの graph から、名前付きプランラインの variant を 1 つ登録または更新します(name が必要です。variant のデフォルトは main)。ファイルはシンボリックリンクをたどらない制限付きパスで読み込まれ、ドリフト検出用にコンテンツハッシュが追跡されます。project のデフォルトは検出されたプロジェクトルートです。path を指定した場合、指定する name/variant/project はファイルの値と一致する必要があります(INVALID_PATH: name/variant/project must match the plan file path)。force を指定すると、削除された成果物の有効なロックを解放します。 |
plan.list | project(デフォルト:検出されたプロジェクトルート)のすべてのプランラインを、名前順、variant はその中でソートして一覧表示します。include_archived を指定しない限り、アーカイブ済みのラインと variant は除外されます。active: true を指定すると、プロジェクトのアクティブなラインのみを返します。この指定は include_archived と併用できません。 |
plan.export | plan_id のヘッドグラフをその variant 専用のファイル、または制限付きの path に書き込み、ルートからの相対パスを返します。別の variant が追跡しているプランファイルへの書き込み、または同期されていないローカル編集がある variant 自身のファイルへの書き込みは拒否されます(INVALID_PATH)。ただし、force: true を指定した場合は除きます。書き込まれたファイルは同期されません。ただし、variant 自身が追跡しているファイルにエクスポートした場合はハッシュが記録されます(その場合、ドリフトは false になります)。 |
plan.revise | プランのグラフをその場で置き換え、進捗を引き継ぎます(変更のない成果物はステータス/カウンターを保持し、変更された成果物または再オープンされた成果物は再導出されます)。成果物には、直接の前提条件を示す metadata.consumes_revision_from を宣言できます。このバリアまたはいずれかの前提条件を変更すると、有効なリースが拒否されます。force を指定すると、診断情報 superseded_revision が報告され、以前のエビデンス/時間が保持されます。新しい revision と差分を返します。force を指定すると、削除された成果物の有効なロックを解放します。 |
plan.fork | 名前付き variant のヘッドグラフをコピーし、順序付きの edits を適用して、同じラインの新しいドラフト(未選択)variant として登録します。アーカイブ済みラインへの fork は、ファイルが書き込まれる前に ARCHIVE_REFUSED で拒否されます。アクティブなラインのアーカイブ済み variant からの fork は可能です。ファイル書き込み後に登録に失敗した場合、そのファイルは削除されます。 |
plan.select | 名前付き variant をライン内で選択済みの(実行可能な唯一の)variant とし、進捗を引き継ぎます。force を指定すると、以前に選択されていた variant のロックを解放します。 |
plan.archive | ライン全体または 1 つの variant をアーカイブします(archived のデフォルトは true)。アーカイブ解除もできます。アーカイブ済み variant は読み取り可能ですが、同期、選択、実行は拒否されます(ARCHIVE_REFUSED)。 |
plan.compare | 保存済みプランのスコアカードを比較します(plan_ids は異なる ID を 2~16 個指定するか、project(デフォルト:検出されたルート)内の plan ライン名を指定すると、アーカイブされていないすべての variant が対象になります。最大 16 個です)。パレートフロント、重み付き順位、推奨プランを返します。同点の場合は同じ順位になり、tied_with_recommended に推奨プランと同点の variant が一覧表示されます。重みは有限かつ >= 0 である必要があります。monte_carlo を指定する場合、全 variant にわたる iterations × (成果物数 + 前提条件エッジ数) の合計は 200000000 以下である必要があります(INVALID_GRAPH)。読み取り専用です。スコア計算は非同期ランタイム外で実行されます。 |
plan.baseline | プランの現在の CPM スケジュール(成果物ごとの最早開始/終了時刻)と予算(工数ベース × metadata.cost_rate。デフォルトは 1)を、次の番号付き出来高ベースラインとして固定します。任意の start(RFC 3339。デフォルトは現在時刻)および calendar {hours_per_day (0 < h ≤ 24, default 8), workdays (default mon–fri), utc_offset_minutes (default 0)} を指定できます(省略時、最初のベースラインでは壁時計上の時間を使用し、ベースラインを再設定する場合は前回のカレンダーを維持します)。最初のベースラインの番号は 1 です。再ベースラインには空白でない reason(最大 2048 文字。そうでない場合は INVALID_GRAPH)が必要で、実績値とスナップショットは維持されます。ベースライン、実績値、スナップショットは 1 つの variant に属します。新しく選択された variant には、理由を指定せずに独自のベースライン 1 が設定されます。実行側の操作は選択済みかつ未アーカイブの variant のみ対象です(VARIANT_NOT_SELECTED/ARCHIVE_REFUSED)。plan.ev.baselined として監査されます。 |
plan.ev | as_of(RFC 3339。デフォルトは現在時刻)時点の最新のベースラインに基づく出来高レポートです。as_of は PV のステータス日です。EV と AC は、呼び出しが実行される時点までに記録された進捗と実績値を反映します。BAC、PV、EV、AC、SV、CV、SPI、CPI、EAC、ETC、VAC、TCPI、成果物ごとの行、消費済みクリティカルフロート、SPI_BELOW_0_9/CPI_BELOW_0_9 アラート(現在のベースラインの as_of 時点で、保存済みかつバックフィルされていない最新の 2 件のスナップショットにおいて指標が 0.9 未満の場合に発生。現在の読み取り値はその 2 件に含まれません)、excluded_unbaselined(ベースライン設定後に追加された成果物)を返します。AC は、削除済みおよびベースライン未設定の成果物を含め、プランに記録されたすべての時間を合計します(ベースライン行のコストレートを使用し、設定されていない場合は 1 を使用します)。そのため、再ベースライン後も支出が消えることはありません。plan.revise によって削除されたベースライン設定済みの成果物は、削除時点で獲得していた割合(完了済みなら 100、それ以外は earning rule の割合)を保持し、行のステータスは removed として報告されます。再追加すると、獲得割合はリセットされますが、時間は累積され続けます。分母が 0 の比率は null になり、undefined で説明されます。出力に NaN や無限大が含まれることはありません。アーカイブ済みを含むすべての variant で読み取り専用です。アーカイブ済みの場合は archived: true を返し、プロジェクトにアクティブなラインがちょうど 1 つある場合はその active_plan も返します。plan.baseline の前は NOT_BASELINED になります。 |
plan.snapshot | plan.ev レポートを計算してスナップショットとして追加します(as_of は PV のステータス日です。EV と AC は呼び出し時点で記録されている進捗を反映します)。as_of が taken_at より 1 時間を超えて前の場合、そのスナップショットは backfilled: true としてマークされ、アラートを発生させず、後続のアラート判定でも除外されます。summary(各 null 比率の説明を含む undefined 付き。アラートはこのスナップショットの位置までの読み取り値のみを対象とします。つまり、現在のベースラインにおける as_of 順で、このスナップショットとそれより前にある最新のバックフィルされていないスナップショットを対象とするため、バックフィルによって新しい読み取り値のアラートが引き継がれることはありません)、snapshot_count、as_of 順の最新 100 件のスナップショットを古い順に並べた export(同じ日付の場合は取得時刻順)を返します。これにより、バックフィルされた as_of は日付順に配置されます。この 100 件より古いバックフィルは保存・計数されますが、一覧には表示されません。出力形式は、要約の一覧(format: "json" がデフォルト)または日付、PV、EV、AC、SPI、CPI、EAC の列を含む Markdown テーブル(format: "markdown"。未定義の比率は n/a と表示)です。実行側の扱いは plan.baseline と同じです。ベースライン設定前は NOT_BASELINED になります。 |
plan.review | グラフ、保存済みプラン、またはプランファイルに対する任意の AI レビューです(読み取り専用。graph、plan_id、path のうち指定できるのは 1 つだけです。任意の capacities/resource_key/project_buffer_pct で総所要時間を平準化でき、max_questions は 1~64、デフォルトは 64 です)。必ず lint を実行します。lint エラーがある場合は、審査役への呼び出しを行わず status: "invalid_graph" を返します。それ以外の場合は、Jev への 1 回のまとめた呼び出しで、依存関係の誤りの可能性と不足、分割およびインターフェース分割の候補、クラッシュオプションについて質問し、助言的な findings と proposals を返します。proposals は plan.fork の編集リストであり、それぞれ simulate で検証されます(lint を通過し、総所要時間を短縮)。hours_saved / max(cost, 1) の順に順位付けされます。キーがない場合、または LLM の設定が使用できない場合は、lint とともに reason を含む status: "review_unavailable" を返します。プランレビュー(任意)を参照してください。 |
plan.status、plan.get、plan.ev、plan.snapshot、plan.baseline、 | |
plan.acquire_cohort、plan.heartbeat、plan.mark_status、plan.accept、plan.force_releaseでは、plan_id、plan(選択中のバリアントに解決されるプランのライン名)、active: true(アーカイブされておらず、選択中のバリアントもアーカイブされておらず未完了である、プロジェクト内の唯一のライン)のいずれか1つだけでプランを指定します。planとactiveには、オプションでprojectを指定できます(デフォルト:検出されたプロジェクトルート)。plan_idと併せたprojectの指定は無効なパラメーターです。アクティブなラインがない場合はNO_ACTIVE_PLAN、複数ある場合はその名前を示してAMBIGUOUS_ACTIVE_PLANが返されます。不明なライン、または選択中のバリアントがないラインの場合はPLAN_NOT_FOUNDが返されます。 | |
定期ジョブやエージェントは、次のラインに作業を引き継げるよう、plan_idを固定せずにactive(またはplan)でプランを検索してください。activeが一致するのは未完了のラインのみで、別のラインが開始されると対象が変わる(または曖昧になる)ため、最初に一度だけ解決し(plan.statusとplan.acquire_cohortはplan_idを返します)、その後はそのプランのハートビート、ステータスマーク、最後のplan.status/plan.evには同じplan_idを使ってください。アーカイブ済みのバリアントのIDを固定した場合も、plan.status/plan.evで読み取りは可能です。これらはarchived: trueと、実際に進行中の作業先を示すactive_planを返しますが、スナップショット、ベースライン、実行はARCHIVE_REFUSEDで拒否されます。 |
plan.lint、plan.simulate、plan.reviewでは、インラインのgraph、保存済みのplan_id、プランファイルのpathのいずれか1つだけを指定します。plan.scheduleではgraphまたはplan_idを指定します。
plan.scheduleとplan.simulateは、plan.submitが拒否する入力を拒否し、plan.lintはそれらを指摘事項として報告します。モンテカルロ出力は、同じプラットフォームとツールチェーンであれば同じシードに対して再現可能ですが、浮動小数点演算関数に差異が生じることがあるため、ターゲットやコンパイラのバージョンをまたいでビット単位で同一の結果になるとは限りません。
プランをコードとして扱うワークフロー
.cpm-planner/plans/<name>/<variant>.jsonにプランファイルを作成し、plan.lint {path}でチェックしてから、plan.sync {path}で登録し、返されたplan_idを使って実行します。名前付きラインには複数のバリアントがありますが、選択されるのは常に1つだけです。plan.forkは構造化編集からドラフトを作成し、plan.compareはバリアントを採点し、plan.selectは1つを実行可能にします。定義は追跡対象のファイルに保存し、未追跡の一時的なグラフは決して保存しないでください。
計画レビュー(任意)
plan.review は OpenRouter 経由で、TypeSafe の較正済み判断モデルである Jev(typesafe/jev-1.13)に、lint を通過する計画について問い合わせます。1 回のレビューで最大 64 件の質問をまとめて送信します。OPENROUTER_API_KEY(または CPM_OPENROUTER_KEY_FILE)を設定するまで無効です。キーがなくてもツールは応答し、review_unavailable と lint レポートを返します。LLM の設定が無効でもサーバーは停止しません。起動時にログへ記録され、plan.review は設定名を示す理由とともに review_unavailable を報告します。
-
確率は参考情報です。 検出結果はセカンドオピニオンとして扱ってください。提案は機械的に検証されます(編集後の計画が lint を通過し、シミュレーションでメイクスパンが短くなる必要があります)。
plan.fork {edits}で適用し、その後plan.compareを実行してください。 -
コスト。 判定モデルへの呼び出しに到達した
plan.reviewは、1 回につき OpenRouter の課金対象リクエスト 1 件です。OpenRouter での Jev の料金は、入力トークン 100 万件あたり約 0.042 ドルです。レポートには、プロバイダーから提供された場合にusageが含まれます。サーバーあたり、判定モデルを呼び出すレビューは同時に最大 2 件まで実行され、それ以降の呼び出しは空き枠ができるまで待機します(キーがない場合や lint エラーの場合など、判定モデルを呼び出す前に終了するレビューは待機しません)。 -
プライバシー。 この 1 件のリクエストで OpenRouter に送信される情報は次のとおりです。
- 固定のタスク文、計画のメイクスパン、クリティカルパス(ID)。
- 質問:各質問について、その種類、対象として挙げる成果物の ID、それらの ID を引用した質問文。質問の種類に応じて、前提条件の
consumesテキスト、成果物のスケジュール済み時間、計画のスケジュール済み時間の中央値、依存関係の欠落に関する質問を促したヒューリスティック信号(説明文が他の項目に言及していること、同じディレクトリまたは入れ子のディレクトリにファイルがあること、metadata.ownerが共通していること)も含まれます。 - 質問で挙げられた各成果物について、その ID、スケジュール済み時間、余裕時間、
criticalとmilestoneのフラグ、所有するファイルパス(省略せず完全な形で送信)、前提条件(ID、consumes、種類)、およびdescription、artifact、ownerのメタデータ。description、artifact、owner、consumesはそれぞれ 500 文字で切り詰められます。
グラフ内のそれ以外の情報(他の成果物、その他のメタデータキー、見積もり)は送信されません。内容を OpenRouter と共有できない可能性がある計画はレビューしないでください。
-
監査。 キーがログに記録されたり返されたりすることはありません。LLM 変数に誤って設定された値も同様です。結果にかかわらず、すべての
plan.review呼び出しでplan.review監査イベントが 1 件記録されます(計画が見つからない場合、パスが不正な場合、レビューに失敗した場合を含みます)。監査されないのは、パラメーターが原因で呼び出しが拒否された場合(invalid_params)のみです。イベントには次のフィールドのみが含まれます。status:ok、review_unavailable、invalid_graph、errorのいずれか(レビュー失敗時はPLAN_NOT_FOUND、INVALID_PATH、INVALID_CAPACITIESなど)。code:errorの場合はエラープレフィックス、それ以外は null。failure_class:判定モデル呼び出しの失敗が原因でreview_unavailableになった場合は、そのクラス(unauthorized、rate_limited、timeout、upstream、decode、transport、invalid_request)。それ以外は null(キーがない場合や、使用できない LLM 設定の場合を含む)。plan_id:レビューされた保存済み計画。インラインのgraphまたはpathの場合は null。question_count:送信された質問の数(判定モデルが呼び出されなかった場合は 0)。jev_called:判定モデルが呼び出されたかどうか。prompt_hash:正規化されたリクエストの sha256。判定モデルが呼び出されなかった場合は null。model:プロバイダーが報告したモデル。呼び出しに失敗した場合は設定済みのモデル。判定モデルが呼び出されなかった場合は null。endpoint:判定モデルのエンドポイントのホスト。判定モデルが設定されていない場合、lint でエラーが見つかった場合、またはレビューがerrorで終了した場合は null。
プロンプト自体が記録されることはありません。
ライブラリとして使用する
CPM カーネルは、MCP に依存しない通常の Rust ライブラリとしても利用できます。
use cpm_planner::{CpmAlgorithm, Task, TaskKind};
let mut tasks = vec![
Task::new("design", "Design", TaskKind::Custom { description: "design".into() }, 4.0),
Task::new("build", "Build", TaskKind::Custom { description: "build".into() }, 8.0)
.depends_on("design"),
Task::new("test", "Test", TaskKind::Custom { description: "test".into() }, 2.0)
.depends_on("build"),
];
let result = CpmAlgorithm::calculate(&mut tasks);
println!("critical path: {:?}", result.critical_path); // ["design", "build", "test"]
// also: result.bottlenecks, result.optimal_duration_parallel,
// and per-task .float (slack) / .is_critical on each Task.
クレートレベルのドキュメント(cargo doc --open、または現行バージョンが公開された後は docs.rs)には、submit、lease、complete を通じてプランナーを動作させる実行可能な例があります。
llm::jev::JevJudge(plan.review の判定処理)は、HTTP クライアントと接続プールを所有します。プールされた接続は、それを開いた tokio ランタイムによって駆動されるため、判定処理とそのクローンは同じランタイムで使用し、別のランタイムには新しい判定処理を作成してください。
Praxec
cpm-planner は完全に単独で動作し、通常の MCP で通信するため、特定のクライアントにコード依存しません。Praxec のパックでは、MCP ツールとして使用されています。praxec のワークフローに接続するには、MCP 接続を宣言します(プロトコルのみで、コード共有はありません)。
connections:
planner:
kind: mcp
command: cpm-planner
このツールと、それを使うワークフローパックを最も簡単にセットアップして実行する方法は、次のワンコマンドセットアップです。
curl -fsSL https://raw.githubusercontent.com/praxec/packs/main/setup.sh | bash
このツールのプロバイダー座標(コンテナーイメージまたはリリースバイナリ)と、それに依存するパックについては、パックレジストリをご覧ください。
環境変数
クライアントの env ブロック(または -e/--env フラグ、あるいは docker run -e)で設定します。すべて任意です。
| 変数 | デフォルト | 意味 |
|---|---|---|
CPM_PLANNER_DB | すべての OS で ~/.local/share/praxec/cpm-planner.db(~ は HOME、それがない場合は USERPROFILE を指します。Windows では %USERPROFILE%\.local\share\praxec\cpm-planner.db);Docker イメージでは /data/cpm-planner.db | 永続的かつプロセス間で共有されるプランナー状態を保存する SQLite のパスです。:memory: を指定すると、一時的な状態になります。 |
CPM_PLANNER_STATE_MODE | 未設定 | 通常の永続状態のオープンでは未設定のままにします。既存のデータベースが空である場合、またはサイドカーのレシートによって既知のプランが失われていることが検出された場合、起動時に変更を拒否します。サーバーが報告したタイムスタンプ付きバックアップのパスを確認した後に限り、recover を設定してください。initialize は既存の空の場所を明示的に受け入れます。すべての MCP の結果で、解決済みの場所、結果、バックアップパス(存在する場合)を含む durable_state が報告されます。 |
CPM_PROJECT_ROOT | .cpm-planner/ または .git がある、cwd の最も近い祖先 | プランをコードとして保存するファイル(.cpm-planner/plans/<name>/<variant>.json)のリポジトリルートです。ルートが必要なツールは、ルートが見つからない場合に INVALID_PATH: no project root (set CPM_PROJECT_ROOT or run inside a repo) を報告します。 |
CPM_MAX_TTL_SECS | 28800(8 時間) | plan.acquire_cohort と plan.heartbeat の ttl_seconds に対するサーバー側の上限です。要求された値が大きい場合は切り詰められます。1..=2592000 の整数(最大 30 日)でなければならず、それ以外の値では起動が中止されます。 |
OPENROUTER_API_KEY | 未設定 | plan.review 用の OpenRouter キーです。未設定または空白の場合、plan.review は review_unavailable(「OpenRouter key configured」ではなく「OpenRouter key が設定されていません」)を報告します。ログに記録されたり、返されたりすることはありません。 |
CPM_OPENROUTER_KEY_FILE | 未設定 | OPENROUTER_API_KEY が未設定の場合に使用される、OpenRouter キーを格納したファイルです(内容の前後の空白は削除され、最大 4096 バイト)。unix では、全ユーザーに読み取り可能な(o+r)ファイル、または空のファイルは警告とともに無視されます(chmod 600 を適用してください)。 |
CPM_JEV_MODEL | typesafe/jev-1.13 | plan.review 用の Jev モデル ID です。A-Z a-z 0-9 . _ : / - の文字を最大 128 文字含めることができ、キーを含んではなりません。それ以外の場合は、値ではなく変数名を示すログが記録され、plan.review は利用できなくなります。 |
CPM_JEV_ENDPOINT | https://openrouter.ai/api/v1/systemone | Jev エンドポイントの URL です。認証情報を含まない https://、またはループバックホストに限り http:// を使用できます。 |
CPM_LLM_TIMEOUT_SECS | 30 | 各 LLM 呼び出しのタイムアウトです。1..=300 の整数秒で指定します。 |
CPM_LLM_MODEL | deepseek/deepseek-v4.1-flash | 生成(チャット)モデル ID です。A-Z a-z 0-9 . _ : / - の文字を最大 128 文字含めることができます。フロンティアベンダーは呼び出し前に拒否され、モデル名を示す型付きエラーが返されます:anthropic/、openai/(openai/gpt-oss* を除く)、google/、x-ai/、xai/。 |
リースのデフォルトは 5 分です。長時間の作業では、取得/ハートビート時に ttl_seconds(サーバーの最大値以下)を渡し、少なくとも ttl/3 ごとにハートビートしてください。
ドキュメント
- docs/README.md:プロジェクトドキュメントの目次です。
- docs/AGENT-INSTALL.md:AI コーディングツールに cpm-planner をインストール、登録し、動作を確認する方法です。
- docs/architecture.md:モジュール、リクエストフロー、ストアのスキーマ、並行処理について説明しています。
- docs/releasing.md:リリース手順書です。
- CONTRIBUTING.md、SECURITY.md、SUPPORT.md、CHANGELOG.md。
コントリビューション
コントリビューションを歓迎します。ツールチェーン、ゲート、ブランチモデルについては、CONTRIBUTING.mdをご覧ください。参加するすべての方は、行動規範に同意するものとします。
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。