
ひとつの機能を修正するには、どのファイルに触れる必要があるか?operationId をひとつ入力すれば答えが出る。
問題
フルスタックアプリケーションにおいて、「ひとつの機能」はひとつのファイルには収まらない。
「提案の承認(AcceptProposal)」という機能を修正しなければならないとしよう。この機能は API スペックにもあり、サービスロジックにもあり、データベーススキーマにもあり、認可ポリシーにもあり、状態遷移ダイアグラムにもあり、外部関数呼び出しにもあり、テストシナリオにもあり、フロントエンドにもある。
従来、この全体の範囲を把握する方法は二つだった:
- Grep を何十回も実行する
- コードを手動で追跡する
どちらも遅く、どちらも漏れが生じる。特にレイヤーをまたぐ参照 — 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 が動作するには前提がある:
ソースがシンボリックにお互いを参照していること。 SSaC の
@get、@auth、@state、@callディレクティブが、他の SSOT を明示的に指していなければならない。参照が暗黙的であれば — たとえば DB テーブル名がコード内に文字列としてのみ存在すれば — 追跡できない。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 を何十回も実行する手間がコマンド一つに置き換わる。