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

機能一つを修正するにはどのファイルを触ればいいか? operationId 一つを入力すれば答えが出る。


問題

フルスタックアプリケーションにおいて「機能一つ」は一つのファイルに存在しない。

「ワークフロー実行(ExecuteWorkflow)」という機能を修正しなければならないとしよう。この機能は API スペックにも、サービスロジックにも、データベーススキーマにも、認可ポリシーにも、状態遷移図にも、外部関数呼び出しにも、テストシナリオにも、フロントエンドコンポーネントにも存在する。

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

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

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

AI に修正を任せるときはさらに深刻だ。200 エンドポイント規模のコードベースで AI は全体のコンテキストを捕捉できない。コンテキストが崩壊してパターンがドリフトし、201 番目の機能は 21 番目の機能の 10 倍のコストになる。これがバイブコーディングがぶつかる壁だ。

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


Feature Chain とは

Feature Chain は一つの API 機能(operationId)に接続されたすべてのソースノードを抽出したものだ。

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

yongol chain ExecuteWorkflow specs/
── Feature Chain: ExecuteWorkflow ──

  OpenAPI    api/openapi.yaml                         POST /workflows/{id}/execute
  SSaC       service/workflow/execute_workflow.ssac   @get @empty @auth @state @call @publish @response
  DDL        db/workflows.sql                         CREATE TABLE workflows
  DDL        db/execution_logs.sql                    CREATE TABLE execution_logs
  Rego       policy/authz.rego                        resource: workflow
  StateDiag  states/workflow.md                       diagram: workflow → ExecuteWorkflow
  FuncSpec   func/billing/check_credits.go            @func billing.CheckCredits
  FuncSpec   func/billing/deduct_credit.go            @func billing.DeductCredit
  FuncSpec   func/worker/process_actions.go           @func worker.ProcessActions
  FuncSpec   func/webhook/deliver.go                  @func webhook.Deliver
  Hurl       tests/scenario-happy-path.hurl           scenario: scenario-happy-path.hurl

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


なぜ可能か

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

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

  • SSaC@get Model.Method → DDL テーブル
  • SSaC@auth action resource → Rego 認可ポリシー
  • SSaC@state diagramID → Mermaid 状態図
  • SSaC@call pkg.Func → FuncSpec 実装
  • SSaC@publish "topic" → 同じトピックを購読する関数群
  • OpenAPI の operationId → SSaC ファイル名
  • Hurl シナリオ → OpenAPI エンドポイント
  • React TSXapiClient.<op>() → OpenAPI operationId

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


探索経路

operationId を起点にすると、参照グラフはこのように広がる:

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

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


これが変えること

修正範囲の把握

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

この質問の答えを得るために我々はコードを読み、grep を回し、同僚に聞く。Feature Chain はこの質問を一つのコマンドに置き換える。抜けたファイルは存在しない — シンボル参照がある限り。

AI によるコード修正

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

Feature Chain があれば違う。operationId 一つだけ教えれば全修正範囲が自動的に特定される。AI に渡すコンテキストが漏れなく準備される。9 つの SSOT はそれぞれ宣言的仕様 — 生成される Go コードよりはるかに圧縮されている — なので、チェーン全体をコンテキストに入れてもウィンドウに余裕がある。

コードレビュー

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

オンボーディング

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


なぜ operationId なのか

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

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

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

yongol はこれを**「operationId がキーストーン(keystone)」**と呼ぶ。PascalCase の識別子一つが 9 つのレイヤーを物理的に束ねる。


前提条件

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

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

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

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


未来:GEUL + SILK

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

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

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


まとめ

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

operationId 一つを入力すれば、API スペックから DB スキーマまで、認可ポリシーからテストシナリオまで、関数実装からフロントエンドコンポーネントまで — Grep 数十回が一つのコマンドに置き換わる。AI には漏れのないコンテキストが、人には「レールの上の自由」が残る。

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