Feature Chain — operationId ひとつでフルスタックを追跡する

ひとつの機能を修正するには、どのファイルに触れる必要があるか?operationId をひとつ入力すれば答えが出る。


問題

フルスタックアプリケーションにおいて、「ひとつの機能」はひとつのファイルには収まらない。

「提案の承認(AcceptProposal)」という機能を修正しなければならないとしよう。この機能は API スペックにもあり、サービスロジックにもあり、データベーススキーマにもあり、認可ポリシーにもあり、状態遷移ダイアグラムにもあり、外部関数呼び出しにもあり、テストシナリオにもあり、フロントエンドにもある。

従来、この全体の範囲を把握する方法は二つだった:

  1. Grep を何十回も実行する
  2. コードを手動で追跡する

どちらも遅く、どちらも漏れが生じる。特にレイヤーをまたぐ参照 — API スペックからサービスへ、サービスから DB スキーマへ、サービスから認可ポリシーへ — を人間が漏れなく追跡することは現実的に難しい。

しかし、もし各レイヤーのソースが他のレイヤーをシンボリックに参照しているなら、その参照を辿るだけで全体の範囲が自動的に明らかになる。


Feature Chain とは

Feature Chain は、ひとつの API 機能(operationId)に紐づいたすべてのソースノードを抽出したものだ。

operationId をひとつの起点として、ソース間のシンボル参照を辿りながら、関連するすべてのファイルと行番号を一度に出力する。Grep を何十回も実行する手間が、コマンド一つに置き換わる。

fullend chain AcceptProposal specs/
── Feature Chain: AcceptProposal ──

  OpenAPI    api/openapi.yaml:296                          POST /proposals/{id}/accept
  SSaC       service/proposal/accept_proposal.ssac:19      @get @empty @auth @state @put @call @post @response
  DDL        db/gigs.sql:1                                 CREATE TABLE gigs
  DDL        db/proposals.sql:1                            CREATE TABLE proposals
  DDL        db/transactions.sql:1                         CREATE TABLE transactions
  Rego       policy/authz.rego:3                           resource: gig
  StateDiag  states/gig.md:7                               diagram: gig → AcceptProposal
  StateDiag  states/proposal.md:6                          diagram: proposal → AcceptProposal
  FuncSpec   func/billing/hold_escrow.go:8                 @func billing.HoldEscrow
  Gherkin    scenario/gig_lifecycle.feature:4              Scenario: Happy Path - Full Gig Lifecycle
  Gherkin    scenario/gig_lifecycle.feature:42             Scenario: Unauthorized Access

機能ひとつの全体構造が一画面に表示される。接続されていないレイヤーは出力しない。


なぜ可能なのか

これは魔法ではない。ソースがすでにお互いを参照しているから可能なのだ。

fullend フレームワークでは、各 SSOT(Single Source of Truth)レイヤーが他のレイヤーをシンボリックに指している:

  • SSaC@get Model.Method → DDL テーブル
  • SSaC@auth action resource → Rego 認可ポリシー
  • SSaC@state diagramID → Mermaid 状態ダイアグラム
  • SSaC@call pkg.Func → Func Spec 実装
  • OpenAPI の operationId → SSaC ファイル名
  • Gherkin の action step → operationId
  • STML の endpoint → OpenAPI path

これらの参照は元々 crosscheck — SSOT 間の整合性を検証するツール — のために設計された。crosscheck がすでにこれらの参照をパースしているため、同じインフラを再利用することでグラフ探索だけで feature chain が抽出される。


探索経路

operationId を起点とすると、参照グラフはこのように展開される:

operationId (起点)
├── OpenAPI → path + method
├── SSaC → サービス関数ファイル
│   ├── @get → DDL テーブル群
│   ├── @auth → Rego ポリシールール
│   ├── @state → Mermaid stateDiagram 遷移
│   ├── @call → Func Spec 実装
│   └── @publish → キュー購読者
├── Gherkin → operationId を参照するシナリオ群
└── STML → endpoint を参照するフロントエンドファイル

各枝は一段階のシンボル参照だけを辿る。深さではなく、幅の広い探索だ。ひとつの機能がどのレイヤーに痕跡を残しているかが、すべて明らかになる。


これが変えること

修正範囲の把握

「この機能を直すには、どこに触れればいいのか?」

この問いに答えるために、私たちはコードを読み、grep を走らせ、同僚に聞く。Feature Chain はこの問いをコマンド一つに置き換える。シンボル参照がある限り、漏れるファイルはない。

AI によるコード修正

AI に機能の修正を任せるとき、最も難しいのは「修正範囲を伝えること」だ。コンテキストウィンドウに関連ファイルをすべて入れてこそ AI が正確に修正できるが、どのファイルが関連するかを人間が判断しなければならない。

Feature Chain があれば違う。operationId をひとつ伝えるだけで、全体の修正範囲が自動的に特定される。AI に渡すコンテキストが漏れなく準備される。

コードレビュー

PR をレビューするとき、「この機能を修正したなら、あのファイルも変わっているべきでは?」という疑問を chain と照合すればすぐに確認できる。レイヤー間の不一致を、人間の代わりに構造が検出してくれる。

オンボーディング

新しく加わった開発者が「AcceptProposal がどう動くか知りたい」と言ったとき、Feature Chain をひとつ見せれば済む。API から DB まで、認可ポリシーからテストシナリオまで — 機能の全体像が一目でわかる。


なぜ operationId なのか

起点を何にするかが重要だ。Feature Chain は operationId を選んだ。

理由はシンプルだ。フルスタックアプリケーションにおいて、機能の単位は API エンドポイントだ。ユーザーがボタンを押すと API が呼ばれ、その API がサービスロジックを実行し、DB を読み、認可を確認し、状態を遷移させる。この一連の流れの起点が operationId だ。

operationId はすでに OpenAPI スペックに定義されており、チーム全体が共有する名前だ。「AcceptProposal を修正しなければ」と言えば、バックエンド開発者も、フロントエンド開発者も、QA も同じものを思い浮かべる。この普遍的な名前ひとつでスタック全体を貫くのが、Feature Chain の設計だ。


前提条件

Feature Chain が動作するには前提がある:

  1. ソースがシンボリックにお互いを参照していること。 SSaC の @get@auth@state@call ディレクティブが、他の SSOT を明示的に指していなければならない。参照が暗黙的であれば — たとえば DB テーブル名がコード内に文字列としてのみ存在すれば — 追跡できない。

  2. crosscheck を通過していること。 Feature Chain はシンボル参照を辿るため、参照が有効でなければ誤った結果が出る。crosscheck が参照の整合性を保証し、Feature Chain はその上で探索する。

これが Feature Chain が汎用ツールではない理由だ。どんなプロジェクトにも適用できるわけではない。ソース間の参照が設計されたプロジェクト — fullend のように SSOT がお互いを明示的に指す構造でのみ動作する。


未来:GEUL + SILK

現在、Feature Chain は各 SSOT パーサーを順に巡って探索する。SSaC パーサー、DDL パーサー、Rego パーサー、Mermaid パーサーをそれぞれ呼び出し、結果を組み合わせる。

すべての SSOT が GEUL グラフに変換されれば、Feature Chain は単一インデックスクエリになる。SILK の SIDX ビット演算 AND により、operationId に紐づいたすべてのノードを一度のクエリで抽出できる。

パーサー別の巡回からグラフクエリへ。Feature Chain のインターフェースは同じだが、内部は根本的に変わる。


まとめ

フルスタックアプリケーションにおいて、「機能」はひとつのファイルにはない。複数のレイヤーにまたがって存在し、それらのレイヤーはお互いを参照している。Feature Chain はこの参照を辿り、機能ひとつの全体範囲を自動的に抽出する。

operationId をひとつ入力すれば、API スペックから DB スキーマまで、認可ポリシーからテストシナリオまで — Grep を何十回も実行する手間がコマンド一つに置き換わる。

コード:github.com/park-jun-woo/fullend