[v0.1/Proto Review] package felis.v1 と protocol 2.0 の命名ズレは 1.0 で確定すべき #138

Closed
opened 2026-09-05 11:38:03 +09:00 by natsukium · 1 comment
Owner

背景

crates/felis-protocol/proto/felis.protopackage felis.v1 は schema-namespace major で、PROTOCOL_MAJOR = 1 とは独立して進むと felis.proto 前文と docs/explanation/architecture/ipc.md「Schema evolution」で定義されている。

package moves only when a daemon has to hold two schemas at once: a deprecation window serves the prior and the new major side by side

一方 docs/reference/ipc.md「The minor ledger」末尾の not on the table 節と crates/felis-protocol/proto/BREAKING.md では、ResourceReport の repack / Image family の repack が「pre-release なので major 1 のまま破壊」と説明され、#30「Reset the first public wire baseline to protocol 2.0」で最初の公開 baseline を 2.0 にリセットする計画がある。

このとき package 名を felis.v1 のまま PROTOCOL_MAJOR = 2 に上げると:

  • Rust 生成物は felis.v1 のまま protocol 2 の bytes を喋る。非 Rust クライアント(将来の felis-tui / felis.el / third-party)が felis.v1 を import したまま protocol 2 と信じると混乱する。
  • 逆に 2.x の deprecation window で felis.v1felis.v2 を両方持つ設計が前提だが、最初の public が既に v1 パッケージで protocol 2 だと「felis.v2 は protocol 3 から」という off-by-one が恒久化する。
  • buf breaking の baseline は proto-baseline/ に tag 単位で置かれるが、package 名が major とズレていると baseline 比較時に package rename を breaking として誤検出/見逃し得る。

これは prost 生成物の import path (felis.v1::FrameKind) に現れる公開 API で、1.0 でタグを打った後に変えると全 downstream の import を壊す。互換性を無視できる今しか直せない。

問い

1.0 / protocol 2.0 baseline で package 名をどう凍結するか:

  • 案A: package felis.v2 に bumpPROTOCOL_MAJOR = 2 と package を揃える。explanation/architecture/ipc.md の「package moves only when…」節は「最初の public は前例がないので例外的に揃えた」と追記し、以降は「nvN は release 時のみ一致し、pre-release break では揃えない」に再定義。
  • 案B: package felis.v1 のまま据え置き — package は「この repo で最初に freeze した schema」の印として v1 に固定し、PROTOCOL_MAJOR とは独立させる。reference/workspace.md「Versioning」に「package version ≠ protocol major after 1.0」と明記。
  • 案C: package を felis (unversioned) に — major ごとに felis.vN を生やすのではなく、felis.proto 自体を major で分岐させる(felis2.proto)。ただし buf の推奨と逆行。

現行 docs は案B寄りだが、#30 の「2.0 に reset」は案Aを示唆しており不整合。

提案

  • #30 の実行時に案A/B のいずれかを選ぶ。個人的には 案A が downstream の混乱が最も少ない(「felis.v2 を import すれば protocol 2」と読める)。案B を選ぶなら reference/ipc.md「Versioning」冒頭に「package v1 は protocol 2 でも v1 のままである」ことを赤字で固定し、just proto の生成物パスと skills/felis の import 例を更新。
  • どちらにせよ crates/felis-protocol/src/generated/ の再生成、buf breaking baseline の再取得、reference/workspace.md「Versioning」節の表を 1.0 で凍結。CHANGELOG.md 1.0 に「wire package = X / protocol = Y」を併記。
  • felis-protocol crate の publish = false を外す時の packagecrate version の対応も同時に決める(reference/workspace.md Revisit-if)。

判定基準

  • felis-protocol/proto/felis.proto の package 行を見ただけで、どの protocol major を喋るかが一意に決まること(または「ズレる」なら docs がズレを明言していること)。
  • 1.0 の just proto 生成物と buf breaking baseline が同じ package で green であること。
  • 非 Rust クライアント作者が felis.v1 / felis.v2 のどちらを import すべきか reference/ipc.md だけで判断できること。
  • explanation/architecture/ipc.md「Schema evolution」に Revisit trigger(「package を bump するのは side-by-side decoder が必要な時のみ」)が選んだ案と整合していること。

対象ファイル

  • crates/felis-protocol/proto/felis.proto (package 行)
  • crates/felis-protocol/src/preface.rs (PROTOCOL_MAJOR 定数とコメント)
  • crates/felis-protocol/src/generated/ (prost 生成物)
  • docs/reference/ipc.md「Layering / Versioning」
  • docs/reference/workspace.md「Versioning」
  • docs/explanation/architecture/ipc.md「Schema evolution / Kind or arm?」
  • justfile / scripts/proto/ / flake.nix (buf toolchain)

Parent: #12 および #11 / #5, #30

## 背景 `crates/felis-protocol/proto/felis.proto` の `package felis.v1` は schema-namespace major で、`PROTOCOL_MAJOR = 1` とは独立して進むと `felis.proto` 前文と `docs/explanation/architecture/ipc.md`「Schema evolution」で定義されている。 > package moves only when a daemon has to hold two schemas at once: a deprecation window serves the prior and the new major side by side 一方 `docs/reference/ipc.md`「The minor ledger」末尾の **not on the table** 節と `crates/felis-protocol/proto/BREAKING.md` では、`ResourceReport` の repack / `Image` family の repack が「pre-release なので major 1 のまま破壊」と説明され、`#30`「Reset the first public wire baseline to protocol 2.0」で最初の公開 baseline を `2.0` にリセットする計画がある。 このとき package 名を `felis.v1` のまま `PROTOCOL_MAJOR = 2` に上げると: - Rust 生成物は `felis.v1` のまま protocol 2 の bytes を喋る。非 Rust クライアント(将来の `felis-tui` / `felis.el` / third-party)が `felis.v1` を import したまま protocol 2 と信じると混乱する。 - 逆に 2.x の deprecation window で `felis.v1` と `felis.v2` を両方持つ設計が前提だが、最初の public が既に `v1` パッケージで protocol 2 だと「`felis.v2` は protocol 3 から」という off-by-one が恒久化する。 - `buf breaking` の baseline は `proto-baseline/` に tag 単位で置かれるが、package 名が major とズレていると baseline 比較時に `package` rename を breaking として誤検出/見逃し得る。 これは `prost` 生成物の import path (`felis.v1::FrameKind`) に現れる公開 API で、1.0 でタグを打った後に変えると全 downstream の `import` を壊す。互換性を無視できる今しか直せない。 ## 問い 1.0 / protocol 2.0 baseline で package 名をどう凍結するか: - **案A: `package felis.v2` に bump** — `PROTOCOL_MAJOR = 2` と package を揃える。`explanation/architecture/ipc.md` の「package moves only when…」節は「最初の public は前例がないので例外的に揃えた」と追記し、以降は「`n` と `vN` は release 時のみ一致し、pre-release break では揃えない」に再定義。 - **案B: `package felis.v1` のまま据え置き** — package は「この repo で最初に freeze した schema」の印として `v1` に固定し、`PROTOCOL_MAJOR` とは独立させる。`reference/workspace.md`「Versioning」に「package version ≠ protocol major after 1.0」と明記。 - **案C: package を `felis` (unversioned) に** — major ごとに `felis.vN` を生やすのではなく、`felis.proto` 自体を major で分岐させる(`felis2.proto`)。ただし `buf` の推奨と逆行。 現行 docs は案B寄りだが、`#30` の「2.0 に reset」は案Aを示唆しており不整合。 ## 提案 - `#30` の実行時に案A/B のいずれかを選ぶ。個人的には **案A** が downstream の混乱が最も少ない(「`felis.v2` を import すれば protocol 2」と読める)。案B を選ぶなら `reference/ipc.md`「Versioning」冒頭に「package `v1` は protocol 2 でも `v1` のままである」ことを赤字で固定し、`just proto` の生成物パスと `skills/felis` の import 例を更新。 - どちらにせよ `crates/felis-protocol/src/generated/` の再生成、`buf breaking` baseline の再取得、`reference/workspace.md`「Versioning」節の表を 1.0 で凍結。`CHANGELOG.md` 1.0 に「wire package = X / protocol = Y」を併記。 - `felis-protocol` crate の `publish = false` を外す時の `package` ↔ `crate version` の対応も同時に決める(`reference/workspace.md` Revisit-if)。 ## 判定基準 - `felis-protocol/proto/felis.proto` の package 行を見ただけで、どの protocol major を喋るかが一意に決まること(または「ズレる」なら docs がズレを明言していること)。 - 1.0 の `just proto` 生成物と `buf breaking` baseline が同じ package で green であること。 - 非 Rust クライアント作者が `felis.v1` / `felis.v2` のどちらを import すべきか `reference/ipc.md` だけで判断できること。 - `explanation/architecture/ipc.md`「Schema evolution」に Revisit trigger(「package を bump するのは side-by-side decoder が必要な時のみ」)が選んだ案と整合していること。 ## 対象ファイル - `crates/felis-protocol/proto/felis.proto` (package 行) - `crates/felis-protocol/src/preface.rs` (`PROTOCOL_MAJOR` 定数とコメント) - `crates/felis-protocol/src/generated/` (prost 生成物) - `docs/reference/ipc.md`「Layering / Versioning」 - `docs/reference/workspace.md`「Versioning」 - `docs/explanation/architecture/ipc.md`「Schema evolution / Kind or arm?」 - `justfile` / `scripts/proto/` / `flake.nix` (buf toolchain) Parent: #12 および #11 / #5, #30
Author
Owner

#138 は maintainer 判断で v1 のまま維持 / PROTOCOL 1.0 のままリセット で確定しました。

  • package felis.v1 は据え置き(案B)。PROTOCOL_MAJOR=1 / MINOR=9 までの break は pre-release として許容し、最初の公開 baseline を protocol 2.0 に bump する案(#30)は見送り — baseline を 1.0 にリセットする方針で揃えます。
  • BREAKING.mdbase: 行と first-release の扱いも、このリセットに合わせて整理します。

この issue は Won't fix / 凍結決定として close します。関連する #30 / #5 / #52 の ledger 整備は、v1 / 1.0 を前提に更新します。

#138 は maintainer 判断で **v1 のまま維持 / PROTOCOL 1.0 のままリセット** で確定しました。 - `package felis.v1` は据え置き(案B)。`PROTOCOL_MAJOR=1 / MINOR=9` までの break は pre-release として許容し、最初の公開 baseline を `protocol 2.0` に bump する案(#30)は見送り — baseline を 1.0 にリセットする方針で揃えます。 - `BREAKING.md` の `base:` 行と `first-release` の扱いも、このリセットに合わせて整理します。 この issue は Won't fix / 凍結決定として close します。関連する #30 / #5 / #52 の ledger 整備は、v1 / 1.0 を前提に更新します。
Sign in to join this conversation.
No description provided.