Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Harness Engineer Guide と Developer Reference の境界は **データ対コー
- [形式モデルを実装に追従させる](reference/21-formal-model-following.ja.md)
- [新規プロトコルへ形式モデルを供給する](reference/22-formal-model-supply.ja.md)
- [Telemetry Schema reference](reference/23-telemetry-schema.ja.md)
- [Intent autonomy・レビュー・完了](reference/24-intent-autonomy.ja.md)

リポジトリレイアウトの設計判断は
[Workspace Layout Decision](reference/18-workspace-layout.ja.md) に記録しています。
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ to add one.
- [Keeping a formal model in step with its implementation](reference/21-formal-model-following.md)
- [Supplying a formal model for a new protocol](reference/22-formal-model-supply.md)
- [Telemetry Schema reference](reference/23-telemetry-schema.md)
- [Intent autonomy, review, and completion](reference/24-intent-autonomy.md)

The repository layout decision is recorded in
[Workspace Layout Decision](reference/18-workspace-layout.md): the framework
Expand Down
66 changes: 53 additions & 13 deletions docs/guide/19-plugins.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

この章は利用者向けリファレンスであり、オーサリングガイドです。プラグインシステムが
現在サポートする面、そのコマンドライン面、セッション起動時にプラグインがホストへ自動
compose される仕組み、利用者に見える安全契約、ローカルでの検証手順、そして 7 つの
パッケージハーネス面と 5 つのセルフインストール面の違いを記述します。これはいかなる
compose される仕組み、利用者に見える安全契約、ローカルでの検証手順、そして
パッケージハーネス面とセルフインストール面の違いを記述します。これはいかなる
上流 README のコピーでもありません — 以下のパス・コマンド・失敗契約はすべて Amadeus
のものです。

Expand Down Expand Up @@ -65,7 +65,7 @@ plugins/example/
1. **オーサリング** — `plugins/<name>/plugin.json` と参照ファイルを書きます。
2. **投影** — パッケージャが `plugins/` を discover し、各ソースを構造的に検証
(マニフェスト存在・identity 一意・プラグイン自身のサブツリーを逸脱するパスなし)
し、各プラグインを 7 つのパッケージハーネスツリーとハーネス中立バンドルへ投影
し、各プラグインを各パッケージハーネスツリーとハーネス中立バンドルへ投影
します。プラグインが 0 件のとき、出力はプラグイン非対応ビルドと byte-identical
です。
3. **inspect** — 合成エンジンが discover 済みプラグインをホストスナップショットと
Expand Down Expand Up @@ -120,7 +120,7 @@ verb は次のとおりです。
読み戻すルートと同一なので、install・compose・discovery が乖離することはありません。
`--project-root <dir>` はこれを上書きして別のホストを対象にします — CLI が存在する場所
以外のホストへ compose する手段で、パッケージされるがセルフインストールされない
`kiro` / `kiro-ide` 面では常に必要です。
`kiro` / `kiro-ide` / `pi` 面では常に必要です。

引数処理は fail-closed で、いかなる変更よりも **前** に行われます: 未知 verb・未知
フラグ・余剰引数は usage を stderr へ出して exit `2` で終わり、ホストには一切触れません。
Expand All @@ -137,8 +137,8 @@ compose を配線しています。`--if-stale` 高速路により、合成レ
起動レイテンシを増やしません。フックの失敗は stderr 警告 1 行と exit 0 であり —
プラグインの問題がセッションをブロックすることはありません。

7 つのパッケージ面すべてがこのトリガーを配線します。Kiro CLI と Kiro IDE は同じ
`.kiro` host tree を共有するため、7 面は 6 個の host directory を対象にします。
8 つのパッケージ面すべてがこのトリガーを配線します。Kiro CLI と Kiro IDE は同じ
`.kiro` host tree を共有するため、8 面は 7 個の host directory を対象にします。

| 面 | session-start トリガー | 自動 compose |
| --- | --- | --- |
Expand All @@ -149,6 +149,7 @@ compose を配線しています。`--if-stale` 高速路により、合成レ
| `kiro` | `agentSpawn` | 配線あり |
| `kiro-ide` | `promptSubmit`(`--if-stale` で冪等) | 配線あり |
| `opencode` | JavaScript plugin の `session.created` event | 配線あり |
| `pi` | extension の `session_start` event | 配線あり |

OpenCode は shell hook ではなく公式 JavaScript/TypeScript plugin event を使います。既存の
`.opencode/plugins/amadeus-opencode-plugin.ts` が `session.created` を処理し、`.opencode`
Expand Down Expand Up @@ -186,7 +187,7 @@ OpenCode は shell hook ではなく公式 JavaScript/TypeScript plugin event
- **`native-manifest`**(`claude`)— ホストのプラグインマーケットプレイス経由で
`.claude-plugin/plugin.json` を使ってインストール。自動 compose は `hooks/hooks.json`
から走ります。
- **`folder-drop-auto`**(`codex`・`cursor`・`kimi`・`kiro`・`kiro-ide`)— バンドルの
- **`folder-drop-auto`**(`codex`・`cursor`・`kimi`・`kiro`・`kiro-ide`・`pi`)— バンドルの
`plugins/<name>/` を、プロジェクトルート配下の
`<ハーネスディレクトリ>/.amadeus-plugin-src/<name>/`(Codex なら
`.codex/.amadeus-plugin-src/<name>/`)へコピー。ここが `compose` の走査先であり、
Expand Down Expand Up @@ -279,7 +280,7 @@ spec が drift したことを知らせ、*あなた* がチェック再実行
検証はローカルかつ一時的です — プラグインを試すためにコミット済みツリーを変更する
ことはありません。リファレンスライフサイクルテストがモデルです。canonical ソースを
使い捨ての一時ワークスペースへコピーし、パッケージャのソース/出力ルートをそこへ
リダイレクトし(`AMADEUS_PLUGINS_ROOT` / `AMADEUS_DIST_ROOT`)、7 面すべてへ投影し
リダイレクトし(`AMADEUS_PLUGINS_ROOT` / `AMADEUS_DIST_ROOT`)、全面へ投影し
一時ホストへ compose し、doctor を実行し、drop します。宣言物だけが生成・検出・除去
され、tracked tree に一時ファイルが 1 つも残らないことを assert します。

Expand All @@ -295,11 +296,50 @@ bun test tests/integration/t254-reference-plugin-lifecycle.test.ts

---

## 7 つのパッケージ面、5 つのセルフインストール面
## import する全モジュールを宣言する

パッケージャは各プラグインを **7 つ** のハーネス面へ投影します: `claude`・`codex`・
`cursor`・`kiro`・`kiro-ide`・`opencode`・`kimi`。セルフインストール(ハーネスを
compose されたプラグインは、`plugin.json` が宣言したファイルだけを運びます。したがって
宣言済みツールが import しているのに `tools` へ載せ忘れたヘルパーモジュールは、単なる
記載漏れではなく、compose 後の全ホストにおける import 欠落です。ファイルがディスク上に
そのまま在る自分の作業ツリーではロードでき、実際にインストールされた先で失敗します。

パッケージャはこれを **import-closure guard** で塞ぎます。manifest が宣言する各ツールを
起点に *相対* import(`./x.ts`・`../y.ts`)の推移閉包を辿り、到達した全モジュールが
`plugin.json` に宣言され、かつプラグイン自身のソースとして実在することを要求します。
`node:crypto` のような bare specifier はランタイムがプラグインツリーの外から解決するため
対象外で、絶対指定は境界違反として報告されます。

guard は投影の一部として走るため、壊れた面を出荷する代わりにビルドが失敗します。
allowlist も skip フラグもありません — モジュールは宣言され所有されることで通り、
そうでなければ通りません。読めない参照は閉包から取り除かれるのではなく failure として
列挙されます。これが、import パスの typo が検査対象集合を無言で縮めることを防ぎます。

失敗は違反参照ごとに1行、プラグイン名を前置して出力されます。最初の1件で止まらず、
修復すべき集合が一度に列挙されます。

```
MISSING from formal-model-check plugin.json: plugins/formal-model-check/tools/helper.ts
MISSING from formal-model-check owned sources: plugins/formal-model-check/tools/helper.ts
UNREADABLE import in formal-model-check: plugins/formal-model-check/tools/typo.ts
```

3つの異なる修復として読みます。`MISSING from … plugin.json` は、ファイルはプラグイン内に
実在するが manifest が運んでいない — `tools` へ追加します。`MISSING from … owned sources`
は、manifest が名指すパスに対応するファイルがプラグイン内に無い状態です。
`UNREADABLE import` は参照自体が解決できなかった場合で、ファイル不在・不正なパス・
実体がリポジトリ外へ出る symlink のいずれかです。

guard の実体は `scripts/import-closure-guard.ts` にあります。内部構造とテスト配置は
[コントリビュート](../reference/11-contributing.ja.md#プラグイン-import-closure-guard)
を参照してください。

---

## 8 つのパッケージ面、5 つのセルフインストール面

パッケージャは各プラグインを **8 つ** のハーネス面へ投影します: `claude`・`codex`・
`cursor`・`kiro`・`kiro-ide`・`opencode`・`kimi`・`pi`。セルフインストール(ハーネスを
プロジェクトルートへ反映すること)は **閉じた 5 面** のままです: `claude`・`codex`・
`cursor`・`opencode`・`kimi`。`kiro``kiro-ide` はパッケージされますがプロジェクト
`cursor`・`opencode`・`kimi`。`kiro``kiro-ide`・`pi` はパッケージされますがプロジェクト
ルートへは決して昇格しません。2 つのマトリクスは別々の期待集合に対して検証され、一方が
他方の代替に使われることも、5 面が 7 面へ広げられることもありません
他方の代替に使われることも、5 面がパッケージ面の集合へ広げられることもありません
86 changes: 66 additions & 20 deletions docs/guide/19-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ anything the workspace already owns.
This chapter is the user-facing reference and the authoring guide. It describes
what the plugin system supports today, its command-line surface, how a plugin is
composed into a host automatically at session start, what the safety contract
guarantees, how to verify a plugin locally, and how the seven packaged harness
faces differ from the five self-install faces. It is not a copy of any upstream
guarantees, how to verify a plugin locally, and how the packaged harness
faces differ from the self-install faces. It is not a copy of any upstream
README — every path, command, and failure contract below is the Amadeus one.

The worked example is the reference plugin `test-pro`, kept as authoring source
Expand Down Expand Up @@ -67,8 +67,8 @@ in-prose `rules/` paths rewritten. JSON and TypeScript are copied verbatim.
1. **Author** — write `plugins/<name>/plugin.json` and its referenced files.
2. **Project** — the packager discovers `plugins/`, validates each source
structurally (a manifest is present, identities are unique, no path escapes
the plugin's own subtree), and projects every plugin into the seven packaged
harness trees plus a harness-neutral bundle. With no plugins present, the
the plugin's own subtree), and projects every plugin into each packaged
harness tree plus a harness-neutral bundle. With no plugins present, the
output is byte-identical to a plugin-free build.
3. **Inspect** — the composition engine checks a discovered plugin against a host
snapshot and collects *every* problem (same-name stage, malformed manifest,
Expand Down Expand Up @@ -126,8 +126,8 @@ is installed in** — `bun .codex/tools/amadeus-plugin.ts compose` composes into
`.codex/` from anywhere. That is the same root the engine reads composed plugin
stages back from, so install, compose, and discovery cannot drift apart.
`--project-root <dir>` overrides it to target another host — it is how you compose
into a host that is not where the CLI lives (the `kiro` and `kiro-ide` faces,
which are packaged but never self-installed, always need it).
into a host that is not where the CLI lives (the `kiro`, `kiro-ide`, and `pi`
faces, which are packaged but never self-installed, always need it).

Argument handling is fail-closed and happens **before** any mutation: an unknown
verb, an unknown flag, or a surplus argument prints usage on stderr and exits `2`
Expand All @@ -146,8 +146,8 @@ pays only a few `existsSync` probes and returns without recomposing, so the hook
adds no startup latency in the common case. Any hook failure is a single stderr
warning and a zero exit — a plugin problem never blocks the session.

All seven packaged faces wire this trigger. Kiro CLI and Kiro IDE share one
`.kiro` host tree, so the seven faces cover six host directories:
All eight packaged faces wire this trigger. Kiro CLI and Kiro IDE share one
`.kiro` host tree, so the eight faces cover seven host directories:

| Face | Session-start trigger | Auto-compose |
| --- | --- | --- |
Expand All @@ -158,6 +158,7 @@ All seven packaged faces wire this trigger. Kiro CLI and Kiro IDE share one
| `kiro` | `agentSpawn` | wired |
| `kiro-ide` | `promptSubmit` (idempotent via `--if-stale`) | wired |
| `opencode` | JavaScript plugin `session.created` event | wired |
| `pi` | extension `session_start` event | wired |

OpenCode uses its official JavaScript/TypeScript plugin event rather than a
shell hook. The existing `.opencode/plugins/amadeus-opencode-plugin.ts` handles
Expand Down Expand Up @@ -191,13 +192,13 @@ or silently dropped — it renders as an `unknown` row that fails the check.

## Installing a plugin into a host

The packager emits a per-face **install bundle** for every one of the seven faces,
The packager emits a per-face **install bundle** for every one of the eight faces,
alongside a top-level `INSTALL.md` whose steps are dispatched on the face's host
class:

- **`native-manifest`** (`claude`) — install through the host plugin marketplace
using `.claude-plugin/plugin.json`; auto-compose runs from `hooks/hooks.json`.
- **`folder-drop-auto`** (`codex`, `cursor`, `kimi`, `kiro`, `kiro-ide`) — copy the
- **`folder-drop-auto`** (`codex`, `cursor`, `kimi`, `kiro`, `kiro-ide`, `pi`) — copy the
bundle's `plugins/<name>/` into `<harness-dir>/.amadeus-plugin-src/<name>/` under
your project root (`.codex/.amadeus-plugin-src/<name>/` for Codex, and so on) —
the harness-rooted directory `compose` scans, which is also the root the engine
Expand Down Expand Up @@ -295,8 +296,8 @@ the hash matches, the advisory is silent.
Verification is local and temporary — you never mutate the committed tree to try
a plugin out. The reference lifecycle test is the model: it copies the canonical
source into a throwaway temp workspace, redirects the packager's source and output
roots there (`AMADEUS_PLUGINS_ROOT` / `AMADEUS_DIST_ROOT`), projects into all seven
faces, composes into a temp host, runs the doctor, and drops — asserting that only
roots there (`AMADEUS_PLUGINS_ROOT` / `AMADEUS_DIST_ROOT`), projects into every
face, composes into a temp host, runs the doctor, and drops — asserting that only
the declared artifacts are created, detected, and removed and that no temporary
file survives in the tracked tree.

Expand All @@ -312,12 +313,57 @@ clean afterwards.

---

## Seven packaged faces, five self-install faces
## Declaring every module you import

The packager projects every plugin into **seven** harness faces: `claude`,
`codex`, `cursor`, `kiro`, `kiro-ide`, `opencode`, and `kimi`. Self-install — the
reflection of a harness into the project root — stays the **closed five**:
`claude`, `codex`, `cursor`, `opencode`, and `kimi`. `kiro` and `kiro-ide` are
packaged but never promoted to the project root. The two matrices are verified
against separate expected sets; one is never used as a stand-in for the other, and
the five is never widened to seven.
A composed plugin carries exactly the files its `plugin.json` declares. So a
helper module that your declared tool imports, but that you forgot to list in
`tools`, is not a stylistic omission — it is a missing import in every composed
host. The plugin loads in your working tree, where the file is simply there on
disk, and fails wherever it is actually installed.

The packager closes this with the **import-closure guard**. Starting from each
tool your manifest declares, it walks the transitive closure of *relative*
imports (`./x.ts`, `../y.ts`) and requires every module it reaches to be both
declared in `plugin.json` and present among your plugin's own source files. Bare
specifiers like `node:crypto` are resolved by the runtime from outside the plugin
tree and are out of scope; an absolute specifier is a boundary violation and is
reported as such.

The guard runs as part of the projection, so a build fails rather than shipping
a broken face. It has no allowlist and no skip flag — a module passes by being
declared and owned, or not at all. A reference it cannot read is enumerated as a
failure instead of being dropped from the closure, which is what keeps a typo in
an import path from quietly shrinking the set that gets checked.

Failures print one line per offending reference, prefixed with your plugin's
name, and the whole repair set is listed at once rather than stopping at the
first offender:

```
MISSING from formal-model-check plugin.json: plugins/formal-model-check/tools/helper.ts
MISSING from formal-model-check owned sources: plugins/formal-model-check/tools/helper.ts
UNREADABLE import in formal-model-check: plugins/formal-model-check/tools/typo.ts
```

Read them as three distinct repairs. `MISSING from … plugin.json` means the file
exists in your plugin but the manifest does not carry it — add it to `tools`.
`MISSING from … owned sources` means the manifest names a path with no file
behind it inside the plugin. `UNREADABLE import` means the reference could not be
resolved at all: an absent file, a bad path, or a symlink whose real target
leaves the repository.

The guard lives at `scripts/import-closure-guard.ts`; its internals and test
layout are described in
[Contributing](../reference/11-contributing.md#the-plugin-import-closure-guard).

---

## Eight packaged faces, five self-install faces

The packager projects every plugin into **eight** harness faces: `claude`,
`codex`, `cursor`, `kiro`, `kiro-ide`, `opencode`, `kimi`, and `pi`.
Self-install — the reflection of a harness into the project root — stays the
**closed five**: `claude`, `codex`, `cursor`, `opencode`, and `kimi`. `kiro`,
`kiro-ide`, and `pi` are packaged but never promoted to the project root. The two
matrices are verified against separate expected sets; one is never used as a
stand-in for the other, and the five is never widened to the packaged set.
Loading
Loading