Powrót do strony głównej

Harness Engineering w legacy: agent pisze kod

W Harness Engineering inżynier ustala ramy i testy, agent pisze kod produktowy. Eksperyment na legacy-monorepozytorium wykazał zysk na rutynie: przenos modułów, infrastruktura e2e. Ograniczenia — brak innowacji bez ścisłego kontekstu.

Agent pisze cały kod: Harness w legacy Scala
Advertisement 728x90

Harness Engineering: jak agent pisze kod produktowy w legacy monorepo

W Harness Engineering człowiek określa ramy architektoniczne, scenariusze testowe i recenzuje wyniki, a agent generuje cały kod produktowy. Eksperyment na legacy monorepo z 310 tys. linii Scala/Java pokazał przydatność podejścia do typowych zadań: wydzielenie modułu bez zmiany zachowania. Rola inżyniera przesuwa się w stronę zarządzania kontekstem i procesem, agent przejmuje mechaniczną rutynę.

Monorepo: 25 modułów SBT, 8 lat historii, system o wysokim obciążeniu. Zadanie — wydzielić obsługę webhooków kanału X do osobnego serwisu na wzór istniejących adapterów.

Warunki eksperymentu i role uczestników

Człowiek nie pisze kodu produktowego. Role są wyraźnie rozdzielone:

Google AdInline article slot
  • Człowiek: granice architektoniczne, podział na etapy, wymagania, testy, recenzje, ostateczna weryfikacja.
  • Agent: tworzenie/zmiana kodu, przenoszenie fragmentów, testy według scenariuszy, infrastruktura, naprawa defektów.

Zadanie typowe: mechaniczne przeniesienie z adaptacją wiring, zależności, bez refaktoryzacji logiki biznesowej. Weryfikowalność przez testy unitowe i e2e.

Przygotowanie kontekstu: dokumentacja jako interfejs zarządzania

Dokumentacja staje się narzędziem: ADR opisuje warianty, plan — etapy. Agent działa w zadanych ramach, bez domysłów.

Przykład ADR:

Google AdInline article slot
# ADR-42: wydzielenie obsługi webhooków kanału X z monolitu

## Kontekst
Kanał X jest obecnie obsługiwany wewnątrz jądra. Pozostałe kanały działają jako osobne serwisy za brokerem wiadomości.

## Warianty
1. Cienka powłoka: przenieść istniejący kod z minimalnymi zmianami (pakiety, wiring).
2. Przepisać handler „od nowa” na innym stosie.
3. Pozostawić bez zmian.

## Decyzja
Wariant 1: najmniejsza utrata niejawnego zachowania przy przenoszeniu; architektura wyrównuje się z pozostałymi kanałami.

## Konsekwencje
+ jednolity wzorzec dla wszystkich kanałów  
− tymczasowe duplikowanie kodu; refaktoryzacja — osobne zadanie

Plan po etapach zmniejsza błędy: od szkieletu do pełnego konturu e2e.

Etapy i prompty: etapowe sterowanie agentem

Podział na kroki zapewnia kontrolę. Przykłady promptów:

  • Szkic architektoniczny:
Przeanalizuj, jak zbudowane są adaptery kanałów A i B: jak subskrybują brokera i publikują przychodzące zdarzenia.
Znajdź w monolitcie obsługę webhooków kanału X.
Napisz ADR z trzema wariantami: powłoka / przepisać / zostawić w jądrze. Poleć powłokę i opisz konsekwencje.
Pliki umieść w architecture/adr/, kodu jeszcze nie zmieniaj.
  • Testy jako kontrakt:
W klasie WebhookHandler jest rozgałęzienie po typie czatu. Wydziel je do czystej funkcji routeEvent(...).
Zachowania nie poprawiaj — kopiuj gałęzie as-is. Napisz testy unitowe: czat prywatny, grupa, nieznany typ, puste ciało.
Kryterium: `sbt test` dla modułu zielony.
  • Nowy moduł:
Utwórz moduł sbt channel-x-adapter wg SPEC z ADR-42.
Skopiuj wymienione pliki z monolitu; zmieniaj tylko pakiety, importy i zależności do udanej kompilacji bez `dependsOn(core)`.
Zakaz: nie refaktoryzuj logiki biznesowej wiadomości na tym etapie.
  • Kontur E2E:
Dodaj katalog e2e/ na pytest + testcontainers: kontener brokera, PostgreSQL, mock zewnętrznego API na osobnym porcie.
Napisz jeden test: POST webhooka z tekstem "ping" → w brokerze na oczekiwanym subject pojawiło się zdarzenie z text=ping.

Testy — środek zarządzania: agent orientuje się na zielony sbt test lub pytest.

Google AdInline article slot

Zalety agenta: rutyna pod kontrolą

Agent wyróżnia się w:

  • Przenoszeniu i adaptacji kodu.
  • Powtarzaniu wzorców na wzór.
  • Generowaniu boilerplate.
  • Budowie infrastruktury testowej.
  • Serii jednorodnych poprawek.

Przykład testu e2e na pytest + testcontainers:

# fixture'y: kontener brokera, adapter, mock zewnętrznego HTTP API

def test_incoming_webhook_publishes_to_broker(e2e):
    e2e.http.post("/webhook/channel-x", json={"message": {"text": "hello", "chat": {"id": 42}}})
    msg = e2e.broker.await_message("inbound.channel-x", timeout_s=5)
    assert msg["text"] == "hello"
    assert msg["chat_id"] == 42

def test_outgoing_command_reaches_external_api(e2e):
    e2e.broker.publish("outbound.channel-x", {"chat_id": "42", "text": "hi"})
    calls = e2e.external_mock.wait_for_requests(method="POST", path_contains="sendMessage")
    assert any(b"hi" in c.body for c in calls)

Sprawdza nie kompilację, a zachowanie w powiązaniu: broker, BD, mock API.

Granice i ograniczenia podejścia

Agent nie zastępuje decyzji architektonicznych, ale przyspiesza mechanikę. Ryzyka: uzgodnione błędy (zielone testy maskują regresje), potrzeba ścisłych ram. Stosowane do legacy z wzorcami, nie do greenfield czy R&D.

Programiści mogą dojść do różnych wniosków: oszczędność na rutynie vs. narzut na kontekst.

Co ważne

  • Harness Engineering — kontrolowane środowisko dla agenta: reguły, narzędzia, feedback.
  • Zysk na przenoszeniu/adaptacji kodu i infrastrukturze testowej w projektach legacy.
  • Testy — kluczowy interfejs zarządzania, nie rytuał.
  • Granice: typowe zadania ze wzorcami, bez innowacji architektonicznych.
  • Branża: Anthropic (90% kodu AI), Meta, Amazon — przejście do AI-native dev.

— Editorial Team

Advertisement 728x90

Czytaj dalej