Ovo je osobna bilješka o tome kako organiziram AI-assisted delivery u svom radu u Tiltu. Opisuje moj način rada, a ne službenu Tilt politiku, obvezu prema klijentu ili obećanje da se svaki projekt može završiti preko noći.
Riječ overnight lako stvori pogrešnu sliku. Ne znači ostaviti autonomnom sustavu neograničen pristup i ujutro se vratiti na produkcijski release.
Moj sigurni default je uži: pripremiti jasno definiran rez posla, dopustiti da se ograničena implementacija i provjera nastave dok nisam za računalom te se vratiti promjenama spremnima za ljudski review. Merge i deploy su zasebni ishodi. Događaju se samo kada ih scope i autorizacija izričito uključuju.
Laptop može nastaviti raditi nakon što prestanem tipkati. Odgovornost ne ide spavati.
Noć počinje definicijom gotovog
“Isporuči ovo preko noći” nije korisna uputa. Prije početka određujem što delivery znači za konkretan scope:
- merge request spreman za review;
- niz ovisnih merge requestova;
- mergane promjene iza isključenog feature flaga;
- ili, puno rjeđe, deployano i provjereno okruženje.
Review-ready je default jer stvara koristan napredak bez tihog širenja ovlasti. Ako produkcijska promjena nije izričito dopuštena, workflow mora stati prije produkcije.
Zapisujem i cilj, mjeru uspjeha, non-goals, ovisnosti i acceptance kriterije. Ticket koji opisuje samo željeno sučelje ili rezultat još nije plan za overnight delivery. Treba odgovoriti i na pitanja poput:
- Koji su repozitorij i base branch mjerodavni?
- Mora li neka druga promjena biti mergana prije ove?
- Postoji li migracijska ili kompatibilnosna granica?
- Koji dio traži produktnu odluku, a ne implementaciju?
- Koja se provjera može izvršiti automatski, a koja mora čekati čovjeka?
- Koji uvjet treba zaustaviti rad čak i ako je moguća daljnja implementacija?
Većina overnight problema počinje prije prve izmjene datoteke. Sustav je dobio ambiciju umjesto delivery ugovora.
Discovery dolazi prije implementacije
Prije delegiranja koda pregledavam dostupni produktni materijal, aktualne tickete, povezani rad, otvorene reviewove i stvarno stanje repozitorija.
Cilj nije učitati svaki dokument u jedan golemi kontekst. Cilj je pronaći kontradikcije dok su još jeftine:
- dva ticketa koja različito opisuju istu promjenu;
- specifikaciju koja pretpostavlja stari API ugovor;
- ovisnost koja još čeka review;
- ručnu ili komercijalnu vrijednost koju software ne smije izmišljati;
- rollout korak koji nije moguće lokalno provjeriti;
- sigurnosno ili privacy pitanje koje traži ljudsku odluku.
Ako je posao prevelik, dijelim ga prema neovisno provjerljivim ishodima, a ne prema proizvoljnim tehničkim slojevima. Mali vertikalni rez s vlastitim acceptance dokazom ujutro je korisniji od tri napola završena brancha nazvana backend, frontend i testovi.
Tilt tool loop
Workflow je najlakše objasniti kroz alate koje koristim u Tiltu.
- Linear čuva product i delivery stanje: cilj, scope ticketa, ovisnosti, komentare, acceptance kriterije i aktualni status.
- GitLab čuva source istinu: repozitorije, brancheve, merge requestove, reviewove i CI. Koristim
glabkada run treba svjež command-line pregled tog stanja. - Slack služi za vremenski osjetljivu koordinaciju, pitanja o blokerima i sažeti jutarnji handover. Pomaže ljudima reagirati, ali ne zamjenjuje ticket ili commitanu dokumentaciju kao trajni izvor.
- Cursor Agent izvršava ograničeni lokalni implementacijski rad. Svaki kasniji ticket počinje u svježoj sesiji kako bi se aktualni repozitorij i upute ponovno pročitali.
- Amphetamine drži autoriziranu lokalnu Mac sesiju uključenom i budnom preko noći. Rješava dostupnost računala, a ne ispravnost softwarea.
- Sentry i Grafana daju runtime dokaze kada scope traži operativnu provjeru i pristup je autoriziran. To su opcionalni ulazi, a ne razlog da se delivery proširi na produkciju.
Podjela je namjerna. Linear govori što se treba dogoditi. GitLab pokazuje što postoji i prolaze li provjere. Slack drži ljude povezanima. Runtime monitoring pokazuje što je software stvarno napravio. Nijedan alat ne može tiho dodijeliti ovlast koja nedostaje u drugom sloju.
Svjež kontekst sigurniji je od zapamćenog
Za svaki neovisan ticket ili rez krećem sa svježim radnim kontekstom.
Worker čita aktualni ticket, commitana pravila repozitorija i relevantne specifikacije, zatim prije planiranja dohvaća trenutačno remote stanje. Stari razgovor može pružiti povijest, ali ne smije nadjačati živi repozitorij ili aktualne upute.
To je važno jer memorija agenta zvuči mjerodavno čak i kada je zastarjela. Thread se može jasno “sjećati” funkcije, migracije ili produktne odluke koja se promijenila nekoliko sati ranije.
Svježina je zato inženjerska kontrola:
- izričito odabrati namijenjeni repozitorij i base branch;
- napraviti fetch prije planiranja i ponovno prije otvaranja merge requesta;
- trajna pravila držati u version controlu;
- zapamćeno stanje tretirati kao hipotezu dok ga repozitorij ne potvrdi;
- nakon velike promjene scopea ili ponovljene zabune prijeći na svježeg workera.
Cilj nije thread koji pamti sve. Cilj je worker koji može rekonstruirati činjenice potrebne za jednu ispravnu isporuku.
Svaki writer mora biti izoliran
Overnight paralelizam postaje opasan kada nekoliko workera dijeli jedan promjenjivi checkout.
Koristim izolirane worktreeove i fokusirane brancheve kako bi svaki writer imao jasnu granicu. Ovisnosti i merge redoslijed određuju se prije implementacije, a ne nakon što dva brancha isti ugovor izmijene na različite načine.
Promjene trebaju ostati aditivne gdje god je moguće. Rizično ponašanje počinje isključeno, novi ugovori failaju closed, a worker ne smije širiti vlastite ovlasti zato što bi šira promjena bila praktična.
To je posebno važno kada projekt obuhvaća više repozitorija. Relevantni repozitoriji mogu biti dostupni za čitanje, ali jedan zadatak i dalje treba jasno definiran write scope. “Možeš ga vidjeti” nije isto što i “smiješ ga mijenjati”.
Loop od šest faza
Stvarni run organiziram kroz šest faza.
1. Refresh
Pročitati aktualni ticket, specifikacije, otvorene reviewove i commitane upute. Dohvatiti zadnje remote stanje i identificirati povezane repozitorije bez pretpostavke da su nepromijenjeni.
2. Plan
Prije izmjena navesti ovisnosti, merge redoslijed, acceptance kriterije, feature-flag politiku, ručne gateove i stop uvjete.
3. Implement
Raditi u izoliranom branchu. Zadržati promjenu unutar scopea, očuvati kompatibilnost i zapisati svaku pretpostavku koju nije bilo moguće provjeriti.
4. Verify
Pokrenuti relevantni formatter, statičke provjere, testove i build. Dodati neovisan review kada rizik to opravdava. Pratiti CI i riješiti review nalaze umjesto da se otvoreni merge request tretira kao završetak.
5. Hand over
Vratiti čistu površinu za review: što je promijenjeno, koje su provjere prošle, merge redoslijed, rollout stanje, preostale blokere i točne akcije koje čovjek još mora izvršiti.
6. Clean up
Ukloniti završene worktreeove tek nakon što je branch objavljen, CI zelen i handover dovršen. Cleanup je provjereno završno stanje, a ne automatski korak brisanja.
Redoslijed je namjerno običan. Overnight delivery postaje pouzdan kroz discipliniranu software praksu, a ne kroz dramatičniji prompt.
Orkestrator ne smije postati implementer
Kod veće isporuke jedan dugotrajni kontekst posjeduje graf ovisnosti i projektni manifest. Prati aktivne brancheve, reviewove, CI stanje, blokere i cleanup. Ograničenu implementaciju delegira svježim workerima.
Orkestrator ne piše svaku promjenu. Ako preuzme implementaciju, s vremenom skuplja previše statea, postaje writer u konfliktu i gubi neovisan pogled potreban za koordinaciju isporuke.
Kada je rizik značajan, review kontekst također odvajam od implementacijskog. Svjež reviewer lakše uočava pogrešnu pretpostavku od workera koji je proveo sate čineći pristup interno konzistentnim.
Dugotrajni konteksti imaju signale za rotaciju. Čista granica faze nakon context compactiona dobar je trenutak za handover. Novi ticket, promijenjen base branch, ponovljena istraga ili neuspjeli pokušaji još su jači signal za svjež početak.
Stop uvjeti dio su isporuke
Overnight workflow treba eksplicitne razloge za zaustavljanje.
Moji uključuju:
- nejasnu produktnu odluku;
- nedostajuće pristupe, dozvole ili komercijalne vrijednosti;
- neplaniranu breaking promjenu;
- destruktivne operacije nad podacima ili infrastrukturom;
- izlaganje produkcije izvan odobrenog ishoda;
- ovisnost čije se aktualno stanje ne može provjeriti;
- bilo koju akciju izvan autoriziranog scopea.
Zaustavljanje jednog blokiranog brancha ne znači da svaki siguran zadatak mora stati. Neovisna dokumentacija, testovi ili review mogu se nastaviti ako im scope ostaje jasan.
Važno je da sustav ne pretvori nedostatak ovlasti u pretpostavljenu odluku. Koristan jutarnji handover može reći: “Implementacija je spremna, ali ove dvije odluke još traže čovjeka.” To je uspješna isporuka.
Što želim vidjeti ujutro
Idealan rezultat nije poruka gotovo.
Želim sažet delivery manifest:
- svaku promjenu i link za review;
- planirani redoslijed ako promjene ovise jedna o drugoj;
- rezultate provjera i CI-ja;
- neriješene review nalaze;
- rollout ili feature-flag stanje;
- blokere i pretpostavke;
- točne ručne akcije koje još treba izvršiti;
- potvrdu da je lokalni rad sačuvan ili sigurno očišćen.
Tako jutarnji review postaje konačan zadatak. Ne moram rekonstruirati što se dogodilo iz nekoliko dugih razgovora niti pregledavati svaki branch samo da bih otkrio preskočenu odluku.
Što overnight delivery stvarno kupuje
Korist nije u tome da osam sati proteklog vremena postane osam sati senior inženjerske prosudbe. Ne postane.
Korist je u tome da se jasno definiran mehanički i analitički rad može nastaviti između dviju ljudskih odluka: čitanje repozitorija, ograničena implementacija, testovi, buildovi, neovisne provjere, priprema reviewa i prikupljanje dokaza.
To mijenja način na koji koristim sljedeće jutro. Umjesto ponovnog kretanja od ticketa mogu pregledati konkretne trade-offove i provjerene promjene.
U Tiltu je to standard koji koristim za overnight AI-assisted rad: ograničiti ovlasti, osvježiti činjenice, izolirati writere, provjeriti rezultat i učiniti svaku preostalu ljudsku odluku vidljivom.