MCP ツールリファレンス
VMark は AI アシスタントに 10 個の複合 MCP ツール を公開します:session、workspace、document、workflow、selection、comments、browser、browser_read、coherence、coherence_resolve。これらは合わせて、エディタの読み書きのバックボーン、ファイル/ウィンドウのライフサイクル、CST セーフなワークフロー編集、選択範囲を対象とするピンポイント編集、制限付きのブラウザナビゲーション、そしてワークスペース整合性レイヤーのビューをカバーします。
10 個のうち 3 つ——session、browser_read、coherence——は readOnlyHint: true を宣言しているため、MCP クライアントはこれらを自動承認できます。browser/browser_read と coherence/coherence_resolve がそもそも別々のツールに分かれているのはこのためです:アノテーションはアクションごとではなく ツールごと に付くので、ARIA スナップショットと execute_js を 1 つにまとめたツールは、execute_js の危険性を表明せざるを得なくなります。「これは何かを変更するか?」という基準で分割することで、それぞれの半分が真実を表明でき、サーフェスの本当に破壊的なアクションをツールリスト内で目立たせられます。
以前の 12 ツール/76 アクションのサーフェスは整理されました——ドキュメント内のフォーマットツール(太字、見出し、テーブルなど)は、AI エージェントがすでに Markdown のラウンドトリップで簡単にこなせる作業を重複していたためです。selection は(プルーニングプランの ADR-7 に従い)残されました。ドキュメント全体のラウンドトリップは大きなファイルでは非効率だからです——編集のたびにドキュメント全体を入力トークンとして、ドキュメント全体を出力トークンとして(入力の約 5 倍の料金)支払い、さらに書き込みウィンドウが長くなって古いリビジョンによるリトライループが広がります。完全な根拠は MCP プルーニングプラン を参照してください。
推奨ワークフロー
session.get_stateを 1 回呼び出して、開いているウィンドウ、タブ、タブごとの{filePath, dirty, revision, kind}を確認します。- 小さな Markdown の変更や全面的な書き直しの場合:
document.read→ 推論 →document.write(安全な並行性のためにexpected_revisionを渡す)。 - 大きな Markdown ファイルで、変更対象の領域をユーザーが選択している場合のピンポイント編集:
selection.get→ 推論 →selection.set(入力と出力の両方のトークンコストを選択範囲まで削減)。 - GitHub Actions YAML(
kind: "yaml-workflow")の場合:コメントとアンカーを保持する CST セーフな編集にはworkflow.apply_patch、actionlint 診断にはworkflow.validate。 - ファイル操作(開く、保存、閉じる、タブ切り替え)は
workspaceにあります。
Mermaid ダイアグラム
MCP 経由で AI を使用して Mermaid を生成する場合は、mermaid-validator MCP サーバー のインストールを検討してください——ダイアグラムがドキュメントに到達する前に、同じ Mermaid v11 パーサーで構文エラーをキャッチします。
session
ワンショットの状況把握。1 回の呼び出しですべてのウィンドウ、すべてのタブ、サーバーの機能を発見します。
get_state
引数なし。
返り値 {windows, capabilities}:
{
"windows": [
{
"label": "main",
"focused": true,
"activeWorkspaceInstanceId": "wsi-a1b2c3",
"tabs": [
{
"id": "tab-1",
"filePath": "/path/to/notes.md",
"title": "notes",
"dirty": false,
"revision": "rev-x7Q3aB1F",
"kind": "markdown",
"active": true,
"visible": true
},
{
"id": "tab-2",
"filePath": "/repo/.github/workflows/ci.yml",
"title": "ci",
"dirty": true,
"revision": "rev-x7Q3aB1F",
"kind": "yaml-workflow",
"active": false,
"visible": false
}
]
}
],
"capabilities": {
"version": "<vmark-mcp-server version>",
"supportedKinds": ["markdown", "yaml-workflow"],
"mcpProtocol": "0.2.0"
}
}画面に実際に表示されているものを知る
タブは存在し、アドレス指定可能でありながら、それでも表示されていないことがあります。3 つのフィールドがそれを示します:
| フィールド | 意味 |
|---|---|
tab.active | このタブは、そのウィンドウの現在のタブです。 |
tab.visible | このタブは今この瞬間にレンダリングされています。ウィンドウが現在表示していないワークスペースインスタンスにタブが属している場合は false になります。 |
window.activeWorkspaceInstanceId | ウィンドウが表示しているワークスペースインスタンス。ワークスペースレールがオフの場合は null(その場合はすべてのタブが可視)。 |
window.focused は、オペレーティングシステムから読み取った、ユーザー が見ているウィンドウです。「このリクエストに応答したウィンドウ」ではありません——VMark は該当するワークスペースを所有するウィンドウにリクエストをルーティングするため、マルチウィンドウのセッションではそれが別のウィンドウであることがよくあります。
windows にはすべてのドキュメントウィンドウ(main と、Finder やコマンドラインから開いた各ウィンドウ)が並びます。VMark がそのすべてに問い合わせるためです。AI クライアントで入力している間は VMark のどのウィンドウにもフォーカスがなく、focused はすべて false になります。このとき tabId もワークスペースのパスも持たないリクエストは、main ではなく最後に使ったドキュメントウィンドウに送られます。
これらは確認ステップとして扱ってください:workspace.switch_tab の後にもう一度 get_state を呼べば、そのタブが本当にユーザーの前面にあるかどうかがわかります。switch_tab 自体も応答前にストアを再読み取りするため、アクティブ化が成立しなかった場合は、リクエストをそのまま返すのではなく activated: false を報告します。
kind の判別子は、そのタブで document.write(markdown 用)と workflow.apply_patch(yaml-workflow 用)のどちらを使うべきかを示します。
workspace
ファイルとウィンドウのライフサイクル。ドキュメント内のことは扱いません。
パスのスコープ。 ファイル操作(
open、save、save_as)は、開いている ワークスペースのルートと、すでに開いているドキュメントのディレクトリに限定されます。 そのスコープ外のパスへのリクエストはINVALID_PATHで拒否されます。ワークスペースが なく、開いているドキュメントもない場合はスコープが存在しないため、ファイル操作は 拒否されます。これにより、自動化されたクライアントはあなたが開いたものの範囲内で 動作します。
new
新しい無題のタブを作成します。
| パラメーター | タイプ | 必須 | 説明 |
|---|---|---|---|
kind | string | いいえ | "markdown"(デフォルト)または "yaml-workflow" |
windowLabel | string | いいえ | 対象ウィンドウ;デフォルトはフォーカス中 |
{tabId} を返します。
open
ディスクから ファイル を バックグラウンド タブに開きます——ユーザーに見えているタブやワークスペースは変わりません。返された tabId を document / selection の呼び出しにつなげます;switch_tab はユーザーにタブを 見せる べきときだけ使ってください。
| パラメーター | タイプ | 必須 |
|---|---|---|
filePath | string | はい |
windowLabel | string | いいえ |
{tabId, workspaceInstanceId, activationChanged, workspaceSwitched} を返します。
open_workspace
フォルダー をアクティブなワークスペースとして開きます。open(すでに同意済みのツリー内の単一ファイル)とは異なり、これはアシスタントにまったく新しいファイルツリーへのアクセスを与えるため、1 回限りのユーザー承認によってゲートされ、上記のパスのスコープの対象外です。
| パラメーター | タイプ | 必須 |
|---|---|---|
folderPath | string | はい |
ここでは new や open と違い、windowLabel は 受け付けません。フォルダーは常にリクエストが届いたウィンドウで開きます。これは意図的です:承認ダイアログと実際のオープンは同じウィンドウに着地する必要があり、クライアントが指定したラベルでは、あるウィンドウの前でプロンプトを表示しながら別のウィンドウを変更する——1 つを承認したのに別のものが返ってくる——事態を招きかねません。マルチウィンドウのターゲティングには、まだ存在しないリクエストルーティングが必要です。
承認フロー。 最初の呼び出しは {needsApproval: true} を返し、正規化された フォルダーパス(シンボリックリンクは解決済み)を示す同意ダイアログを表示します。アシスタントはユーザーに確認したうえで、同じ呼び出しをリトライ してください;ユーザーが承認すると、リトライがフォルダーを開きます。承認はそれを求めた接続に属します:使えるのは同じ MCP 接続からのリトライだけです。接続している別のアシスタントには別途プロンプトが表示され、再接続したクライアント(新しい接続)は改めて承認を受ける必要があります。また、5 分以内に使われなかった承認は失効します。拒否されたリクエストは、再承認されるまで失敗し続けます。「記憶する」オプションはありません——各オープンは個別に承認されます。
フォルダーへのアクセス。 ダイアログで承認しただけでは、VMark が常に読み取れる場所(ホームフォルダーとマウントされたボリューム)以外のフォルダーは読めません。そのようなフォルダーの場合、承認後の再試行で VMark のフォルダー選択ダイアログがそのフォルダーで開き、APPROVAL_REQUIRED が返されます。ユーザーにそこでフォルダーを選んでもらうと、次の再試行で開きます。別のフォルダーダイアログがすでに開いている場合は何も表示されず、BUSY が返ります。承認は保持されるので、ユーザーがそのダイアログを閉じてから再試行してください。そのウィンドウでワークスペースの切り替えが進行中の間も BUSY が返ります。
save
タブを既存のパスに保存します。
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ(デフォルトはフォーカス中のタブ) |
{filePath, revision, journaled} を返します。
save_as
タブを新しいパスに保存します。
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
filePath | string | はい |
{revision, journaled} を返します。
タブ自身の現在のファイル以外のパスへの保存は、新規書き込みとして扱われます。新しい場所への保存とジーニーの結果を自動承認(設定 → インテグレーション)がオフのとき(デフォルト)、そのようなリクエストは APPROVAL_REQUIRED で拒否され、何がブロックされたかがトーストで通知されます。タブ自身のパスへの保存は常に許可されます。
パスの確認は、そのファイルへの保存キューで保存の順番が来たときにもう一度行われます。その時点で範囲外になったパス(たとえば保存の待機中にワークスペースが閉じられた場合)は INVALID_PATH で拒否され、何も書き込まれません。
save_as は、タブ自身のファイルではないファイルを置き換えることはありません。すでにファイルがある保存先は APPROVAL_REQUIRED で拒否されます。リクエストの確認後、保存の実行中に作成されたファイルも同様です。ファイルは、配置する瞬間にそのパスに何もない場合にだけ書き込まれ、そこにあったファイルは内容を保ちます。ディスクがこの方法で書き込めない場合は、上書きせずに保存を拒否します。
save または save_as は、この保存より後に行われた保存——どのドキュメントやウィンドウからのものでも——がすでにそのファイルに到達している場合(たとえばシンボリックリンクとそのリンク先のファイルを経由した場合)、STALE で拒否されます。そのため、この古いほうの保存は何も書き込んでいません。再度書き込む前にドキュメントを読み取ってください。document.write は同じ場合を saved: false と save_error で報告します。
close
ドキュメントのタブを閉じます。force なしで未保存の作業を破棄することを拒否し、ピン留めされたタブは決して閉じません。
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | はい |
force | boolean | いいえ |
成功時は {closed: true} を返します。それ以外の場合は {closed: false, reason} を返します:
reason | 意味 |
|---|---|
DIRTY | タブに未保存の変更があり、force が指定されていない |
DIVERGENT | ディスク上のファイルが変更され、ユーザーはタブ側のバージョンを残した;force なしで閉じるとそれが失われる |
PINNED | タブがピン留めされている——force を指定しても拒否される;ユーザーがピン留めを解除する必要がある |
エディタがまだ渡していないキーストロークは、チェックの前に未保存として数えられます。ブラウザタブは INVALID_TAB エラーで拒否されます——browser ツールの close アクションで閉じてください。
switch_tab
タブをアクティブにして 可視 にします。ワークスペースレール が有効な場合、ユーザーのアクティブなワークスペースコンテキストを切り替えることがあります——その場合レスポンスは workspaceSwitched: true を報告するので、アシスタントはユーザーに伝えるべきです。
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | はい |
{activated, workspaceSwitched, workspaceInstanceId, activeTabId} を返します。
focus_window
ウィンドウにフォーカスします。
| パラメーター | タイプ | 必須 |
|---|---|---|
windowLabel | string | はい |
document
読み取り、書き込み、変換。サーフェスのバックボーンです。
read
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ(デフォルトはフォーカス中のタブ) |
{content, revision, filePath, kind, dirty} を返します。書き込み前には必ず読み取ります——revision トークンは次の write に同伴される必要があります。
write
ドキュメント全体のコンテンツを置き換えます。
| パラメーター | タイプ | 必須 | 説明 |
|---|---|---|---|
tabId | string | いいえ | 対象タブ(デフォルトはフォーカス中) |
content | string | はい | 新しい全コンテンツ |
expected_revision | string | いいえ | 直近の読み取りからのリビジョントークン |
addresses | string[] | いいえ | この編集が対応する comments.list のコメント ID(最大 64 個) |
save | boolean | いいえ | ディスクにも保存する(デフォルト true);false はタブだけを変更する |
デフォルトでは書き込みは保存されます:レスポンスは saved: true を持つか、saved: false とともに save_skipped("untitled"——タブにまだファイルがないので save_as を使う;"opt_out"——save: false を渡した)または save_error(ディスクへの書き込みが失敗した)を持ちます。対象が Markdown ドキュメントのアクティブな WYSIWYG タブの場合、テキストはライブのエディタに読み込まれ(1 回で取り消せるステップとして)、保存されるのはエディタによるそのシリアライズです——同じ Markdown ですが、正規化されることがあり、送信した文字そのままとは限りません。他のタブは、送信したテキストを改行コードだけ正規化して保存します。
書き込みがタブを変更した後、保存が実行される前にタブが閉じられた場合、レスポンスは saved: false で、タブが閉じられたことを示す save_error が付きます。タブが持っていたパスには何も書き込まれません。
AI クライアントによる保存は——write、workspace.save、workspace.save_as のいずれによるものでも——ドキュメントの履歴に mcp スナップショットとして記録され(履歴サイドバーでは (mcp) と表示されます)、AI が書いたバージョンをあなた自身のものと見分けられます。手動保存と同じく、隣接する自動保存に統合されることも、サイズを理由にスキップされることもありません。
保存の応答には journaled も含まれます(write では保存を行った場合のみ)。"yes":VMark のエージェント編集ジャーナルが保存されたテキストを記録しました。"pending":記録済みで、記録中の書き込みが完了した時点でドキュメントの履歴に位置づけられます。"no":ファイルは保存されましたが、ジャーナルには記録されていません。ジャーナルが原因で保存がエラーになることはありません。
expected_revision が指定されていてその読み取り以降にドキュメントが変更されている場合、レスポンスは現在のリビジョンを含む STALE 構造化エラーエンベロープになります;再読み取りしてリトライしてください。
// success
{ "revision": "rev-newAfterWrite", "applied": true, "durable": true, "saved": true }
// stale
{ "error": "STALE", "message": "Document has changed since the last read", "current_revision": "rev-currentNow" }タブを表示しているエディタで、WYSIWYG でもソースモードでも、ユーザーが入力メソッド(IME)で変換している間、書き込みは BUSY で拒否され、何も変更されません:変換中のテキストは確定するまで入力メソッドのものだからです。ソースエディタは、変換が終わった直後の短い猶予期間も変換中として扱われます。少し待ってからリトライしてください。
すべての書き込みは、何かが変更される前に VMark のエージェント編集ジャーナルに記録されます。成功レスポンスには applied: true と durable が含まれます:durable: false は、内容は書き込まれたもののジャーナル記録をまだ保存できていないことを意味します。VMark はバックグラウンドで再試行し、それが完了するまで、その文書への次の書き込みは JOURNAL_DEGRADED で拒否されます。ジャーナルが記録そのものを拒否した場合、書き込みは適用されたまま記録なしとしてログに残り、次の書き込みはそのまま進みます。書き込みは何も変更せずに次の場合に拒否されます:同じ文書への別の書き込みを記録している間は JOURNAL_BUSY(同じファイルを表示している二つのウィンドウは一つの文書を共有します)、このタブが最後に書き込んだ後に別のウィンドウがその文書に書き込んだ場合は STALE_PARENT(読み直してから再試行してください)、ジャーナルが動作していないか時間内に応答しない場合は JOURNAL_UNAVAILABLE、content に単独の UTF-16 サロゲートが含まれる場合は INVALID_TEXT。書き込みを記録している間にユーザーが文書を編集した、タブを閉じた、入力メソッドで変換を始めた、または選択範囲を動かした(tabId を指定しなかった場合はタブを切り替えた)ときは、書き込みは ABORTED と reason(edited、closed、composing、selection)で拒否され、何も変更されません。読み直してから再試行してください。applied: true を含む INTERNAL エラーは別物です。書き込みが文書を変更した後でエディターが失敗し、その時点の文書のテキストが記録されています(durable は上記と同じ、current_revision は文書のリビジョン)。次に書き込む前に読み直してください。失敗した書き込みの後の applied を含まない INTERNAL エラーは、文書が部分的に変更されている可能性を意味します。この場合も読み直してください。
transform
決定的な書き換えを適用します。現在は CJK 固有の変換(全角 ↔ ASCII 句読点変換、CJK ↔ ラテン間のスペース調整)をサポートします。
| パラメーター | タイプ | 必須 | 説明 |
|---|---|---|---|
tabId | string | いいえ | 対象タブ |
kind | string | はい | "cjk-format"、"cjk-spacing"、または "cjk-punctuation" |
expected_revision | string | いいえ | 並行制御トークン |
addresses | string[] | いいえ | この編集が対応する comments.list のコメント ID(最大 64 個) |
cjk-format はユーザーの CJK フォーマット設定をエンドツーエンドで適用します。cjk-spacing は CJK 文字と隣接するラテン/数字の間に単一スペースを挿入します。cjk-punctuation は CJK 文字に隣接する ASCII 句読点を全角形式に変換します。
{revision, applied, durable} を返します。write と同じく、タブを表示しているエディタ(WYSIWYG でもソースモードでも)でユーザーが入力メソッドで変換している間は、何も変更せずに BUSY で拒否されます。 write と同じく、何かが変更される前に VMark のエージェント編集ジャーナルに記録されます。applied、durable とジャーナルによる拒否(JOURNAL_BUSY、STALE_PARENT、JOURNAL_DEGRADED、JOURNAL_UNAVAILABLE、INVALID_TEXT、ABORTED)の意味も同じです。何も変更しない呼び出しは記録されません。
workflow
GitHub Actions ワークフロー YAML 用の actionlint 検証と CST セーフな外科的編集。kind が "yaml-workflow" のタブでのみ利用可能です。
document.read / document.write はすべてのタブで動作——ワークフロー YAML を含む
workflow ツールは読み書きのバックボーンの代替では ありません。ワークフロータブでは以下が可能です:
document.readで生の YAML テキスト(すべてのコメント付き)を取得document.writeで全体を置き換え(送信した文字列はそのまま保存される——コメントを含めれば保持される)- 部分的な編集でコメント、アンカー、キー順が確実に保持されることを サーバー自身に保証 させたい場合は
workflow.apply_patch
1 つのフィールドを変更しつつ他はそのままにしたい場合は apply_patch を使ってください(サーバーは変更しないコメントを落とすことができません)。全体を書き直したり、新しいワークフローをゼロから生成したりする場合は document.write を使ってください。
apply_patch
IRPatch オブジェクトの配列を適用します。パッチは VMark の CST 認識ミューテーターを通じてディスパッチされ、コメント、アンカー、キー順を保持します。YAML ファイルへの生の document.write ではこれらが失われます。
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
patches | IRPatch[] | はい |
expected_revision | string | いいえ |
addresses | string[] | いいえ |
IRPatch は判別共用体(kind フィールド)です。サポートされる種類:
kind | 効果 |
|---|---|
workflow.set | トップレベルフィールドを設定({path, value})——name、env.X など |
job.set | ジョブ上のフィールドを設定({jobId, path, value}) |
step.set | ステップ上のフィールドを設定({jobId, stepIndex, path, value}) |
with.set | ステップの with: ブロック内のキーを設定({jobId, stepIndex, key, value}) |
with.remove | ステップの with: ブロックからキーを削除 |
needs.add / needs.remove | needs: からジョブ ID を追加または削除 |
trigger.setFilters | トリガーのフィルター配列を置き換え——branches、paths、types など({event, filter, value: string[]}) |
成功時は {revision, applied, durable}、失敗時は構造化された STALE / INVALID_PATCH / NOT_WORKFLOW エラーエンベロープを返します。 write と同じく、何かが変更される前に VMark のエージェント編集ジャーナルに記録されます。applied、durable とジャーナルによる拒否(JOURNAL_BUSY、STALE_PARENT、JOURNAL_DEGRADED、JOURNAL_UNAVAILABLE、INVALID_TEXT、ABORTED)の意味も同じです。何も変更しない呼び出しは記録されません。
validate
ワークフロー YAML に対して actionlint を実行します。
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
{ok, diagnostics, binaryAvailable} を返します。各診断は {line, col, message, severity} を持ちます。binaryAvailable: false は actionlint がローカルにインストールされていないことを意味します;Homebrew または上流のリリースからインストールしてください。
selection
ユーザーの現在のエディタ選択範囲を読み取るか置き換えます。ユーザーが変更したい領域をハイライトしている場合は、document.read/document.write の代わりにこれを使ってください——selection.get は選択されたスライスだけを返し、selection.set はその範囲だけを書き換えるので、トークンコストはドキュメントではなく編集量に比例します。
選択範囲はビュー状態——フォーカス中のタブのみ
選択範囲は、現在レンダリングされているエディタ内にのみ存在します。tabId を指定する場合はフォーカス中のタブと一致していなければなりません;一致しない場合は INVALID_TAB を返します。フォーカス中のタブに生きているエディタがない場合(読み取り専用ビューアーなど)、レスポンスは NO_EDITOR になります。
get
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
返り値:
| フィールド | タイプ | 備考 |
|---|---|---|
text | string | 選択スライスの Markdown シリアライズ(WYSIWYG モード)、または選択された生テキスト(ソースモード)。折りたたまれている場合は空文字列。 |
isEmpty | boolean | 選択範囲が折りたたまれている(カーソルのみ)場合は true。 |
range | {from, to} | WYSIWYG モードでは ProseMirror の位置;ソースモードでは文字オフセット。 |
mode | "wysiwyg" | "source" | range の位置空間を判別します。 |
kind | "markdown" | "yaml-workflow" | ドキュメント種別の判別子。 |
tabId | string | 確認用にエコーバックされます。 |
revision | string | 楽観的並行制御のために set に渡し返します。 |
set
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
content | string | はい |
expected_revision | string | いいえ(推奨) |
addresses | string[] | いいえ |
エディタが現在の選択範囲として報告するものを何であれ置き換えます。WYSIWYG モードでは、プレーンなインラインテキストはリテラルなテキストノードとして挿入されるため、先頭/末尾の空白が正確に往復します;markdown マーカーを含むコンテンツ(**bold**、*italic*、`code`、フェンス付きコード、ブロック引用、リストなど)は markdown として解析され、対応するノードとして挿入されます。ソースモードでは、content は常に生テキストとしてはめ込まれます——ソースサーフェスはすでに markdown バイト列だからです。空の content は選択範囲を削除します。選択範囲が折りたたまれている場合、content はカーソル位置に挿入されます。
成功時は {revision, replaced_chars, applied, durable} を返します。replaced_chars は呼び出し前に選択されていたテキストの長さです——AI が意図したものを編集したかを確認するのに役立ちます。 write と同じく、何かが変更される前に VMark のエージェント編集ジャーナルに記録されます。applied、durable とジャーナルによる拒否(JOURNAL_BUSY、STALE_PARENT、JOURNAL_DEGRADED、JOURNAL_UNAVAILABLE、INVALID_TEXT、ABORTED)の意味も同じです。何も変更しない呼び出しは記録されません。
STALE は document.write とまったく同じように {error: "STALE", message, current_revision} を返します。ドキュメントレベルのリビジョンが get と set の間のキーストロークを捕捉します。純粋なカーソル移動(キーストロークなし)はサーバーによる調停の対象外です——ユーザーが get と set の間でカーソルを移動した場合、編集は新しい位置に着地します。
フォーカスされているエディタでユーザーが入力メソッドで変換している間、set は WYSIWYG モードでもソースモードでも何も変更せずに BUSY を返します;少し待ってからリトライしてください。get がこの理由で拒否されることはありません。
comments
ドキュメントに対するユーザーのレビューコメントを読み、返信します。コメントの解決・再オープン・削除はユーザーが決めることです。このツールにはそれらのアクションはなく、それを求める呼び出しは VMark に届く前に拒否されます。
list
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
cursor | string | いいえ |
{doc, generation, threads, nextCursor?} を返します。スレッドは古い順です。各スレッドは comment id、state(open、addressed、resolved、reopened のいずれか)、commentGen、アンカーされた引用テキスト、返信を持ちます。
長いリストはページに分けて返され、各ページは欠けずに届く大きさに収まります。nextCursor がある間は、cursor にその値を設定して list を再度呼び出してください。ページをまたいで分割されたスレッドは repliesFrom と repliesTotal を持ち、後続の部分は comment、state、commentGen、continued: true と続きの返信だけを持ちます。JSON テキストとしてどのページにも収まらない本文(大量のエスケープを含むテキストに限られます)は、body の代わりに bodyBase64 として、UTF-8 バイト列を base64 にしたもので届きます。カーソルが指すスレッドが削除されている場合や、別のドキュメント向けに発行されたカーソルの場合は STALE_COMMENT で拒否されます。カーソルを指定せずに、もう一度 list を呼び出してください。
reply
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
commentId | string | はい |
body | string | はい |
expectedCommentGen | string | はい |
スレッドに返信を追加します。返信 ID は VMark 自身が発行するため、再試行された呼び出しには最初の結果が返り、2 つ目の返信が追加されることはありません。
mark_addressed
| パラメーター | タイプ | 必須 |
|---|---|---|
tabId | string | いいえ |
commentId | string | はい |
expectedCommentGen | string | はい |
スレッドを対応済みにします。解決するかどうかはユーザーが決めます。
comments.reply と comments.mark_addressed はどちらも、list が返したスレッドの commentGen を指定します。次の場合は何も変更せずに拒否されます:その後スレッドが変わったか削除された場合は STALE_COMMENT(もう一度 list してください)、コメント ID が不正またはこのドキュメントのコメントを指していない場合は INVALID_COMMENT、スレッドが解決済みの場合は COMMENT_NOT_ALLOWED、返信が多すぎる、本文が長すぎる、またはスレッドがこれ以上変更できない場合は COMMENT_LIMIT、そしてジャーナルの拒否 JOURNAL_BUSY、JOURNAL_DEGRADED、JOURNAL_UNAVAILABLE、INVALID_TEXT。
編集がコメントへの対応であることを示すには、それらの ID を addresses として document.write、document.transform、workflow.apply_patch、selection.set に渡します。このリンクはリビジョンとともに記録され、ドキュメントの履歴に表示されます(後で削除されたコメントは削除済みコメントとして表示されます)。スレッドの状態は変わりません。64 個を超える ID、重複した ID、未知・削除済み・解決済み・別ドキュメントの ID は INVALID_ADDRESSES で拒否され、何も変更されません。
browser
埋め込みブラウザサーフェスの 変更を伴う 半分——ページ、タブ、または保存されたログインを変更するすべて。まず browser_read でページを読み取ってください:ここでのすべてのターゲティングモードは、読み取りが返したものを参照します。
ブラウザツールは 設定 → 詳細設定 → macOS → 埋め込みブラウザ に従います。これは macOS では デフォルトでオン なので、オフにしない限り、接続された AI クライアントはこれらのツールを利用できます。オフの間、すべてのアクションは BROWSER_DISABLED で失敗します。MCP に返される URL は、アプリのブラウザセッション状態で使われるのと同じ境界を通じてマスクされます。
readOnlyHint: false, destructiveHint: true とアノテーションされています——ここでのすべてのアクションが何かを変更するため、単に保守的なのではなく正確です。
エラーは型付きです。 拒否は TOKEN: message(STALE_COMMAND、NOT_GRANTED、EVAL_TIMEOUT、TAB_LIMIT、…)の形で届き、同じトークン——およびアプリが付加した構造化データ(ナビゲーションチケット、act の reason、リトライ用の動詞)——が structuredContent に入ります。文章ではなくトークンで照合してください。
EVAL_TIMEOUT はクリーンな失敗ではなく 不確定 です:ドライバーが待つのをやめた後も、送信したスクリプトは最後まで実行された可能性があります。そのため data.detail.indeterminate: true を持ち、何も起きなかったかのようにリトライしてはなりません——再び操作する前に、ページを読み取って(browser_read)状態を確認してください。
act
引数:tabId?、operation: "click" | "type" | "scroll" | "key"、および操作ごとのターゲット:
- click / type——ターゲット(
ref(事前の読み取りから)またはrole+name)、およびタイプ入力用のtext?。refは正確で順序に依存しませんが、すでに許可済み の操作でのみ尊重されます;アクションが承認を必要とする可能性がある場合は、プロンプトがユーザーに読める要素を示すようrole+nameを使ってください。 - scroll——
ref(ビューにスクロールインする)またはdy(垂直方向のピクセル差分)。 - key——
key(例:"Enter"、"Escape"、"Tab")、ターゲット指定用のオプションのref、およびオプションのmodifiers: {ctrl, shift, alt, meta}。
scroll と key は act クラス(承認ゲート付き)で、合成 DOM イベントをディスパッチするため、event.isTrusted でゲートするサイトはこれらを無視することがあります。変更を伴う操作にはオリジンスコープの承認が必要です;AI が選んだアップロードは決して許可されません。
クリックは成功を報告する前にその効果を検証し、推測するのではなく拒否します。 ターゲットはビューにスクロールインされ、可視にレンダリングされていなければならず(計算済みスタイルと、折りたたまれた祖先や透明な祖先がチェックされるため、閉じたアコーディオンステップ内の重複ボタンはクリックされずスキップされます)、クリック位置はヒットテストされます——オーバーレイに覆われたターゲットは、突き抜けてクリックするのではなく、覆っている要素の名前(covered by div.cmp-overlay、ページデータ)とともに拒否されます。複数の可視要素が同じ role と name を持つ場合、act は ambiguous として拒否され、candidates にそれらの ref が列挙されます——ドキュメント順で 1 つを選ぶことは決してありません。その他の拒否理由:hidden、offscreen(ビューポートにスクロールインできない)、disabled(pointer-events: none や inert なサブツリーを含む)、upload(ファイル入力は決して自動化されない)、rejected-value(フィールドがテキストをサニタイズした)。開いた shadow root は走査されます。レスポンスには matchedTotal / matchedVisible のカウント、成功時 と 失敗時のタブの現在の url と generation、そして act の間にページがウィンドウを開こうとした場合は popup: {url} が含まれます(VMark はポップアップをブロックします;URL はページが開こうとしたものです)。type はテキストフィールド、<select> コントロール(オプションのラベルまたは値を渡す;存在しないオプションは no-such-option として拒否される)、および contenteditable 領域を扱います。key は合成イベントに欠けているデフォルト動作をエミュレートし——フォーム内の Enter はフォームを送信し、Tab はフォーカスを移動します——defaultAction を報告します。
承認が何に紐づくか。 click の承認は要素(role + name)に紐づきます。type、key、scroll の承認は、要求した正確なテキスト、キー(修飾キーを含む)、または差分にも紐づきます——プロンプトにそれが表示されます——そのため、内容を変えてリトライすると再び確認されます。
workflow_run / workflow_cancel
workflow_run は、source テキストとして渡したワークフローを AI 所有のタブで実行します。引数:tabId?、source(ワークフローテキスト——小さな行指向の文法;あなたが書くか、AI が書くか、または workflow_record があなた自身の操作からキャプチャします)、inputs?({name} 参照に代入される {name: value} のマップ;宣言されたすべての入力を指定する必要があり、宣言されていないものは拒否されます)、allowRepeat?、resumeRunId?(下記参照)。これは {runId, steps, firstStep} を 即座に 返します——複数ステップの実行は 1 回のリクエストより長く続くことがあるため、実行は 非同期 に行われます。進捗は browser_read の workflow_status をポーリングしてください;実行があなたを待っている間は pendingApproval が報告されます。
決定的なステップ——その文法での click / type / navigate、および extract——は VMark 内で実行され、手動で発行した act とまったく同じように 個別に承認ゲートされます:実行は各ステップをそれぞれ個別に認可するので、ワークフローは承認プロンプトを回避する手段にはなりません。goal、confirm、api、およびあらゆる自由記述のステップは、AI が手動で処理できるよう実行を 一時停止 します。一時停止後の再開: 一時停止したステップを実行し(または AI に手伝ってもらい)、resumeRunId に一時停止した実行を指定して新しい実行を開始します——完了済みのステップを引き継ぎ、一時停止したステップを完了済みとして扱うので、何も二重に送信されません。同じ source と同じ inputs での再実行も、このセッションですでに成功した書き込みステップをスキップします(完了済み書き込みの台帳;スキップされたステップは skipped として報告されます)。ただし allowRepeat が設定されている場合は別です。inputs が異なれば別のジョブであり、すべてが実行されます。
workflow_cancel {tabId?, runId} は実行を停止します。これは 決して承認ゲートされません——停止は常に許可されます——そして実行の保留中のプロンプトを取り下げ、あなたの承認を待っているステップを中止し、タブをあなたに返します。終了済みの実行は already-terminal を報告してそのまま残され、未知の runId は RUN_NOT_FOUND です。あなたがブラウザを引き継いだ瞬間(ページやそのクロムへの何らかの操作が制御を取り戻す)にも実行は停止します——プロンプトを待っている間も含みます。
実行には上限があり(≤ 25 ステップ、source ≤ 64 KiB、実行 時間 120 秒——あなたを待っている時間は数えません)、タブごとに一度に 1 つだけです。
workflow_record
AI 所有のタブでの あなた自身の操作 を、再生可能なワークフローとして記録します。引数:tabId?、recordOp("start" または "stop")、site?(記録されたワークフローのフロントマター内のサイト ID;デフォルトは recording)。
start は record 権限によって 同意ゲート されます。この権限は——execute_js や session と同じく——恒久的に付与されることは決してありません:記録のたびに毎回あらためて確認されるため、AI があなたを黙って記録することはできません。あなたが許可するまで、start は needsApproval を返します。許可すると、VMark は休止中のページワールドのキャプチャシムを起動し、あなたが行う クリックとフィールドの編集 の記録を開始します。stop は {source, inputs, eventCount} を返します——source は、保存したり、そのまま workflow_run に渡したりできるワークフローテキストです。
記録は 設計上、値を含みません。これはページを信頼するフィルターではありません:あなたが入力した内容が記録されることは一切ありません。すべてのテキストフィールドは名前付きの {input} 変数になり(値は再生時に与えられ、記録されることはありません)、パスワードまたはワンタイムコードのフィールド は confirm: ステップになります——再生時にあなたが手作業で完了する、人間によるゲートです——そのため秘密情報はパラメータ化すらされません。そしてすべての URL はオリジンとパスだけに切り詰められるため、クエリ文字列内のトークンが残ることはありません。記録されるのは、あなたが触れた ロケーター(ARIA ロールとアクセシブルネーム)であり、そのデータではありません。記録はページ遷移をまたいであなたに追従し、上限があります(ページごとに 200 イベント、セッションごとに 1,000)。
open
引数:url、オプションの timeoutMs(1〜9,000 ms)、およびオプションの profile([A-Za-z0-9._-]、macOS 14 以降、sandbox ポスチャ):ログインを名前で再利用できる 名前付きの永続コンテキスト です——それを開くには使用ごとに新たな承認が必要で、AI が資格情報を見ることは決してありません。現在の Sandbox または Shared のポスチャを使って AI 所有のタブを作成して前面に表示し、ロード完了後にその tabId、navigationId、URL、タイトル、generation を返します。開いておける AI 所有のタブは最大 8 つ です(TAB_LIMIT);AI は使い終わったタブを閉じます。Shared のポスチャで宛先の承認が必要な open はタブを保持し、その tabId に対して navigate でリトライするよう AI に伝えます(data.retry)——新たに open すると、承認の対象外のタブが作成されてしまうためです。
navigate
引数:tabId?、url、およびオプションの timeoutMs。AI 所有のタブをナビゲートし(タブを前面に表示します)、ナビゲーションチケットの結果を返します。TIMEOUT になってもチケットは返されるので、後から wait で最終結果を取得できます。
close
引数:tabId。AI が開いた AI 所有のタブを閉じます。決して承認ゲートされません——停止は常に許可されます。人間のタブは拒否されます(TAB_NOT_AI_OWNED)。ネイティブビューがなくなったことが確認されると、結果は {tabId, closed: true, destroyed: true} になります。ドライバーがリトライ後も破棄を確認できなかった場合は data.destroyed: false とともに TAB_TEARDOWN_FAILED として報告されます——タブの記録はすでに消えているので、close をリトライしないでください;ネイティブビューがまだ動作している可能性があることをユーザーに伝えてください。
ゲート検出。 ロードされた open / navigate / wait の結果は、着地したページが ログインウォール、同意インタースティシャル、人間確認チャレンジ、または レート制限 として読み取れる場合に gate: {kind, hint} を持つことがあります——これにより AI は、結果を読んだその瞬間に、要求したコンテンツを見ていないことに気づきます。検出は精度優先で(レンダリングされたチャレンジウィジェット、または簡潔なページ上の少なくとも 2 つの独立したシグナル——$429 の価格、「Protected by Cloudflare」のフッター、CAPTCHA について書かれた 記事は決して分類されません)、純粋に助言的です:AI に伝えられる内容を変えるだけで、認可されているものは変えません。すべてのヒントは、ゲートを回避するのではなく、あなたを巻き込む方向を指します。
style
引数:tabId?、ターゲット(ref または selector)、および set: {prop: value}、addClasses、removeClasses、injectCss のいずれか 1 つ。ブロックしているオーバーレイの解除、ターゲットのハイライトなど。act クラス(承認ゲート付き、op style)。隔離されたコンテンツワールド。
execute_js
引数:tabId?、script——JSON シリアライズ可能な値を return する(または await する)async 関数の本体。構造化された動詞では表現できないことのための逃げ道です。隔離されたコンテンツワールド で実行されます——DOM は共有しますが(querySelector、element.style は動作します)、ページ自身の JS ヒープ/グローバルは 見られません。値は result として返されます(undefined は null になります);例外の送出や、JSON にエンコードできない値は、結果ではなく エラーを示す失敗 になります。承認は 呼び出しごとのみ(決して常設の付与ではなく、Rust ドライバーで強制されます)で、承認はスクリプトを表示し、返り値は 信頼できない ものとしてフラグ付けされ、後続の act に自動的に渡されることはありません。まず query/style を優先してください。
session_save / session_load
引数:tabId?、handle([A-Za-z0-9._-]、1〜128 文字)。session_save はタブのセッションを handle で名付けた OS キーチェーン エントリにスナップショットし、値を含まないサマリー(カウント)を返します;session_load はそれを復元し、{loaded: true, handle}——確認と AI が指定したハンドルのみで、値は一切含みません——を返します。session_load は、セッションが保存された 同じオリジン のページにのみ適用されます。これは 参照による 資格情報です(ADR-A7):AI は保存されたセッションを名前で指定し、クッキー/トークンの値を受け取ることは決してなく、それらがログに記録されることもありません。どちらも session 権限で——決して常設の付与ではなく(呼び出しごとに承認)、あるハンドルの承認を別のハンドルに流用することはできません。保存されたセッションは localStorage とクッキー の両方を対象とし、どちらも保存時にページがコミットされていたオリジンにスコープされます。
console_clear
引数:tabId?。browser_read の console とまったく同じように {entries: [{level, text}], url} を返し、バッファをドレイン するので、次の読み取りには新しい出力だけが見えます。他のコンソール読み取りと一緒ではなくここに置かれているのは、ドレインがページ内で element.textContent = "[]" を評価する——DOM 書き込み——だからです。
Shared のポスチャは、一致する navigate の付与が存在しない限り、新しいオリジンごとに宛先の承認を求めます。人間が作成したタブは、AI の読み取り/操作の前に一時的なアタッチメント承認を必要とします。Sandbox タブは別の非永続的な AI クッキーストアを使用します。
browser_read
読み取り専用 の半分:タブを変更せずに観察します。readOnlyHint: true とアノテーションされているため、MCP クライアントはこれを自動承認できます——それがこの分割の狙いです。これらのアクションは以前 browser にあり、そこでは 1 つのツールレベルのアノテーションが execute_js も記述しなければならなかったため、ARIA スナップショットを取るだけで人間の承認が必要でした。
openWorldHint は true のままです:読み取り専用が記述するのは、ツールが 何を変更するか であって、そのバイト列が信頼できるかどうかではありません。返されるものはすべてページに制御され、信頼できません——結果をそのまま browser の act ターゲットとして渡さないでください。
read
フォーカス中のブラウザタブ、または tabId で指定したタブについて {url, snapshot, truncated?, unreachable?} を返します。snapshot は {role, name, ref} ノードの ARIA 指向のリストです——見出しには level、さらに checked、disabled、そして AI が決して操作できないファイル入力には upload: true が付きます——各 ref(例:"e5")はその要素の安定したハンドルで、現在のビューが存続する間有効です。走査は開いた shadow root に入ります;unreachable は入れなかった閉じた shadow root とフレームの数で、truncated: true はノード数の上限(2,000)または名前の長さの上限(200 文字)に達したことを意味します。
screenshot
引数:tabId?。タブの現在のレンダリングの 画像コンテンツブロック(base64 JPEG、品質制限あり)と、ページ名を示すテキスト行を返します——ARIA スナップショットでは記述できない、レイアウトとレンダリング状態への視覚的なチャネルです。ネイティブに(takeSnapshot)キャプチャされ、ページの DOM や JavaScript を一切読み取りません。read クラス:read とまったく同じように認可されます(AI 所有のタブで許可;人間のタブにはアタッチメントが必要で、キャプチャ時に消費されます)。表示中のページではないタブは空白でレンダリングされることがあります——open と navigate はタブを前面に表示します。
query
引数:tabId?、selector(CSS)、およびオプションの fields: {attributes, box, styles:[...]}。{count, elements: [{ref, tag, text, …}], truncated?} を返します——ARIA スナップショットでは名付けられない構造化 DOM データ(テーブル、計算値)——上限は 50 要素、各要素のテキストは 500 文字までです(セレクターがそれより多く一致した場合は truncated: true)。read クラス。 隔離されたコンテンツワールドで実行されます。
extract
引数:tabId?。{title, byline, url, markdown, textLength, truncated} を返します——ページを リーダーモードの Markdown として、AI が操作するのではなく 読みたい ページのために。1 回の上限付きキャプチャがページの HTML をエクスポートします;抽出自体はページ内ではなく VMark 内で実行されます:そのオリジンに登録された サイトプラグイン が最初の権利を持ち(組み込みの Wikipedia プラグインは wiki のクロム——インフォボックス、ナビゲーションボックス、ハットノート、編集リンク——を名前で取り除きます)、汎用の密度ヒューリスティックリーダーが他のすべてのサイトのフォールバックです。truncated: true は、ページがキャプチャ上限を超え、末尾が読まれなかったことを意味します。read クラス。 返されるものはすべてページ由来で信頼できません。
workflow_status
引数:tabId?、runId(workflow_run から)。{status, completedSteps, skippedSteps, stepCount, firstStep, pausedAt?, pendingApproval?, reasonCode?, reason?, resumedFrom?, stepResults} を返します。status は running / paused / completed / failed / cancelled / superseded のいずれかで、stepResults はステップごとに 1 つのエントリ({index, status, attempts, reason?, data?})を持ち、pendingApproval は実行があなたの判断を待っている間存在します。paused の状態は、あなたを必要とするステップを pausedAt で示します。read クラス——自由にポーリングしてください。
console
引数:tabId?。{entries: [{level, text}], url} を返します——ページがキャプチャした console.* の出力に加え、キャッチされなかったエラーと未処理の Promise リジェクション(Uncaught / Unhandled rejection: を接頭辞とする level: "error" エントリとして記録されます——console.* のパッチだけでは決して見えないシグナル)。AI 所有のタブのみ(Sandbox と Shared のポスチャのどちらでも;人間のタブにはキャプチャシムがありません)、メインフレームのみ。キャプチャは、ページワールドのシムが隠し DOM バッファに書き込み、ドライバーが隔離ワールドからそれを読み取ることで機能します——したがって VMark へ戻る メッセージングチャネルは開かれません(ブリッジなしの保証が保たれます)。出力はページに制御され、信頼できません——read のように扱い、決して act のターゲットにしないでください。
バッファは上限付きのリングなので、連続した読み取りは重複します。読みながらドレインするには、browser の console_clear を使ってください——ドレインはページのバッファ要素に [] を書き込みますが、これは DOM 書き込みであり、したがって readOnlyHint: true の下には置けません。
wait
引数:tabId?、オプションの navigationId(省略するとタブの最新のチケット)、およびオプションの timeoutMs(1〜9,000 ms)。ナビゲーションを開始することも、フォーカスやアクティブなタブを変えることも、ビューを作成することも決してありません——観察するだけであり、それが読み取り専用のツールに置ける理由です。AI 所有のタブのみ。バッファされたロード/失敗の結果、NAVIGATION_SUPERSEDED、またはチケットが制限時間内に完了しない場合は TIMEOUT を返します。
wait_for
引数:tabId?、ref(読み取りから)、role(+ オプションの name)、text(可視テキストの部分文字列)、urlContains(タブの URL が含まなければならない部分文字列——クリックによるナビゲーションが着地したことを、ページのラウンドトリップなしにタブの状態から確認します)のうち ちょうど 1 つ、およびオプションの timeoutMs(1〜9,000 ms)。条件が成立するかタイムアウトが経過するまでポーリングし、{matched: true|false}(ref/role 条件の場合は一致した要素の ref も)を返します——これにより「見つかった」と「タイムアウトした」を区別できます。read クラス。フローを決定的にするために使ってください:操作し、wait_for で結果を待ち、それから読み取ります。
見えるものから 2 つのルールが導かれます。urlContains は マスクされた URL と照合されます——リダイレクトがそこに仕込んだトークンを探れないよう、クエリ文字列とフラグメントは取り除かれます——そのため ? や # を含む検索文字列は最初から拒否されます。また、1 回だけ許可 でアタッチされた人間のタブでは拒否されます(ATTACHMENT_ONCE_INSUFFICIENT):ポーリングは多数の読み取りであり、1 回の読み取りのアタッチメントではカバーできないためです——次のナビゲーションまで許可 を求めてください。
coherence
ワークスペース整合性レイヤーの 読み取り専用 ビュー——どの派生ドキュメントが、その生成元となった上流に対して古くなっているかを示します。どのアクションもドキュメントやエディタ状態を変更しません。status は読み取り専用です;edges は先に照合を行い、由来レコードをワークスペースの台帳に追記することがありますが、ドキュメントの内容を変更することは決してありません。すべて Rust バックエンドがワークスペースごとのカーネルから完全に応答するため、エディタウィンドウが前面になくても動作します。
さらに 2 つの読み取り専用アクションがセマンティックレイヤーを公開します:
claims——現在のカノン設定:{claim, entryId, statement, maturity, invalidAt, visible}。セマンティックチェックの制約になるのはestablishedの設定だけです。visibleはデフォルトコンテキストを反映します。contexts——コンテキストの集合(暗黙のdefaultは常に存在します):{id, name, parent, enforcement, visibleClaims, errors}。
readOnlyHint: true とアノテーションされています。唯一の変更を伴うアクション resolve は独自のツールに置かれており——coherence_resolve を参照——それがこのツールを自動承認可能にしています。設定とコンテキストの変更はまったく公開されません:カノンは人間の管理下にとどまります。
すべてのアクションで workspace_root(照会するワークスペースの絶対パス)が必要です。session.get_state(開いているタブの filePath)または workspace ツールから取得できます。パスが欠落している、絶対パスでない、またはディレクトリでない場合は、平文の文字列エラーで拒否されます。
status
1 つのワークスペースのカーネル状態カウンター。
| パラメーター | タイプ | 必須 | 説明 |
|---|---|---|---|
workspace_root | string | はい | 照会するワークスペースの絶対パス |
返り値:
{
"initialized": true,
"objects": 12,
"open_items": 2,
"quarantined": 0,
"writer": "0198c0de-0000-7000-8000-000000000001"
}| フィールド | 意味 |
|---|---|
initialized | ワークスペースにまだ整合性台帳がない(.vmark/ ディレクトリがない)場合は false。その場合、objects 以外のカウンターはすべて 0 です。 |
objects | 追跡中のオブジェクト(整合性 ID を持つファイル)。 |
open_items | 現存する非フレッシュなエッジ——現在の内訳の件数。 |
quarantined | 直近の読み取りで隔離された不正な台帳行。 |
writer | このインストールのライター ID(UUID)。 |
edges
内訳そのもの:上流が動いたすべての現存依存エッジ。先にスキャンと照合を実行するため、結果は呼び出し時点のディスク上のファイルを反映します。
| パラメーター | タイプ | 必須 | 説明 |
|---|---|---|---|
workspace_root | string | はい | 照会するワークスペースの絶対パス |
返り値は配列——すべて整合している場合は空です:
[
{
"txf": "0198c0de-0000-7000-8000-00000000000a",
"input": 0,
"upstream": "0198c0de-0000-7000-8000-00000000000b",
"upstream_path": "characters/elena.md",
"pinned": "rev-a1b2c3",
"downstream": "0198c0de-0000-7000-8000-00000000000c",
"downstream_path": "scenes/chapter-3.md",
"downstream_rev": "rev-d4e5f6",
"state": "version-stale"
}
]| フィールド | 意味 |
|---|---|
txf / input | このエッジを識別する変換エントリと入力スロット(アプリ内の解決アクションに渡します)。 |
upstream / upstream_path | 下流が依存するオブジェクトと、その最後に確認されたパス。 |
pinned | 下流の生成元となった上流のリビジョン。 |
downstream / downstream_path / downstream_rev | 派生オブジェクト、そのパス、および現在のリビジョン。 |
state | "version-stale"、"stale-valid"、"stale-contradicted"、"stale-unknown"、"waived"、"diverged"、"diverged-multi-head"、または "unpinnable"。 |
エッジの解決(新しい版の受け入れ/免除)は、通常は VMark の「整合性の内訳」パネルで人間が行う操作です。AI がそれを行えるのは coherence_resolve を通じてのみで、しかもワークスペースの所有者がそれを明示的に委任した場合に限られます。
coherence_resolve
整合性レイヤー上の 唯一の変更を伴うアクション で、coherence を自動承認可能に保つために独自のツールになっています——そして取り消し不可能なものが、5 つの列挙値の 1 つとして埋もれるのではなく、ツールリスト内で目立つようにするためでもあります。readOnlyHint: false, destructiveHint: true とアノテーションされています。
resolve
引数:{workspace_root, txf, input, resolution: "accept-newer" | "waive", reason? (required for waive)}。txf と input は coherence → edges の行から取得します。
明示的に委任されたエージェントとして、活きている古くなったエッジを解決します。認可は fail-closed です:ワークスペースの所有者が あなたの認証済みブリッジ ID に対して、その解決の種類をカバーする有効で失効していない委任を(アプリ内で、「整合性の内訳」パネルから)付与している必要があり、かつエッジがまだ活きていなければなりません。委任による解決はすべて、その付与に紐づけて監査ログに記録され、そのエントリは取り消せません。coherence_resolve では有効期限を設定できないため、AI による免除がひとりでに失効することはありません。
拒否は、付与が欠落しているか失効していることを意味します——リトライするのではなく、ユーザーに付与を求めてください。これを coherence から分離してもセキュリティ特性は何も変わりません:認可は常に認証済みのブリッジプリンシパルをキーにしており、クライアントが主張する何かをキーにしたことは一度もありません。
エラー
2 種類のエラー形状が現れます:
ドメインエラー——success: false を設定し、JSON エンコードされたエンベロープを error で返します:
{ "error": "STALE", "message": "...", "current_revision": "rev-..." }引数形状エラー——必須引数の不足/不正(例:content フィールドなしの document.write)の場合、error は問題を説明する平文の文字列です。構造化エンベロープはドメインレベルの条件のために予約されています。
| コード | 表面化形式 | 意味 |
|---|---|---|
STALE | エンベロープ | expected_revision が一致しなかった;再読み取りしてリトライ。または save / save_as:この保存より後に行われた保存がすでにそのファイルに到達しているため、この保存は何も書き込まなかった;書き込む前に読み取ること |
INVALID_PATCH | エンベロープ | workflow.apply_patch が不正な patches 配列を受信 |
INVALID_TAB | エンベロープ | tabId を解決できなかった |
INVALID_PATH | エンベロープ | filePath を読み取れなかった、または開いているワークスペース/ドキュメントのスコープ外 |
APPROVAL_REQUIRED | エンベロープ | 新しい場所への保存とジーニーの結果を自動承認 がオフの状態で、新しい場所への save_as。タブ自身のもの以外のファイルがすでにあるパスへの save_as。または open_workspace がユーザーの承認、もしくは VMark のフォルダー選択ダイアログでのフォルダー選択を待っている |
BUSY | エンベロープ | open_workspace を続行できなかった:別のフォルダーダイアログが開いているか、そのウィンドウでワークスペースの切り替えが進行中。承認は保持される——再試行する。または、ユーザーが入力メソッドで変換している間に document.write、document.transform、selection.set が届いた。何も変更されていない——少し待って再試行する |
JOURNAL_BUSY | エンベロープ | 同じ文書への別の書き込みを記録している間に document.write / document.transform / selection.set / workflow.apply_patch が届いた。何も変更されていない——少し待って再試行する |
WRITE_BUSY | 文字列 | 書き込み系の呼び出し(document.write / document.transform、selection.set、workflow.apply_patch、comments.reply / mark_addressed、coherence_resolve など)が別の書き込みの後ろで 3 秒待っても順番が来なかった。適用されていない——再試行する |
TIMEOUT | 文字列 | coherence または coherence_resolve の呼び出しが 20 秒以内に終わりませんでした。書き込み(edges、resolve)の場合はまだ実行中で、結果は不明です。再試行する前に現在の状態を読み取ってください |
STALE_PARENT | エンベロープ | document.write / document.transform / selection.set / workflow.apply_patch:このタブが最後に書き込んだ後に別のウィンドウがその文書に書き込んだ。何も変更されていない——読み直して再試行する |
JOURNAL_DEGRADED | エンベロープ | document.write / document.transform / selection.set / workflow.apply_patch:この文書の以前のジャーナル記録がまだ保存待ち。何も変更されていない——数秒後に再試行する |
JOURNAL_UNAVAILABLE | エンベロープ | document.write / document.transform / selection.set / workflow.apply_patch:エージェント編集ジャーナルが動作していないか記録できない。何も変更されていない |
INVALID_TEXT | エンベロープ | document.write / document.transform / selection.set / workflow.apply_patch:content に単独の UTF-16 サロゲートが含まれる。何も変更されていない |
REVIEW_BACKLOG_FULL | エンベロープ | document.write:文書に未レビューの AI の変更が多すぎる。何も変更されていない |
ABORTED | エンベロープ | document.write / document.transform / selection.set / workflow.apply_patch:書き込みの記録中にユーザーが文書を編集した、閉じた、変換した、または選択範囲を動かした。どれかは reason が示す。何も変更されていない——読み直して再試行する |
NOT_WORKFLOW | エンベロープ | 非 YAML ワークフロータブで workflow.* が呼ばれた |
READ_ONLY | エンベロープ | 読み取り専用ドキュメントへのミューテーションが試行された |
NO_EDITOR | エンベロープ | selection.* が呼ばれたがフォーカス中のタブに生きているエディタがない |
INTERNAL | エンベロープ | ハンドラーで予期しないエラー |
| (平文文字列) | 文字列 | 必須引数の欠落または型違い |