<p><em>On the quiet gap between what your code says, what your migrations promised, and what your database actually did — and how this release closes it.</em></p><p>Here's a bug I've shipped more than once. A model confidently declares a relationship:</p><pre><code class="language-php">class Order extends Model
{
    public function customer()
    {
        return $this-&gt;belongsTo(Customer::class);
    }
}
</code></pre><p>The code is right. The tests (the ones I wrote) pass. And yet, months later, a query mysteriously returns null, because somewhere along the way a migration was edited, a foreign key was never added, and the database never actually agreed with the code.</p><p>That's the theme of e 0.6.3: there are three sources of truth in a Laravel app — your code, your migrations, and the live database — and they drift apart silently. This release is about seeing all three at once.</p><h2>Why this, why now</h2><p>We already had two of the three pieces. The schema diff compares migrations against the live database. Eloquent completion reads real columns from your schema. What was missing was the relational half — the part that lives in your model classes as method calls and, if all goes well, mirrors itself as foreign keys in the database.</p><p>Nobody shows you that mirror. So I built it.</p><h2>How #1 works: the Eloquent relationship graph (⌘⌥R)</h2><p>Press ⌘⌥R and e does three things:</p><ol><li><p><strong>Parses your models.</strong> It walks <code>app/Models</code>, finds every <code>hasMany</code>, <code>belongsTo</code>, <code>belongsToMany</code>, <code>morph*</code> call, and notes which model each one points to and which method it lives in.</p></li><li><p><strong>Reads the real foreign keys.</strong> It asks the database directly — <code>PRAGMA foreign_key_list</code> on SQLite, <code>information_schema</code> on MySQL, constraint joins on Postgres.</p></li><li><p><strong>Cross-checks them.</strong> For <code>Order belongsTo Customer</code>, it expects an FK on <code>orders</code> pointing at <code>customers</code>. For <code>Customer hasMany Order</code>, it expects the FK on <code>orders</code> pointing back.</p></li></ol><p>The result is a graph of your models where each relationship is a clickable edge — and the interesting ones are the edges that don't line up:</p><pre><code class="language-text">Order · orders
    customer()   belongsTo → Customer     ⚠ no FK
    items()      hasMany → OrderItem

Customer · customers
    orders()     hasMany → Order          ⚠ no FK
</code></pre><p>That ⚠ no FK is the bug from the top of this post, caught before production catches it for you. The relationship is real in code; the database was never told. Click the model name to jump to the file, click a relation to jump to the related model.</p><p>Paired with the schema diff, you now have the complete picture: code says X, migrations say Y, the database is doing Z — here's where they disagree. As far as I know, no other editor puts those three in one frame.</p><h2>How #2 works: a security lens on your routes (⌘⌥M)</h2><p>The architecture map already knew every route. It turns out <code>php artisan route:list --json</code> also hands you each route's middleware stack — we just weren't looking at it. So now we do:</p><pre><code class="language-text">⚠ 8 unprotected

POST  /invoices/{id}/pay   →  InvoiceController@pay      ⚠ open   [web]
POST  /webhooks/stripe     →  StripeController@handle    🔒       [web, verify.signature]
GET   /invoices            →  InvoiceController@index    🔒       [web, auth]
</code></pre><p>A route that changes state (POST/PUT/PATCH/DELETE) with no authentication in its stack gets a red ⚠ open. It reads like a mini security audit you didn't have to run. And because the agent is right there, clicking the ⚠ hands it the context:</p><pre><code class="language-text">│ Security review: POST /invoices/{id}/pay changes state but has no authentication
│ middleware (current stack: web). Suggest the right protection…
</code></pre><p>Cheap to build, high signal. The middleware was in the data all along; we just made it visible.</p><h2>How #3 works: a Pest test straight from a replay</h2><p>This one closes a loop we'd already started. You can replay a route against your running app (the ▶ button) and see the response and the SQL it ran. Now there's a 🧪 Test button next to it. Click it, and e writes a Pest feature test built from what actually happened:</p><pre><code class="language-php">&lt;?php

it('GET /dashboard responds 200', function () {
    $response = $this-&gt;get('/dashboard');

    $response-&gt;assertStatus(200);
    $response-&gt;assertSee('Dashboard');           // from the response's &lt;title&gt;
});
</code></pre><p>For a JSON endpoint it reads the top-level keys instead:</p><pre><code class="language-php">$response-&gt;assertJsonStructure(['data', 'meta', 'links']);
</code></pre><p>It opens the file, and from there it flows straight into the autonomous test loop (⌘⇧T): replay → generate → fix to green. You went from "does this endpoint work?" to "there's a test asserting it does" in two clicks.</p><h2>A note on how it's built</h2><p>Every one of these features leaned on something that already existed:</p><ul><li><p>The relationship graph reuses the model→table logic from Eloquent completion and the FK plumbing I added to the database layer.</p></li><li><p>The security lens is one new field on the route struct plus a badge.</p></li><li><p>The Pest generator reuses the replay result and the existing test runner.</p></li></ul><p>That's the pattern I keep coming back to: the best features are usually two things you already have, wired together. And each one shipped the same way — compiling, unit-tested, and signed &amp; notarized by Apple in CI so the <code>.dmg</code> just opens, no scary warnings.</p><h2>What I hope you feel</h2><p>Less "where's my debugger, my schema tool, my security scanner, my test scaffolder" — and more <em>the editor already knows</em>. The truth about your app shouldn't be scattered across five tools and a production incident. It should be one keystroke away.</p><p>Code, migrations, database — the whole truth, in one place. That's 0.6.3.</p><p>☕ Grab it on the releases page, and if you find a relationship the graph flags that you think it shouldn't — tell me. That's exactly the conversation I want to be having.</p>