The First Feature
Time to write code: creating a note. This chapter is about the edit loop — the tight cycle you and Elyra will live in for the rest of the project — and the LSP machinery that makes it check its own work.
The problem
Every feature crosses at least four files in a SILT app: a migration, a model, a controller, and a Svelte page. They have to agree with each other — the controller validates fields the migration created, the page submits what the controller expects. Most agent frustration lives exactly here: an edit in one file that quietly disagrees with another.
The hard way
The classic loop: agent edits the controller, says done. You run the page — 500 error. You paste the error back. Agent apologizes, fixes it, breaks the model instead. Each round trip costs a minute and a little trust. The agent isn't careless; it just couldn't see the mistake at the moment it made it.
The Elyra way: pin the contract first
Start a fresh session for the feature. Freddy's SPEC.md is the contract, so keep it in the agent's sight at all times:
/pin SPEC.md
Pinned files are injected into every request — not just once at the start, where they'd eventually fall out of a compacted context. The spec is now standing context, like a card taped to the monitor. Pin sparingly: the spec earns its tokens, your 400-line controller doesn't.
Building the feature
Now the prompt. Note the shape: scope, constraints, definition of done — three sentences, not an essay:
> Implement note creation per SPEC.md. Migration (notes table:
content, nullable title, timestamps, soft-delete archived_at),
Note model, NoteController with store(), an Inertia Capture
page with the box focused on load, and the route. Done means:
migration runs and the page saves a note. No tags yet.
"No tags yet" matters. Small slices keep every diff reviewable; Chapter 5 adds tags against a schema that already exists. Elyra works through the files and you watch every diff as it lands.
The edit loop that checks itself
Here's where the LSP extensions from Chapter 2 earn their
install. Watch what comes back from a single edit to
NoteController.php:
edit app/Http/Controllers/NoteController.php
Successfully replaced 1 block(s).
[Diagnostics — auto-checked via LSP]
1 error in this file after the edit:
- app/Http/Controllers/NoteController.php:24:16: Undefined
method 'Note::create'... did you forget the $fillable
property on the model?
[Related symbols — auto-resolved via LSP]
- Note: class App\Models\Note
The agent sees the error in the result of its own edit — before it says "done", before you run anything. The next thing it does, unprompted:
edit app/Models/Note.php
Successfully replaced 1 block(s).
[Diagnostics — auto-checked via LSP]
(no errors)
That round trip you used to pay for — run, 500, paste, apologize — happened internally, in one turn. This isn't a party trick; it's the compounding difference between an agent you babysit and one you supervise.
Blast radius: seeing the ripples
Later in the session you rename store()'s
validation rules into a FormRequest. The edit result
includes one more section:
[Blast radius — auto-resolved via LSP]
store is referenced in 2 places outside this file:
- routes/web.php:14
- tests/Feature/ExampleTest.php:9
Two call sites, listed the moment the signature changed.
The agent updates the route without being told, and
flags the test file. When you want the same
superpower explicitly, the LSP tools are yours too
— ask "who calls store?" and the agent uses
php_references instead of grepping and
hoping.
Close the loop the way Chapter 2 taught: verify, then commit.
> Run the migration, then verify: php artisan tinker to create
a note through the model. Then commit as
"feat: note capture (migration, model, controller, page)"
What you learned
-
/pinthe contract (SPEC.md), not the code. Pinned files survive compaction and anchor every turn. - Prompt shape: scope + constraints + definition of done. "No tags yet" is as important as what you do ask for.
- The edit loop checks itself. Auto-diagnostics surface errors in the edit's own result; the agent fixes them before claiming done.
- Blast radius makes signature changes safe. Call sites are listed the moment they are affected — no forgotten route files.
- One feature slice, one commit. Reviewable diffs beat heroic ones.