Door ·

Specs voor agents verdienen een editor die rendert

Specs voor agents verdienen een editor die rendert

Het grootste deel van mijn werkdag is een 13-inch scherm met een markdownbestand aan de ene kant en een terminal aan de andere. Er draait een agent in de terminal. Het markdownbestand beschrijft wat die agent moet bouwen. Het is geen notitie, het is de input, en mijn teksteditor gaat ervan uit dat er later een mens proza leest.

Een spec- of contextbestand dat ik voor een agent schrijf, staat dichter bij een programma dan bij een essay, en daarom wil ik dat de editor de structuur rendert in plaats van me sterretjes te tonen.

Ik probeerde eerst de officiële Milkdown-extensie voor VS Code, omdat ik Milkdown al prettig vond en het ook de editor in de CMS van mijn blog is. Markdown rendert hij netjes. Wat hij niet doet, is passen: er staat 120px padding aan elke kant van de tekst, bemeten zoals een documentatiesite bemeten is. De helft van een 13-inch scherm laat een kolom over die zo smal is dat een tabel midden in een woord afbreekt en een kop over drie regels loopt. Dus forkte ik hem.

Wat ik in deze bestanden schrijf

1.00

Een nieuw agentic project van mij begint met een corpus, niet met code. Eén hoofddocument dat zegt wat het project moet doen, en dan subfolders met documenten die zeggen wat elke module of elk systeem erin moet doen. De verdeling is niet gelijk. Ik kies de paar pijlers die echt menselijke sturing nodig hebben en schrijf die goed uit, want dat zijn de plekken waar een agent die aan zichzelf overgelaten is het verkeerd raadt op manieren die een dag kosten. Al het andere krijgt een korte notitie en ruimte om te bewegen.

Drie eigenschappen volgen uit die manier van schrijven:

  • De agent leest per taak een stuk van het corpus, niet het geheel, dus de structuur van de documenten wordt uiteindelijk de structuur van het werk.

  • Het document overleeft het gesprek. Een chatcontext is tegen de volgende sessie verdwenen; een specbestand staat morgen op schijf, en daar wordt de volgende sessie naartoe gestuurd.

  • Ik kan een spec reviewen zoals ik code review, omdat de structuur zichtbaar is. Een document van 200 regels met vier koppen en een tabel leest anders wanneer de tabel een tabel is.

Wat Milkpad is

Een fork van Milkdown VSCode, gepubliceerd als Milkpad, met de editor-engine eronder ongemoeid gelaten. De CMS van mijn blog draait op dezelfde engine, wat toeval is en niet de reden: ik vond het al prettig hoe Milkdown schrijft, en de fork bestaat omdat de extensie eromheen niet paste in het paneel waar ik werk. Vier dagen werk, 54 commits, de meeste gemaakt met agentic coding tools. De wijzigingen zijn de visuele laag, plus het renderen van raw HTML die de engine anders als tags afdrukt. De source staat op GitHub.

Drie beslissingen en wat ze kosten

Laten passen in het paneel

De engine blijft ongemoeid en het sleutelen gebeurt in de getallen eromheen: content padding opgesplitst in een linker- en een rechterwaarde (44px en 8px, omlaag van 120px aan elke kant), vier knoppen voor de maat van koppen, broodtekst, de zwevende toolbar en de block handle, en een block handle die verticaal gestapeld is zodat hij één knop breedte kost in de kantlijn in plaats van twee.

Wat dat kost: het upstream thema zit vol hardcoded px en nergens rem, dus er is geen root font size om aan te draaien en elke maat die moet veranderen wordt met de hand opgesomd. Die lijst is nu van mij, en hij groeit niet vanzelf mee wanneer de engine iets nieuws uitbrengt. De linker padding heeft ook een ondergrens, want de block handle staat in de kantlijn links van een blok, en onder ongeveer 44px valt hij buiten de rand van het paneel met niets meer om vast te pakken.

Markup renderen

1.00

Sommige van mijn bestanden bevatten markup en geen markdown: een strook avatars, een kleine tabel, een badge. Milkdown behandelt raw HTML als tekens, dus die bestanden lieten me tags zien waar een afbeelding had moeten staan, en markup die ik niet kan zien is markup die ik niet kan controleren. De fork tekent het als markup, met een edit box achter elk blok die de source toont en wijzigingen aanneemt terwijl je typt.

Wat dat kost: op het moment dat een editor tekent wat een bestand ook bevat, is dat bestand untrusted input. Een markdownbestand kan overal vandaan komen, en een image tag met een error handler erin zou binnen de editor uitgevoerd worden. Dus alles wat uitvoerbaar is wordt eruit gestript voordat het gerenderd wordt, en de hele editor draait onder een content security policy die helemaal geen netwerkverzoeken toestaat. Een sanitiser en een policy zijn nu mijn verantwoordelijkheid, wat meer oppervlak is dan ik me had voorgenomen te onderhouden. Eén limiet heb ik niet opgelost: een bold tag midden in een zin styleert niets, want een raw tag staat op zichzelf als zijn eigen node en alleen een paragraaf die volledig markup is wordt weer tot één blok samengevoegd.

Wat renderen verbergt

Dit is de helft die me iets kost. Zodra een document rendert, is de syntax die het maakt niet meer zichtbaar, dus een bestand dat ik bewerk wordt terug opgeslagen in de gewoontes van de editor en niet in de mijne: lijstpunten worden sterretjes, een reeks lege regels klapt samen tot één, een kaal webadres krijgt punthaken eromheen. Het rendert allemaal hetzelfde. De diff van een bestand dat ik heb aangeraakt is echter niet alleen mijn wijziging.

De minder flatteuze kanten

1.00

Er bestaat geen testsuite. CI controleert formatting, lint en types en bouwt daarna de package, dus wat gecontroleerd wordt is stijl, en niets verifieert gedrag.

Niemand anders dan ik heeft het gebruikt. Het staat sinds vanmorgen op de Marketplace, dus dit is een post van de eerste dag: geen issues aangemaakt, geen tweede installatie, niets voorbij mijn eigen gebruik. Alles wat ik zeg over de setup van iemand anders is een gok.

Een deel van wat het adverteert kwam gratis mee met de engine. De featurelijst dekt volledige GFM-ondersteuning en wiskundeondersteuning, onder andere, en ik heb die lijst niet item voor item nagelopen.

Eén fix erin zit in een patch op een dependency, met niets in mijn source om het te laten zien. Het image block bewaart drie dingen in de twee velden die markdown biedt, dus het schrijft de beeldverhouding in de alt-tekst en leest de verhouding er weer uit, en het opslaan van een document verving daardoor echte alt-tekst door een getal. De eerste keer dat ik opsloeg veranderde “profile picture of Saul Mirone” in “1.00”. Dat goed repareren betekende de dependency patchen, en de patch is met opzet aan één versie vastgezet, dus de volgende upgrade van dat package stopt de installatie in plaats van de fix geruisloos te laten verdwijnen. Een gestopte installatie is de fout die ik daar wil, al betekent het wel dat onderhoud zich zal aandienen als een gebroken build.

En de kleine die blijft bijten: mijn eigen README in Milkpad bewerken herschrijft de lijstmarkeringen, mijn CI controleert formatting, dus twee commits in die repository bestaan alleen om de formatter over een bestand te draaien dat de editor had opgeslagen.

Op dit moment

Het is mijn default, geïnstalleerd als de editor voor markdown, en er komen wijzigingen naarmate bugs en verbeteringen opduiken. Er staat vandaag niets op die lijst, wat ik lees als een goed teken en niet als een teken dat het af is. Ik hoop dat mensen het gebruiken, en het net zo goed vinden als ik het vind.

Als je specs of contextbestanden voor agents in markdown schrijft, dan is wat deze week de moeite waard is om te proberen niet een ander model. Open een van die bestanden ergens waar het rendert. Het corpus en het renderen zijn twee losse beslissingen, en de tweede heeft geen fork nodig. Als je degene wilt die ik uiteindelijk heb, hij staat op de Marketplace.

Wat overdraagbaar is

1.00

Wanneer het schrijven de input voor een machine is, wordt het schrijfoppervlak onderdeel van de toolchain. Niemand reviewt code in een editor die zijn structuur verbergt, en een document dat een agent leest verdient dezelfde behandeling. Dat is hier voor mij opgehouden abstract te zijn: ik forkte een editor omdat 120px padding aan elke kant niets leesbaars overliet naast de terminal, en de nuttige helft van het resultaat was de structuur van het bestand zien, niet de tekst mooier maken.

Lees ook