The Grammar Ships: .sil Syntax Highlighting for VS Code
Syntax highlighting for .sil files started as a GitHub issue. Someone from the VS Code extension community found it within 24 hours. What the grammar reveals is more than aesthetic — each colour layer maps to a distinct semantic layer of the EMBER format.
Fifteen Files in a Finder Window
At the A-03 review gate, the pipeline has produced fifteen .sil artifacts. Signals, workflow traces, screen traces, specs. Each one is a plain text file. Each one is readable. None of them is scannable.
Your eye has no anchor. A signal and a spec are the same visual weight. The field key intent: and the value it introduces look identical. The separator line is the only break, and even that is just characters. You're reading, not browsing. With fifteen files, reading is the slower mode.
The fix was one GitHub issue and twenty-four hours.
One Issue, One Day
Issue #8 on the phoenix-runtime repository: “.sil syntax highlighting.” Scope: TextMate grammar only, no LSP, no validation. Just colour. Makes reading a specs/ directory substantially easier.
Twenty-four hours later, RedCMD commented. RedCMD builds tooling specifically for TextMate grammar authors — their tmlanguage-syntax-highlighter extension gives you autocomplete, validation, error diagnostics, and call hierarchy while authoring grammars. They found the issue through search. They're exactly the kind of person who would.
The extension shipped to the VS Code Marketplace the same day. That's open source working.
What the Grammar Targets
A TextMate grammar assigns scope names to matched patterns, and those scope names map to colours in your theme. The question the grammar has to answer is: what patterns in a .sil file are semantically distinct?
The answer is five layers. Here's a spec file with all five visible:
CONSTRUCT spec
ID cart.checkout
VERSION 1
─────────────────────────────────────────
intent:
Allow a customer to purchase items in their cart
and receive order confirmation
journey:
Cart review → Shipping → Payment → Confirmation
rules:
- Charge must succeed before order is created
- Guest checkout allowed — login not required
confidence: highCONSTRUCTHeader keywordspec signal episodeConstruct typeID VERSION → :Operatorscart.checkoutArtifact identifier─────────────────────────Separatorintent: rules: journey:Field keyshigh open certifiedConstantsFive layers, five distinct visual registers. When you open a directory with fifteen artifacts, your eye now has anchors. The amber field keys scan differently than body text. The construct type — spec, signal, episode — is visible before you read the ID.
Across the Nine Constructs
EMBER has nine construct types. Each one sits at a different position in the pipeline and carries different fields. The grammar handles all nine with the same rules — because the header structure is identical across every construct.
CONSTRUCT signal
ID cart.checkout
VERSION 1
─────────────────────────────────────────
type: workflow
entry: POST /cart/submit
entities: Cart, Order, Payment, User
boundary: Stripe, SendGrid, PostgreSQL
confidence: high
notes: High abandonment reported at payment stepCONSTRUCT episode
ID ep-042
VERSION 1
─────────────────────────────────────────
date: 2026-03-15
status: open
trigger: client requirement change
change:
Add guest checkout — purchase without login required
affects:
A-01 → add guest.checkout workflow
A-03 → update spec — guest vs authenticated intent
A-05 → new UI pass and API route for guest flow
skip:
A-00 → brief unchanged
A-04 → stack unchangedCONSTRUCT certification
ID cart.checkout
VERSION 1
─────────────────────────────────────────
result: certified
coverage: full
verified:
- Charge before order creation — confirmed
- Guest checkout path — confirmed
- Promo applied before total — confirmed
notes:
All rules from spec verified in build pass 4The signal and the certification are the bookends — first and last artifacts in the pipeline. With the extension installed, you can tell them apart in a directory listing from the construct type alone, before reading a single field.
What the Grammar Proves
A TextMate grammar only works meaningfully if the tokens it highlights are actually distinguishable. If EMBER had blurry boundaries — if field keys looked like body values, or header keywords could appear in the body — the grammar would produce false positives and missed tokens.
The grammar works cleanly. That's not a statement about the extension. It's a statement about the format.
The header is guaranteed to be three lines of a specific structure. The separator is a unique Unicode character sequence ─ (U+2500), not ASCII hyphens. Field keys always match /^[a-z][\w-]*:/ and always appear at the start of a line. Status and confidence values are a closed vocabulary. The arrow → is a single Unicode character, unambiguous in every context.
Every layer the grammar highlights is a layer the format was designed to carry. The colours don't decorate the structure. They reveal it.
Install
The full EMBER language reference — constructs, fields, design decisions — is at EMBER: A Language Designed for the Third Reader.