
Which files do you need to touch to modify a single feature? Type one operationId and the answer appears.
The problem
In a full-stack application, a “feature” doesn’t live in one file.
Say you need to modify a feature called “ExecuteWorkflow.” That feature lives in the API spec, the service logic, the database schema, the authorization policy, the state transition diagram, the external function calls, the test scenarios, and the frontend components.
Historically there have been two ways to grasp this entire scope:
- Run grep dozens of times
- Trace the code by hand
Both are slow, and both miss things. Cross-layer references in particular — API spec to service, service to DB schema, service to authorization policy — are practically impossible for a human to track exhaustively.
It gets worse when you hand the edit to an AI. At 200 endpoints, the AI can no longer hold the full context. Context collapses, patterns drift, and the 201st feature costs 10× the 21st. This is the wall vibe coding hits.
But if each layer’s source symbolically references other layers, then following those references is enough to reveal the whole scope automatically.
What Feature Chain is
Feature Chain is the set of every source node connected to a single API feature (operationId).
Starting from one operationId, it follows the symbolic references between sources and prints every related file and line number at once. Dozens of greps get replaced by one command.
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
The full structure of a feature appears on one screen. Unconnected layers are not printed.
Why it works
This isn’t magic. It works because the sources already reference each other.
In the yongol framework, each SSOT (Single Source of Truth) layer points symbolically at other layers:
- SSaC’s
@get Model.Method→ DDL table - SSaC’s
@auth action resource→ Rego authorization policy - SSaC’s
@state diagramID→ Mermaid state diagram - SSaC’s
@call pkg.Func→ FuncSpec implementation - SSaC’s
@publish "topic"→ functions subscribing to the same topic - OpenAPI’s operationId → SSaC filename
- Hurl scenario → OpenAPI endpoint
- React TSX’s
apiClient.<op>()→ OpenAPI operationId
These references were originally designed for yongol validate — the step that cross-validates the consistency of 9 SSOTs before compile time. Since validate already parses them, reusing the same infrastructure turns feature-chain extraction into graph traversal.
The traversal
Starting from an operationId, the reference graph expands like this:
operationId (entry point)
├── OpenAPI → path + method
├── SSaC → service function file
│ ├── @get → DDL tables
│ ├── @auth → Rego policy rules
│ ├── @state → Mermaid stateDiagram transitions
│ ├── @call → FuncSpec implementations
│ └── @publish → queue subscribers
├── Hurl → test scenarios referencing the operationId
└── React TSX → frontend files calling the endpoint via apiClient
Each branch follows exactly one step of symbolic reference. It’s a breadth-first traversal, not a depth-first one. Every layer a feature leaves traces in shows up.
What this changes
Scoping edits
“Where do I touch to change this feature?”
To answer that, we read code, run grep, ask a coworker. Feature Chain replaces the question with a single command. No file slips through — as long as the symbolic reference exists.
AI-driven edits
The hardest part of delegating a feature change to an AI is telling it “what the scope is.” The AI can only edit correctly when the relevant files are in its context window, and a human has to judge which files are relevant.
With Feature Chain it’s different. Hand it one operationId and the full scope is identified automatically. The AI’s context is prepared with nothing missing. Because the 9 SSOTs are declarative specs — far more compressed than the generated Go code — you can fit the whole chain in the context window with room to spare.
Code review
When reviewing a PR, “if they touched this feature, shouldn’t that file also change?” becomes trivial to verify — just diff against the chain. Cross-layer inconsistency gets caught by structure instead of by people.
Onboarding
When a new engineer says “I want to understand how ExecuteWorkflow works,” just show them the Feature Chain. From API down to DB, from authorization policy to test scenarios — the full terrain of a feature on one screen.
Why operationId
The choice of entry point matters. Feature Chain chose operationId.
The reason is simple. In a full-stack application, the unit of a feature is the API endpoint. A user clicks a button, an API is called, service logic runs, the DB is read, authorization is checked, state transitions happen. The start of that entire flow is the operationId.
operationId is already defined in the OpenAPI spec and shared across the team. Say “we need to modify ExecuteWorkflow” and the backend engineer, the frontend engineer, and QA all think of the same thing. Feature Chain is designed around that universal name as the thread running through the whole stack.
yongol calls this “operationId is the keystone.” One PascalCase identifier binds 9 layers physically together.
Preconditions
For Feature Chain to work, there are assumptions:
Sources must reference each other symbolically. SSaC’s
@get,@auth,@state,@call,@publishdirectives must explicitly point at other SSOTs. If the reference is implicit — say, a DB table name only exists as a string inside code — it can’t be traced.yongol validatemust pass. Feature Chain follows symbolic references, so if the references aren’t valid the result is wrong. validate guarantees reference integrity; Feature Chain traverses on top of that.
That’s why Feature Chain isn’t a general-purpose tool. It can’t be applied to arbitrary projects. It only works in projects where cross-source references are by design — structures like yongol where SSOTs explicitly point at each other.
Future: GEUL + SILK
Today, Feature Chain traverses by invoking each SSOT parser in turn. It calls the SSaC parser, the DDL parser, the Rego parser, the Mermaid parser, the Hurl parser, and the TSX parser, then combines the results.
Once every SSOT is translated into a GEUL graph, Feature Chain becomes a single index query. With SILK’s SIDX bitwise-AND operation, all nodes connected to an operationId can be extracted in one query.
From per-parser traversal to graph query. The interface of Feature Chain stays the same, but the internals change fundamentally.
Wrap-up
In a full-stack application a “feature” doesn’t live in one file. It spans multiple layers, and those layers reference each other. Feature Chain follows those references to automatically extract the entire scope of a single feature.
Type one operationId and you get it all: from API spec to DB schema, from authorization policy to test scenarios, from function implementation to frontend component. Dozens of greps replaced by one command. The AI gets context with nothing missing; the human gets freedom on rails.