Wczoraj pokazałem matematykę. 1000 zadań, $700 vs $40, 70% nigdy nie dociera do LLM.

Dziś pokazuję mapę.

Dziesięć warstw architektonicznych które muszą być deterministyczne zanim AI zrobi cokolwiek użytecznego. Cztery z nich publikuję jako code dropy przez następne 8 tygodni. Pozostałe sześć zostaje w pitch-mode i powiem dlaczego.


Powtórka kanapki

Jeśli przegapiłeś część 1: deterministyczny input, AI w środku, deterministyczny output. LLM siedzi w małym ograniczonym slocie po środku. Kod to bułka, model to kotlet. Reszta to dodatki.

Ale “deterministycznie wejście, AI środek, deterministycznie wyjście” to kręgosłup. Teraz zakładamy mięso na kości.

Three-Layer Architecture

Każdy kawałek pipeline’u trzyma się tego samego wewnętrznego wzorca.

graph TB
    subgraph Raw["Warstwa 1: Raw (deterministyczne pobranie)"]
        J[Jira API raw]
        F[Figma MCP raw]
        P[Playwright snap raw]
    end

    subgraph Enriched["Warstwa 2: Enriched (deterministyczny ETL)"]
        TE[Ekstrakcja tokenów]
        AE[ARIA + computed CSS]
        CE[Context bundle]
    end

    subgraph Builders["Warstwa 3: Builders (ustrukturyzowany output)"]
        TC[Task context object]
        BP[Baseline + current pair]
        QC[QA prompt context]
    end

    Raw --> Enriched --> Builders --> AI[Decyzja AI]
    AI --> O[Zwalidowany output]

Trzy wewnętrzne warstwy, powtarzane w każdym komponencie:

  1. Raw - dziki zachód. HTML z Jiry, blob JSON design-tokens z Figmy, pełny DOM dump z Playwrighta. Pobranie source-of-truth, nic więcej.
  2. Enriched - deterministyczny ETL. Parse ADF. Walk po drzewie Figmy. Compute styles. Nadal bez LLM, nadal bez interpretacji - po prostu kod który zna kształt każdego źródła.
  3. Builders - otypowane obiekty. Cokolwiek przechodzi dalej ma schemę, kontrakt, test. LLM, kiedy w końcu się pojawia, widzi tylko output Builderów.

To ten sam wzorzec który napędza mój WCAG toolkit (Series #01, 5-7 maja). Ten sam wzorzec pojawia się przy skali w multi-page audits (Series #05, 2-4 czerwca). Ten sam wzorzec w Figma-to-code (#07, 16-18 czerwca). To nie nowość. To po prostu dyscyplina.

10 map

Dziesięć tematów. Każdy to warstwa która musi być deterministyczna zanim AI się włączy. Oto pełna mapa.

A: Input Layer - łapanie dzikiego zachodu deterministycznie → Odcinek #11, 14-16 lipca

Jira API + Figma MCP + Playwright snap. Trzy bałaganiarskie źródła. Jeden otypowany obiekt QAContext. AI nigdy nie czyta surowego HTML.

B: Decision Layer - 70% bez LLM → Odcinek #09, 30 czerwca - 2 lipca ⭐

Brama decyzyjna z części 1. CSS diff + pixel diff + a11y regression check = deterministyczny werdykt. 70% zadań wychodzi tutaj.

C: Output Layer - Atlassian ADF bez łez → Odcinek #10, 7-9 lipca ⭐ TOP FLAGSHIP

Inline obrazki w Jira ADF przez 303 redirect. Trik który rozwiązuje słynny ból Jiry. Plus mostki markdown-do-ADF i multi-stage uploads.

D: Orchestration - wielu agentów, jedna historia → Sierpień/wrzesień

Częściowe kontynuacje, heartbeats, retry semantics. Multi-agent dispatch gdzie każdy agent zna swój scope i swoją granicę.

E: HITL Safety - każdy WRITE prosi o zgodę → Odcinek #12, 21-23 lipca ⭐

Action queue state machine. Atomic approve-and-execute z trackingiem częściowych failures. Cautionary tale o dedup gdzie mój UNIQUE constraint był zły.

F: Vendor-Agnostic Infra - zmień providera, nie orchestrator → Wrzesień

Wyciąganie vendor-agnostic QA infra z dispatchera związanego z Claude. Wzorzec który robi multi-LLM future tanim.

G: Cost & Telemetry - grosze, nie dolary → Q4 2026

Per-task cost attribution. Token telemetry per worker. Kiedy cache’ować, kiedy batch’ować, kiedy fail fast.

H: Operational Discipline - kalendarze, dedup, UNIQUE był zły → Q4 2026

Pięć gotchas które złapałem na produkcji. UNIQUE na (task, run) wydawało się oczywiste - dopóki częściowe retry tego nie zepsuły.

I: Multi-Process Glue - terminale, tmux, CI → Q4 2026

Jeden skrypt, trzy backendy. Ten sam shell przez Claude Code, OpenCode subprocess, direct API.

J: Approval UX - HITL UI które nie czuje się jak praca → Odcinek #13, 4-6 sierpnia

Drag-drop approval queues. Countdowns. Edytowalne raporty QA. UX który zbudowałem żebym sam chciał używać własnego agenta.

Dlaczego dziesięć

Dlaczego nie trzy? Dlaczego nie dwadzieścia?

Bo każda z tych warstw jest niezależnie wymienna, deterministyczna (lub ma ograniczony scope LLM, bez scope creep), i ma własny test surface. Deterministyczne warstwy dostają unit testy. Warstwy LLM dostają contract testy przeciwko schemom. Obie warstwy mogą fail loudly i obie da się debugować w izolacji.

Anti-pattern który tego unika: pułapka “agent robi wszystko”. Kiedy jeden komponent nie ma granicy, nie ma testowalnego failure mode. Kiedy dziesięć komponentów posiada po jednej rzeczy, możesz naprawić co jest zepsute bez przepisywania tego co działa.

Input layer z bliska

Warstwa A jest najciekawsza do zaczęcia. Tu wszyscy popełniają pierwszy błąd.

Błąd: skarmianie surowego HTML z Jiry do LLM. Model czyta markup, halucynuje strukturę pól, gubi attachment, produkuje werdykt na bazie połowy ticketu. Nie dowiesz się dopóki produkcja się nie wywali.

Fix: single-call task aggregator który zwraca otypowany obiekt QAContext. Oto kształt.

// Single-call task aggregator - jeden webhook, pełen kontekst
// To jest to co AI w końcu widzi. Pre-walidowane, ustrukturyzowane, otypowane.

async function assembleContext(taskId: string): Promise<QAContext> {
  // Równoległe deterministyczne pobrania
  const [jiraRaw, figmaRaw, snapRaw] = await Promise.all([
    fetchJiraTask(taskId),         // n8n webhook, full task + komentarze + attachments
    fetchFigmaBaseline(taskId),    // MCP call, design tokens + komponenty
    capturePlaywrightSnap(taskId), // headless browser, aria + computed CSS
  ]);

  // Warstwa 2: enrichment (nadal deterministycznie - bez LLM)
  const enriched = {
    jira: parseJiraADF(jiraRaw),
    figma: extractTokens(figmaRaw),
    snap: { aria: snapRaw.tree, css: snapRaw.computedStyles },
  };

  // Warstwa 3: builder pattern - otypowany output któremu AI może zaufać
  return {
    taskMeta: { id: taskId, type: enriched.jira.type, severity: enriched.jira.severity },
    baseline: enriched.figma,
    current: enriched.snap,
    diff: computeStructuralDiff(enriched.figma, enriched.snap),
  };
}

Trzy równoległe pobrania. Każde zwraca surowe dane. Każde wzbogacone osobno. Potem builder produkuje otypowany QAContext - to widzi LLM.

Token-wise: naiwna wersja wysyła ~8K tokenów do modelu (samo surowe HTML z Jiry jest ogromne). Ustrukturyzowana wersja wysyła ~2K. To 4x taniej tylko z input layer, przed jakimkolwiek routingiem przez decision-gate.

I AI literalnie nie może czytać surowego HTML w tej architekturze. Widzi tylko QAContext. Jeśli parser się sypie, build się sypie. Jeśli model źle interpretuje otypowane pole, to jest model failure z zalogowanym inputem, nie halucynacja parsera.

Co dalej

Jutro: kalendarz.

Cztery z tych dziesięciu warstw (B, C, A, E) publikują się jako pełne code dropy przez następne 8 tygodni. Pozostałe sześć zostaje w pitch-mode na razie - są produkcyjno-specyficzne, multi-tenant, compliance-sensitive, albo po prostu nie są właściwym scope na publiczny destylat.

Pokażę dokładnie który tydzień każda ląduje, jak wygląda branch w repo, i jak się ze mną dogadać jeśli chcesz ten wzorzec w swoim stacku.

Mapa jest do góry nogami dla większości teamów. Pokażę ci moją.