My Architect, część 4: cykl pracy agenta
To czwarty wpis z serii o My Architect. W części 1 pokazałem cykl agenta w jednym bloku kodu i obiecałem rozłożyć go na czynniki pierwsze. Części 2 i 3 dotyczyły storage'u na plikach YAML i modelu planowania. Dziś sam cykl pracy: jak agent bierze zadanie, pracuje nad nim i zamyka je tak, żeby projekt pozostał żywym źródłem prawdy, a nie dziennikiem pisanym po fakcie.
Start sesji: jedno wywołanie zamiast streszczenia
Kiedyś każdą nową sesję zaczynałem od streszczenia: co zrobione, co ustaliliśmy, na czym stanęliśmy. Teraz to jedno wywołanie:
get_project_context({ pid })
→ meta + hierarchy + backlog + diagrams + stats
Agent dostaje całą hierarchię ze statusami, release'y i statystyki za jednym razem zamiast pięciu osobnych zapytań.
Zostaje pytanie, skąd agent zna pid. Hardkodować go w skillu nie można, skill jest uniwersalny. Dlatego zapisana jest w nim drabinka prób. Najpierw agent szuka w lokalnym CLAUDE.md projektu wzorca pid: "..." obok wzmianki o my_architect. Nie znalazł — wywołuje list_projects: jeśli projekt jest dokładnie jeden, to ten; jeśli jest ich kilka, agent pyta człowieka, a nie zgaduje. Jeśli projektów jest zero, agent proponuje scaffold_project, ale nie uruchamia go bez potwierdzenia. Założenie projektu to decyzja o zakresie, a nie rutyna.
Które zadanie wziąć
get_next_task wybiera zadanie według trzech reguł, w kolejności priorytetu: najpierw najwcześniejszy release, w obrębie release'u najgłębszy poziom drzewa, a przy remisie — alfabetycznie po nazwie. Węzły ze statusem done i cancelled odpadają od razu, węzły bez release'u trafiają na koniec kolejki.
Przed sortowaniem jest jeszcze jeden filtr: jeśli wśród kandydatów są liście, czyli węzły bez dzieci, wybór odbywa się tylko spośród nich. To właśnie leaf-first, a powód jest czysto praktyczny. Węzła-rodzica w rodzaju „Auth flow" nie da się zrobić jako osobnego zadania — zamyka się wtedy, gdy zamknięte są wszystkie jego dzieci. Jeśli agent weźmie rodzica bezpośrednio, spróbuje zrobić kilka rzeczy za jednym podejściem i rozmyje pracę. Liść jest atomowy: jedno podejście, jeden commit, czytelne kryteria odbioru. A rodzice zamkną się sami, kaskadowo — o tym niżej.
Alfabet na trzecim miejscu daje determinizm. Ten sam backlog zawsze zwraca to samo zadanie, więc zachowanie agenta da się przewidzieć i zweryfikować.
Cykl zadania
Pełna sekwencja wygląda tak:
get_next_task({ pid }) → zadanie ze ścieżką i kontekstem rodziców
start_task({ pid, nodeId }) → in-progress, assignee: agent
get_node → get_doc → czytamy dokumentację węzła PRZED kodem
... praca; update_doc na bieżąco, build_hierarchy
jeśli wypłynął dodatkowy podział ...
validate_project({ pid }) → naprawiamy wiszące referencje
complete_task({ pid, nodeId, summary })
→ done, kaskada w górę po przodkach,
w odpowiedzi od razu następne zadanie
Najciekawsze jest tu complete_task. Przed aktualizacją robi snapshot całego łańcucha przodków, ustawia węzłowi status done, zapisuje summary i porównuje statusy przodków przed i po. Jeśli właśnie zamknęło się ostatnie zadanie feature'a, feature przeszedł w done automatycznie, a agent widzi to w odpowiedzi jako jawną listę: który węzeł, jaki status był, a jaki jest teraz. Tam też leży next_task — osobne wywołanie po następne zadanie nie jest potrzebne, cykl domyka się sam.
Jeśli zadanie utknęło na zewnętrznej przeszkodzie, jest block_task z obowiązkowym powodem. Powód zapisuje się w węźle i na kanwie człowiek widzi nie anonimowy czerwony prostokąt, tylko konkretne „czekamy na klucze od dostawcy płatności".
Dokumentacja aktualizowana na bieżąco, a nie po fakcie
Na węzłach wiszą dokumenty markdown i mają jedno zadanie: opisywać, jak feature działa teraz. Nie jak był planowany i nie jak powinien był działać. Dlatego w skillu zaszyta jest twarda reguła: wziąłeś zadanie — najpierw przeczytaj dokumentację węzła, prawda o feature jest tam, a nie w nazwie. Zrozumienie zmieniło się w trakcie pracy — update_doc od razu, w tym samym ruchu.
Węzeł albo dokumentacja, które kłamią, są gorsze niż ich brak.
Przed zamknięciem zadania agent musi przepuścić validate_project. Walidator zwraca listę problemów z typem i wagą: wiszące referencje do dokumentów i diagramów, cykle w hierarchii, zgubieni rodzice. Zepsute referencje w źródle prawdy to nie kosmetyka, więc bez czystego przebiegu complete_task nie jest wywoływany.
„Dokończymy później" już nie ginie
Każdy agent w trakcie pracy zostawia ogony: „to pokryjemy testami później", „retry na razie niepodpięte", „przy wzroście obciążenia trzeba będzie cache'ować". Na czacie te zdania umierają razem z sesją. W My Architect reguła jest inna: każdy taki ogon staje się węzłem przed końcem bieżącego ruchu.
Gdzie dokładnie trafi, decyduje rubryka ze skilla. Dług techniczny dopiero co zamkniętego feature'a agent zapisuje po cichu: ten sam epic, ten sam release, prefiks w rodzaju tech-debt:. Usprawnienie z jawnym triggerem („kiedy pojawią się płacący użytkownicy", „jeśli odsetek false positives przekroczy pięć procent") też zapisuje bez pytań, ale do przyszłego release'u i z triggerem wprost w opisie, żeby potem było jasne, kiedy węzeł „odpala". Za to pytania strategiczne — czy feature jest w ogóle potrzebny, czy nie zmienić defaultów, czy nie wciągnąć nowej zależności — agent musi zatrzymać i oddać człowiekowi, pokazując warianty umiejscowienia wraz z trade-offami.
Przy wątpliwościach skill każe „lenić się w stronę pytania": trzydzieści sekund potwierdzenia jest tańsze niż węzeł, który miesiąc później wypłynie w niewłaściwym release'ie. A przed utworzeniem zawsze idzie sprawdzenie duplikatów po już załadowanym kontekście, bo duplikat w backlogu psuje priorytetyzację get_next_task: przy leaf-first i alfabecie kopia może wyprzedzić prawdziwą pracę.
Zestawienie planu z kodem
Plan ma to do siebie, że dryfuje od codebase'u: coś zrobiono poza trackerem, coś zamknięto i zapomniano odhaczyć. Do tego służy slash command /my-architect:reconcile. Agent przechodzi po wszystkich węzłach draft, zaczynając od najbliższego release'u, i dla każdego sprawdza po kodzie, czy to już przypadkiem nie jest wdrożone: szuka route'ów, komponentów, testów i je czyta. Co potwierdzone kodem — zamyka przez bulk_update_nodes ze sprawdzeniem odpowiedzi. Co zrobione częściowo — zostaje draftem z adnotacją, czego dokładnie brakuje. Główna zasada komendy: nigdy nie oznaczać węzła jako done bez dowodów w kodzie. Dokładność jest ważniejsza niż liczba zamkniętych.
Druga komenda, /my-architect:progress, odpowiada na pytanie „gdzie jesteśmy": procenty done po release'ach i epicach, bieżące zadanie in-progress i co na nim zostało, następne zadanie z kolejki. Jeśli komenda widzi węzły draft, które po wszystkich znakach na niebie i ziemi są już wdrożone, sama zaproponuje przepuszczenie reconcile.
Co to daje
Agent może prowadzić projekt tygodniami. Sesje się kończą, okna kontekstowe się kompresują, a struktura zostaje: każde zamknięte zadanie zostawiło summary, każdy ogon stał się węzłem, każdy dokument opisuje aktualny stan kodu. Człowiek w dowolnym momencie otwiera kanwę i widzi uczciwy obraz, a nie ten, który był aktualny w chwili ostatniego calla.
W części piątej opowiem o dystrybucji przez Claude Code marketplace: jak zbudowany jest plugin, który instaluje skill i serwer MCP jedną komendą, i dlaczego skill żyje w publicznym repozytorium. My Architect można wypróbować na my-architect.app.