← Wstecz Harupa
2026-06-29RU EN UA BY PL

My Architect, część 8: Event Storming — kontrola sekwencji, a nie kolejny diagram

To ósmy artykuł serii o My Architect. Dla tych, którzy nie czytali wcześniejszych części, w skrócie: My Architect to system, w którym projekt żyje między sesjami agenta AI. Jedną stroną zwrócony jest do agenta — to on prowadzi projekt przez MCP; drugą do człowieka — wizualny interfejs pokazuje, co agent już zrobił, i cały postęp projektu. Ten artykuł dotyczy jednego konkretnego mechanizmu tej kontroli.

Witryną jest tu Forklift, średniej wielkości domena dostawy jedzenia złożona z pięciu bounded-kontekstów. Wszystkie tablice, liczby z analizatora i fragmenty DSL poniżej są prawdziwe: projekt został zasiany lokalnie i przechodzi przez realny analyzeEsSequence. Nic nie jest zmyślone.

Diagram dla samego diagramu jest bezużyteczny. Kontrola sekwencji — nie

Wszyscy mamy ten cmentarz. Folder docs/architecture, gdzie leżą ładne PNG narysowane pół roku temu, i żaden już nie odpowiada kodowi. Diagram-obrazek to zrzut czyichś dobrych intencji w chwili T. Niczego nie sprawdza. Nie wie, że zapomniałeś podłączyć gałąź anulowania. Radośnie pokaże strzałkę, której w kodzie nie ma, i przemilczy piętnaście, które są.

Dlatego kiedy mówię „agent rysuje tablicę Event Storming”, słusznie drga ci powieka. Kolejny obrazek? Nie. Różnica tkwi w jednym słowie: sekwencja.

Event Storming to nie diagram pudełek. To rozłożona w czasie historia tego, jak zdarzenie rodzi reakcję, reakcja — komendę, komenda — nowe zdarzenie. Zdarzenie domenowe („Zamówienie złożone”) ma przyczynę. Komenda („Złóż zamówienie”) ma rezultat. Polityka („Gdy tylko płatność autoryzowana → potwierdź zamówienie”) to most między czyimś zdarzeniem a twoją komendą. I właśnie ta własność — wszystko ma przyczynę i skutek — zmienia się z ładnej filozofii w maszynowo sprawdzalny inwariant.

Jeśli zdarzenie wisi bez przyczyny — to luka. Jeśli komenda nie rodzi zdarzenia — luka. Jeśli polityka niczego nie mostkuje — luka. Jeśli karta jest izolowana — ktoś naszkicował myśl i jej nie dokończył. Tych luk nie widać okiem na tablicy z czterdziestu karteczek. Ale widzi je analizator, który czyta graf sekwencji.

Witryna jest apetyczna — Forklift: on-demand food delivery, from tap to doorstep. Pięć bounded-kontekstów: Ordering, Payments, Kitchen, Dispatch, Tracking. Dokładnie ta klasa domeny, gdzie „zapomniałem podłączyć gałąź” kosztuje realne pieniądze: jedzenie ugotowane — pieniędzy nie pobrano; kuriera nie przydzielono — klient się skarży.

Forklift — tablica Dispatch / Delivery Kontekst Dispatch: komendy (niebieskie) → zdarzenia (pomarańczowe), polityki-mosty (liliowe), read-modele (zielone), systemy zewnętrzne (różowe), aktorzy (żółci) i otwarte pytania — hotspoty (romby) na dole.

Dlaczego daje to dźwignię właśnie agentowi

Człowiek patrzy na tablicę i czuje, że czegoś brakuje. Czasem znajdzie. Częściej — nie: uwaga się nie skaluje, przy trzydziestej karcie już nie pamiętasz, czy domknąłeś wynik komendy „Odrzuć zamówienie”.

Agent nie czuje. Agent uruchamia deterministyczne sprawdzenie grafu. analyzeEsSequence przechodzi graf przyczynowo-skutkowy tablicy i zwraca ustrukturyzowany werdykt: ok, listę gaps z typem (isolated, event-without-cause, command-without-effect, policy-not-bridging) i poziomem (warning / info), a osobno — openQuestions (karty-hotspoty).

To właśnie jest dźwignia. Agent dostaje pętlę sprzężenia zwrotnego, która nie kłamie i się nie męczy:

  1. Author — agent autoruje tablicę przez create_diagram(diagramType:'event-storming', nodeId), przypinając ją do węzła hierarchii (epiku/inicjatywy).
  2. Validate — czyta przez get_diagram; pole sequence pokazuje luki w historii.
  3. Refine — naprawia przez update_diagram i waliduje ponownie, aż gaps zwinie się do zera.
  4. Re-validate during implementation — w trakcie realizacji ponownie uruchamia sprawdzenie: kod rozjechał się z historią → tablica znów czerwienieje.

Agent nie próbuje być sprytny „na oko”. Opiera się na tanim deterministycznym sprawdzeniu i iteruje do zielonego — dokładnie tak, jak iteruje testy.

Pętla w akcji: Ordering, od czarnego szkicu do czystej historii

Najpierw agent naszkicował v0 kontekstu Ordering — uczciwy szkic, jaki rzuca żywy człowiek: chwycił główną nić, zaznaczył „tu wróci odpowiedź z Payments” — i nie dokończył ogona.

event-storming
# фрагмент: показана только основная нить Ordering, на доске карточек больше

group "Ordering"
  [command] "Place order"
  [event]   "Order placed"
  [policy]  "Whenever Payment authorized → Confirm order"
  [command] "Confirm order"
  [event]   "Order confirmed"
  [command] "Cancel order"

connect "Place order" -> "Order placed"
# "Whenever Payment authorized → Confirm order" — ни к чему не подключена  (isolated policy)
# "Cancel order" — ни входящего, ни исходящего                            (isolated command)
# "Order confirmed" — без входящей причины                                (event-without-cause, info)

Agent czyta get_diagram, przepuszcza przez analizator i dostaje dla v0:

27 cards · 19 connections · 1 contexts — 2 sequence gap(s), 0 open question(s)
gaps:
  • "Whenever Payment authorized → Confirm order" (policy) is not connected to anything
  • "Cancel order" (command) is not connected to anything

Dwie luki-warning (izolowana polityka powrotu z Payments i niedomknięty ogon anulowania) plus jedna notatka info („Order confirmed” bez przyczyny — rodząca komenda nie domknięta). Dalej — refine: agent podłącza rodzącą komendę, mostkuje politykę w komendę potwierdzenia, domyka ogon anulowania zdarzeniem wynikowym. Ponowna walidacja v1:

34 cards · 30 connections · 1 contexts — 0 sequence gap(s), 3 open question(s)

Luki się zwinęły. Ale — i to jest istotne — tablica nie zrobiła się pusta i nie zaczęła kłamać „wszystko rozwiązane”. Zostały dokładnie trzy karty, które agent świadomie zostawił czerwone. O nich — niżej.

Ta sama pętla na Payments: gdzie szkic jest szczególnie niebezpieczny

Payments to kontekst, w którym niedociągnięta strzałka oznacza „jedzenie ugotowane, pieniędzy nie zdjęto” albo „pieniądze zdjęto dwa razy”. Tu v0 było dziurawe, i to normalne: właśnie dlatego sprawdzenie jest potrzebne.

Forklift — tablica Payments

Werdykt analizatora dla v0 Payments:

25 cards · 15 connections · 1 contexts — 3 sequence gap(s), 0 open question(s)
gaps:
  • "Issue refund" (command) is not connected to anything        — путь возврата нарисован наполовину
  • "Chargeback opened" (event) is not connected to anything     — забытая ветка отказа
  • "On decline cancel order" (policy) missing outgoing command  — мост к отмене брошен на шве

Po refine agent domyka ścieżkę zwrotu (Evaluate refund → Issue refund → Refund issued), domyka obsługę chargebacku i dobudowuje most polityki decline w Cancel order. Werdykt dla v1:

39 cards · 27 connections · 1 contexts — 0 sequence gap(s), 3 open question(s)

I znów — trzy karty zostają czerwone celowo (capture-vs-reject race, atrybucja winy przy zwrocie, właściciel liability przy chargebacku).

Pozostałe trzy konteksty: ten sam wzorzec

Pętla wszędzie jest ta sama. Co złapał analizator w v0 — i do czego zwinęło się w v1:

Kontekstv0 (luki)v1Co było zepsute w v0
Ordering2 →0izolowana polityka powrotu; niedomknięty ogon anulowania
Payments3 →0urwana ścieżka zwrotu; zapomniany chargeback; most decline na szwie
Kitchen5 →0Reject order/Order rejected osierocone; polityka szacowania czasu bez triggera; Start cooking bez zdarzenia; Cooking started izolowany
Dispatch4 →0Notify ops bez wyniku; polityka trackingu-sierota; Courier arrived/Delivery failed bez przyczyny
Tracking3 →0polityka powiadomień bez triggera; Recalculate ETA izolowana; polityka prośby o ocenę nie domknięta

Łącznie w projekcie: 17 mechanicznych luk złapanych i zamkniętych, 15 otwartych pytań świadomie zostawionych na widoku. Ani jednej zmyślonej liczby — to wynik realnego analyzeEsSequence po zasianych tablicach.

Co zostaje otwartymi pytaniami — i dlaczego to feature, a nie bug

Oto główna myśl. Kiedy gaps zwinęły się do zera, naiwny system uległby pokusie powiedzieć „architektura gotowa”. To byłoby kłamstwo. Różnica między luką a otwartym pytaniem jest fundamentalna:

Dlatego hotspoty to pełnoprawni obywatele tablicy. Przechodzą walidację (ok=true), ale zostają na widoku jako openQuestions. Tablica uczciwie mówi: „mechanicznie jestem spójna, ale te rozwidlenia czekają na człowieka”.

I najpiękniejsze: jedno pytanie biznesowe wypływa hotspotem z różnych stron szwu — to samo pytanie widać z kilku kontekstów naraz. To nie duplikacja, lecz mapa tego, kogo dotknie decyzja, gdy product owner ją w końcu podejmie:

Zielony analizator nie oznacza „decyzje podjęte”. Oznacza „historia jest mechanicznie spójna, a wszystkie nierozwiązane rozwidlenia są jawnie wyniesione na powierzchnię, a nie utopione w milczeniu”. To dokładnie ta granica, której chcesz między tym, co agent ma prawo dobudować sam, a tym, gdzie jest zobowiązany zawołać człowieka.

Artefakt: to nie obrazki, to działający projekt

Wszystko powyżej to nie makieta w edytorze graficznym. To zasiany projekt, który otwiera się w produkcie:

Forklift — tablica Ordering

Jak wypróbować samemu — już można

To nie „kiedyś zreleasujemy”. Cały toolchain jest zaktualizowany i dostępny od ręki:

Instalacja w Claude Code:

  1. Załóż konto na my-architect.app, weź token na stronie API Keys i wyeksportuj go w tej samej sesji, w której uruchamiasz Claude Code:

``bash export MCP_API_KEY=mcp_TWÓJ_TOKEN ``

  1. Dodaj marketplace i postaw plugin (serwer MCP podłączy się sam — npx -y @my-architect/mcp@latest, MA_API_URL=https://my-architect.app):

`` /plugin marketplace add d7561985/my-architect-marketplace /plugin install my-architect@my-architect-marketplace ``

  1. Daj agentowi epik albo inicjatywę i poproś o rozłożenie Event Storming — sam przejdzie pętlę create_diagram → get_diagram (sequence) → update_diagram do zielonego, zostawiając otwarte pytania jako hotspoty.

Masz już plugin? Zaktualizuj do świeżych narzędzi i reguły: /plugin marketplace update my-architect-marketplace/plugin update my-architect.

Wniosek: praktyka dla zespołów

Jeśli usunąć cały Forklift i zostawić sedno — działający przepis:

  1. Przestańcie traktować diagramy jak obrazki. Bierzcie format ze sprawdzalnym inwariantem. Event Storming ma go wbudowany: wszystko ma przyczynę i skutek.
  2. Zróbcie sprawdzanie sekwencji tanim i deterministycznym. analyzeEsSequence na tablicy to linter dla architektury. Luki (isolated, event-without-cause, command-without-effect, policy-not-bridging) to błędy kompilacji waszej historii.
  3. Dajcie agentowi pętlę, a nie jednorazowy przebieg. create_diagramget_diagram (validate) → update_diagram (refine) → re-validate podczas realizacji. Agent iteruje do zielonego tak samo, jak do zielonych testów — bez zmęczenia i bez „chyba wszystko podłączyłem”.
  4. Twardo oddzielajcie lukę od otwartego pytania. Lukę naprawia agent. Otwarte pytanie trzyma się hotspotem na widoku i czeka na człowieka. System maskujący to drugie jako pierwsze po cichu podejmuje decyzje biznesowe za was — najgorszy rodzaj długu technicznego.
  5. Przypinajcie tablicę do węzła hierarchii (epiku/inicjatywy), a nie do powietrza.

Najcenniejsze jest tu nawet nie to, że agent naprawia luki. Lecz to, że dokładnie wie, gdzie naprawiać nie wolno — i zostawia te miejsca czerwone, podpisane i widoczne. Architektura, która uczciwie mówi „tego jeszcze nie wiem”, jest warta więcej niż jakikolwiek ładny diagram udający, że wie wszystko.