CLIがstdoutに数行のJSONを流すだけで、あらゆる観測者——GUI・スケジューラ・ログ収集——が 業務の中身を一切知らないまま、進捗バーを描き、失敗を通知し、履歴を残せるようになります。
「進捗どうですか?」に、CLIが自分で答えるためのプロトコル。
宅配便の追跡番号を思い浮かべてください。荷物の中身は本でも食品でも服でもバラバラですが、 追跡画面は1つで全部に対応できます。ステータスの書式が共有されているからで、 中身が統一されているからではありません。shinchoku はバッチ処理——クロール、エクスポート、 動画変換、バックアップ、AI推論——のための追跡番号です。観測側が理解するのは 封筒(7種類のイベント)だけ。中身(あなたの業務)はあなたのものです。
輸送路はstdout。パイプ・SSH・WebSocket中継——行を運べるものなら何でも、プロトコルは無変更で通る。
printf '{"v":1,"event":"done"}\n' だけで正規のプロデューサー。ライブラリは便利グッズであって契約ではない。
JSONでない行はただのログ。未知のイベントとフィールドは無視。既存ツールは今日から「まだバーの出ない」正規プロデューサー。
ドメインの言葉は値として流れ、語彙には決して入らない。だから1つの観測者があらゆるツールに対応できる。
答えている問いが違います。OpenTelemetry が答えるのは「サービス群全体で何が起きているか」—— トレース・メトリクス・ログをネットワーク経由でコレクタへ送り、あとで分析するための仕組みです。 shinchoku が答えるのは「この1プロセスはどこまで進んだか」——spawnした親に向かって、 stdoutで実況することです。
| shinchoku | OpenTelemetry | |
|---|---|---|
| 関心の単位 | 1プロセスの1回の実行 | サービス群・分散システム |
| 進捗(current/total) | 一級のイベント | 概念が存在しない |
| 輸送路 | stdout → 親プロセス | ネットワーク → コレクタ/バックエンド |
| 導入コスト | printf で足りる | SDK + exporter(+ コレクタ) |
| クラッシュ時 | 終了コードが最終判定 | 末尾のテレメトリは失われうる |
両者は競合ではなく合成できます——消費者が受け取ったイベントを OTel パイプラインへ転送すればいいだけです。 宅配便の例えで言えば、shinchoku は荷物の追跡バーコード、OpenTelemetry は物流会社の基幹システムです。 規範的な適用範囲は SPEC §10(Non-goals)へ。
shinchoku は、実績のある4つの古い知恵を組み合わせただけで、独自の発明を足していません。 唯一の貢献はその組み合わせです——昔ながらの輸送路の上に、寛容でドメイン非依存の語彙を1つだけ置く。 それで初めて、1つの観測者があらゆるツールに対応できるようになります。
プロセスは stdout に行を書いて報告し、読む側は寛容にパースする。数十年の実績がある機構——ただしそこでの語彙は合否に縛られている。
進捗・成果物・注釈を特別な書式の行として流し、ランナーがUIに変える。正しい語彙——ただし方言が特定ベンダーのものになっている。
機械可読なイベントをJSON行で流す。正しい輸送路——ただし各ツールが私家版の語彙を発明するので、観測者がツールを横断できない。
子は状態を実況し、親が判定を握る。「終了コードが最終判定」はこの伝統の直系。
| event | フィールド | 意味 |
|---|---|---|
| start | title?, total? | 実行の開始宣言。最初に出す |
| progress | current, total?, msg? | 完了した作業単位数 |
| log | level, msg | info / warn / error(非致命) |
| metric | key, value | 名前付きの数値。観測側はそのまま表示 |
| artifact | path, label? | 成果物ファイルの存在宣言 |
| done | summary? | 正常終了。最後に出す |
| failed | msg | 致命的失敗。最後に出す |
将来のための予約語: ask(対話)・row(表データ)・heartbeat(常駐監視)。
追加は "v" を上げません——下の消費者ルールが互換性を構造的に保証します。
Rust / Go / Node / PHP / Python の emit ヘルパを同梱しています。いずれも約100行・依存ほぼゼロの薄いラッパーです。
# Cargo.toml [dependencies] shinchoku = "0.1" use shinchoku::Event; Event::start().title("取り込み").total(120).emit(); Event::progress(3).total(120).emit(); Event::done().summary("4,520件").emit(); // 消費者側: features = ["parse"] で寛容な parse_line() が使える
// go get github.com/uiuifree/shinchoku/go
import shinchoku "github.com/uiuifree/shinchoku/go"
shinchoku.Start("取り込み", 120)
shinchoku.Progress(3, 120)
shinchoku.Done("4,520件")
// npm install shinchoku(ESM)
import * as shinchoku from "shinchoku";
shinchoku.start({ title: "取り込み", total: 120 });
shinchoku.progress(3, 120);
shinchoku.done("4,520件");
// composer require shinchoku/shinchoku
use Shinchoku\Shinchoku;
Shinchoku::start('取り込み', 120);
Shinchoku::progress(3, 120);
Shinchoku::done('4,520件');
# pip install shinchoku
import shinchoku
shinchoku.start(title="取り込み", total=120)
shinchoku.progress(3, total=120)
shinchoku.done("4,520件")
event → 無視するかログ表示。決してエラーにしないfailed を見ないまま非ゼロ終了 → 失敗として合成する。プロトコルは実行を実況し、終了コードが裁くこの5つのルールがあるから、イベントの追加は互換な変更になり、 ルール5だけ実装した観測者も既に正規の最小消費者です。バー・メトリクス・成果物ボタンは すべてその上の漸進的強化にすぎません。