pi-mina0.1.0
pi extension that pushes the mina editor's verified, content-addressed edits (minas) into an agent's tool surface, and blocks whole-file writes over existing files
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-ext — pi 拡張 pi-mina
pi(コーディングエージェント)に mina を差し込む拡張。既存ファイルへの write を拒否し
(新規作成は許可、minas 不在なら fail-open)、構造化引数の mina_apply と Fallback の
計器を持つ(ADR-0075)。
なぜ拡張か(スキルに対して何が違うか)
minas skill は pull 型で、エージェントが minas を知らなければ永久に呼ばれない
(docs/adr/0070-skill-wrapper-for-distribution.md の未測定の穴)。拡張はその穴を機構で閉じる:
スキル(SKILL.md) |
pi 拡張 | |
|---|---|---|
| 発見 | pull(貼った引き金から) | push(ツール一覧に常時載る) |
| 規約 | 説明する(飛ばせる) | 強制できる(tool_call を block / modify) |
| runner | pi / Claude Code / codex / AGENTS.md | pi のみ |
| コスト | 読んだ時だけ | ツール説明は毎リクエスト |
v0 は 3 行目の「強制できる」に踏み込んでいない。踏み込む範囲(何を block するか)は未決。
何をするか
mina_apply {path, edits: [{old, new}, …]}— 検証付きの内容指定編集を 1 呼び出しに まとめて(全 hunk を検証してから書くので原子性は据え置き)。bash 経由の引用符層を消し、 拒否(exit 2)は理由つきでエージェントに返る(再読して直す指示になる)。- 既存ファイルへの
writeを拒否(新規作成は許可)。理由と代替(mina_apply/minas apply --whole-stdin)を reason に書く。editと bash は閉じない。 mina_info— daemon の世代・言語サーバ・セッションを返す。- Fallback の tally — ネイティブな
read/edit/write、bash 経由のminas、 拒否したwriteを数える(tally.ts、純関数のみ)。/mina-fallbacksで表示し、session_shutdownと表示時にmina-tallyエントリとしてセッションに 1 件残す。
実測(2026-09-17、docs/loop/pi_arms.py、t11 fixture scale=1200、n=3、deepseek-v4.1-flash)
計器と生データは mina リポジトリ側(https://github.com/335g/mina)。
| arm | minas share | calls | 壁時計 | GREEN |
|---|---|---|---|---|
| none(素の pi) | 0% | 15 | 13.4s | 3/3 |
skill(minas skill --md を貼った pi) |
100% | 25 | 23.9s | 3/3 |
extension v0(mina_info だけ・block なし) |
0% | 16 | 9.4s | 3/3 |
extension v1(mina_apply 1 hunk/call + block) |
88% | 36 | 25.7s | 3/3 |
extension v2(mina_apply バッチ + block) |
100% | 14 | 19.0s | 3/3 |
読み: ツール説明だけでは動かない。 説明を持つ mina_info は 3 run で 1 回しか呼ばれず、
share は素の pi と同じ 0%。動いたのは編集の意思決定点にある道具(mina_apply)。バッチ化で
呼び出し数は skill arm を下回った(14 vs 25)ので、押し出しの値段は skill 経路より安い。
block は 3 run とも発火しなかった(blocked=0)— pi のエージェントは既存ファイルの編集に
write を選ばず edit を使う。block の価値はこの fixture では未証明。詳しくは ADR-0075。
動かす
$ pi -e ./pi-ext # その場で読み込む(インストールしない)
$ pi install ./pi-ext # ユーザ設定に入れる
$ cd pi-ext && npm run check # 自己検証(依存ゼロ・ネットワーク不要)
$ cd pi-ext && npm install && npm run typecheck # pi API に対する型検査
$ python3 docs/loop/pi_arms.py --selftest # 測定ハーネス(LLM なし)
$ python3 docs/loop/pi_arms.py -n 3 --tag v2 # 3 arm × 3 run(LLM を呼ぶ)
package.json の pi.extensions が ./index.ts を指す。拡張は TS のまま読み込まれるので
ビルド手順は無い。@earendil-works/pi-* は pi が同梱するので peerDependencies に * で
書き、bundle しない(docs/packages.md)。
計器(Fallback のベースライン)
拡張は arm ラベルを PI_MINA_ARM から拾い、mina-tally エントリとしてセッションに残す。
集計は docs/loop/mina_tally.py(セッション JSONL の toolCall を直接読むので、拡張を
入れていない arm も同じ物差しで測れる):
# arm ごとにセッションを分けて走らせる
PI_MINA_ARM=none pi --session-dir /tmp/arm-none ... # 素の pi
PI_MINA_ARM=skill pi --session-dir /tmp/arm-skill ... # minas skill --md を貼った pi
PI_MINA_ARM=extension pi -e ./pi-ext --session-dir /tmp/arm-ext ... # この拡張を入れた pi
python3 docs/loop/mina_tally.py --arm none /tmp/arm-none
python3 docs/loop/mina_tally.py --arm skill /tmp/arm-skill
python3 docs/loop/mina_tally.py /tmp/arm-ext # arm は in-band の値を使う
share = minas 編集 / (minas 編集 + ネイティブ edit + write)。ADR-0070 が「未測定」と
書いた穴はこれで埋まる。強制(下記)を入れる前にベースラインを取り、入れた後に再測する
(block 後は「拒否された試行」を別に数える必要があり、計器は未対応)。
次に決めること
- block の価値(保留): 実測 3 版 × 3 run で発火は 0 — pi のエージェントは既存ファイルの
編集に
writeを選ばずeditを使う。いまは残すと決めて後で検討する(発火する条件を 探すか、外すか)。
配布(npm)
pi install npm:pi-mina で入る形にしてある(梱包物は 6 ファイル・9.3 kB、node_modules は
入らない)。公開はまだ(この環境に npm の認証が無い)。手順:
$ cd pi-ext
$ npm pack --dry-run # 何が上がるか確認(6 files / 9.3 kB)
$ npm login # 認証(1 回だけ)
$ npm publish # unscoped なので --access public は不要
$ pi install npm:pi-mina # 利用者側
公開前に検証済みのこと: npm pack → 展開したディレクトリで node selftest.ts が通り、
pi -e <展開先> で読み込んで mina_apply が 2 hunk を 1 呼び出しで適用できた(成果物そのものの
確認)。名前は unscoped の pi-mina(@335g/pi-mina も空いているが、scope の所有が要る分だけ
不利)。pi-package キーワードを付けてあるので gallery に載る。
バイナリは pi からは入らない(pi が走らせるのは npm install だけ)ので cargo install minad minas は別経路のままで、拡張が不在を検出して案内する。pi にサブディレクトリ指定は
無い(git:host/user/repo/pi-ext は .../pi-ext の clone を試みる)ので、git チャネルで配る
ならルートに package.json が要るが、いまは取らない。
配布の補足: pi はサブディレクトリ指定を持たない(git:host/user/repo/pi-ext は
repo=.../pi-ext の clone を試みる)。バイナリは pi からは入らない(pi が走らせるのは
npm install だけ)ので、cargo install minad minas は別経路のままとし、拡張は不在を
検出して案内する。