# GEMA-0 V10.1 — Raport całościowy rurociągu (reverse engineering z kodu) **Data:** 2026-05-30 **Wersja produktu:** `10.1.0` (`package.json`) — ten sam silnik co V10 APEX; 10.1 to domknięcie SRE/integracji (swarm size, radar plików, wspólny dispatch, RAM unmount przy shutdown). **Źródło prawdy:** wyłącznie `backend/` (ignorowane: `_docs/` poza tym plikiem, `legacy/`, README jako specyfikacja). **Cel:** blueprint dla migracji RAM-first i audyt luk integracyjnych. **API:** `GET /api/status` zwraca `version` odczytaną z `package.json` (nie hardcoded `"10"`). --- ## Spis treści 1. [Mapa przepływu](#1-mapa-przepływu-post-apioraculum--flushfile) 2. [Orkiestracja — kluczowy kod](#2-orkiestracja--kluczowy-kod) 3. [ByteGrafter (podmiana AST)](#3-bytegrafter-podmiana-ast) 4. [PhantomVM (sędzia)](#4-phantomvm-sędzia) 5. [Oraculum + indexer](#5-oraculum--indexer) 6. [RAM workspace](#6-ram-workspace) 7. [Niepodpięte / niedokończone](#7-niepodpięte--niedokończone) 8. [Drugie rurociągi obok V10.1](#8-drugie-rurociągi-obok-v101) 9. [Frontend sequencer-ui](#9-frontend-sequencer-ui) 10. [Tabela trybów CREATE vs GRAFT](#10-tabela-trybów-create-vs-graft) 11. [Pola misji — kto ustawia / kto konsumuje](#11-pola-misji--kto-ustawia--kto-konsumuje) --- ## 1. Mapa przepływu (POST `/api/oraculum` → `flushFile`) ### Warstwa HTTP — `backend/server.mjs` 1. `app.post('/api/oraculum', …)` — walidacja `projectId`, `prompt` (alias `task` → `prompt`) 2. `dispatchOraculumMissions({ projectId, prompt, workspacesDir, orchestrator, enqueueMission, createLlm: resolveMissionLlm })` — **await** przed odpowiedzią HTTP 200 ### Dispatch — `backend/api/oraculumDispatch.mjs` 3. `fs.existsSync(projectPath)` — `workspaces/` 4. Odczyt opcjonalny `.project_rules` → `domainRules` 5. `buildProjectMap(projectPath)` — `backend/ast/workspaceIndexer.mjs` 6. `generateManifest(prompt, projectMap, domainRules)` — `backend/ai/oraculum.mjs` - domyślnie `generateContent` (`aiGateway.mjs`, model `gemini-2.5-pro`, JSON) - `Promise.race` timeout 45000 ms - `JSON.parse` → `{ missions: [...] }` 7. `createLlm()` — w serwerze: `resolveMissionLlm()` (Gemini provider lub mock) 8. Dla każdego `m` w `manifest.missions`: - `missionPayload` (`taskId`, `mode`, `targetFile`, `functionName`, `oraclePrompt`, `validationArgs`, `profile`, `swarmSize`, `domainRules`) - `EventBroker.publish('NEW_MISSION', missionPayload)` - `enqueueMission(projectId, async () => orchestrator.executeMission(missionPayload, llm))` ### Kolejka — `server.mjs` → `enqueueMission` 9. Misje tego samego `projectId` wykonują się **szeregowo** (`projectMissionQueues`) ### Orkiestrator — `backend/core/orchestrator.mjs` → `executeMission` 10. `ramWorkspace.getPhysicalPath(projectId, targetFile)` → `absoluteTargetFile` 11. `ramWorkspace.mountFile(projectId, targetFile)` → `ramTargetFile` (`os.tmpdir()/gema0_ram_workspaces/...`) 12. `effectiveMode`: jeśli `mode !== 'CREATE_NEW_FILE'` i brak pliku na dysku → wymuszenie `CREATE_NEW_FILE` 13. `EventBroker.publish('MISSION_STARTED', …)` #### Gałąź A — `CREATE_NEW_FILE` 14. Budowa `microContext` 15. Pętla prób 1..3: `EventBroker.publish('SWARM_START')` → `fireSwarm(..., 'FULL_FILE', ..., ramTargetFile, ...)` 16. `runInWriteQueue(absoluteTargetFile)`: - `mkdir` + `writeFile(ramTargetFile, sanitizeGeneratedCode(winner.code))` - **`ramWorkspace.flushFile(projectId, targetFile)`** #### Gałąź B — `GRAFT_EXISTING_AST` 17. `AST_EXTRACTING` → `readFile(ramTargetFile)` → `getCoordinates` → `lockManager.acquireLock` (retry przy `OverlapError`) 18. `extractFunctionSkeleton` → `microContext` ze szkieletem 19. Pętla prób: `fireSwarm(..., functionName, ..., absoluteTargetFile, ...)` — **VM dostaje ścieżkę fizyczną, nie RAM** 20. `GRAFTING_START` → `runInWriteQueue`: - `graftFunctionBody(ramTargetFile, winner.code, functionName, ramTargetFile)` - **`ramWorkspace.flushFile(projectId, targetFile)`** ### Rój — `backend/ai/shotgunSwarm.mjs` → `fireSwarm` 21. `normalizeSwarmSize(swarmSize)` — per agent: stagger `index * 250` ms 22. `generateContent(prompt, systemPrompt, 'gemini-2.5-flash', { temperature, signal })` 23. `sanitizeGeneratedCode` → `PhantomVM.run(...)` 24. `Promise.any(promises)` + timeout globalny 60000 ms; po wygranej `controller.abort()` ### Flush — `backend/core/ramWorkspaceManager.mjs` 25. `flushFile`: `fs.copyFileSync(ramPath, physicalPath)` gdzie `ramPath = join(tmpdir, 'gema0_ram_workspaces', projectId, relativeFilePath)` ### Finally orchestratora 26. `lockManager.releaseLock` (jeśli był lock) 27. Opcjonalnie zapis `assemblyDir/20_agent_report.md`, `40_auditor_verdict.md` --- ## 2. Orkiestracja — kluczowy kod ### Inicjalizacja RAM i wybór trybu Plik: `backend/core/orchestrator.mjs` ```javascript absoluteTargetFile = ramWorkspace.getPhysicalPath(projectId, targetFile); ramTargetFile = ramWorkspace.mountFile(projectId, targetFile); let effectiveMode = mode; if (effectiveMode !== 'CREATE_NEW_FILE' && !fs.existsSync(absoluteTargetFile)) { effectiveMode = 'CREATE_NEW_FILE'; } ``` ### CREATE_NEW_FILE: fireSwarm + flush ```javascript winner = await fireSwarm(microContext, 'FULL_FILE', validationArgs || [], llmProvider, swarmSize, taskId, traceExpectations ?? null, assemblyDir, ramTargetFile, profile, domainRules); await runInWriteQueue(absoluteTargetFile, async () => { await fs.promises.mkdir(path.dirname(ramTargetFile), { recursive: true }); let cleanCode = sanitizeGeneratedCode(winner.code); await fs.promises.writeFile(ramTargetFile, cleanCode, 'utf-8'); ramWorkspace.flushFile(projectId, targetFile); }); ``` ### GRAFT: lock + fireSwarm + graft + flush ```javascript coords = getCoordinates(initialCode, functionName); semanticLockId = lockManager.acquireLock(absoluteTargetFile, coords.nodeStart, coords.nodeEnd); skeleton = extractFunctionSkeleton(ramTargetFile, functionName); winner = await fireSwarm(microContext, functionName, validationArgs, llmProvider, swarmSize, taskId, traceExpectations ?? null, assemblyDir, absoluteTargetFile, profile, domainRules); await runInWriteQueue(absoluteTargetFile, async () => { graftFunctionBody(ramTargetFile, winner.code, functionName, ramTargetFile); ramWorkspace.flushFile(projectId, targetFile); }); ``` ### RAM manager — mount / flush Plik: `backend/core/ramWorkspaceManager.mjs` - **Fizyczny:** `repoRoot/workspaces//` - **RAM:** `os.tmpdir()/gema0_ram_workspaces//` - `mountFile`: kopia dysk→RAM lub pusty plik dla nowego - `flushFile`: kopia RAM→dysk (`copyFileSync`) - `unmountAll`: tylko przy `SIGINT`/`SIGTERM` w `server.mjs` --- ## 3. ByteGrafter (podmiana AST) Plik: `backend/ast/byteGrafter.mjs` - `getCoordinates(sourceCode, targetName)` — `@babel/parser`, współrzędne `node.start` / `node.end` dla `FunctionDeclaration`, arrow/function w `VariableDeclarator`, `ClassDeclaration` - `extractFunctionSkeleton` — sygnatura od `nodeStart` do `bodyStart` + stub TODO - `graftFunctionBody` — wycina węzeł z kodu agenta (`genCoords`), `MagicString.overwrite` na zakresie `originalCoords.nodeStart..nodeEnd` ```javascript const newFunctionCode = generatedCode.slice(genCoords.nodeStart, genCoords.nodeEnd); const magic = new MagicString(originalCode); magic.overwrite(originalCoords.nodeStart, originalCoords.nodeEnd, newFunctionCode); fs.writeFileSync(outputPath, magic.toString(), 'utf8'); ``` --- ## 4. PhantomVM (sędzia) Plik: `backend/core/phantomVM.mjs` ### Bypass VM (bez `vm.Script`) - Frontend/static: `REACT_VITE`, `STATIC_HTML`, `PYTHON_SCRIPT`, rozszerzenia pliku, JSX w kodzie → AST (`@babel/parser`) lub skip - `NODE_ESM` + `functionName === 'FULL_FILE'` + brak testów z `30_mechanical_gate.json` → tylko AST modułu ### Pełna egzekucja VM - Testy z `assemblyDir/30_mechanical_gate.json` lub fallback `validationArgs` / wywołanie `functionName(...testArgs)` - Strip ESM (`export`/`import`) dla `NODE_ESM` - `new vm.Script(executableScript)` → `runInContext(sandbox, { timeout: 2000 })` - Sandbox: proxy `db`, `fetch`, `api`, `console` → ślad `trace` - `validateTrace(trace, traceExpectations)` na końcu --- ## 5. Oraculum + indexer ### `generateManifest` — `backend/ai/oraculum.mjs` Zwraca JSON z tablicą `missions[]` (`targetFile`, `functionName`, `mode`, `oraclePrompt`, `validationArgs`, `profile`, `swarmSize`). Nie wykonuje kodu — tylko routing. ### `buildProjectMap` — `backend/ast/workspaceIndexer.mjs` Rekurencyjny skan workspace (pomija `node_modules`, `.git`, `dist`, `build`, `_docs`, `.gema0`). Dla `.js/.mjs/.ts/.jsx/.tsx` — lista nazw funkcji/klas z AST; dla `.html/.css/.json` — pusta tablica. --- ## 6. RAM workspace | Etap | Operacja | |------|----------| | Start misji | `mountFile` — dysk → tmpdir | | Edycja | `readFile` / `writeFile` / `graftFunctionBody` na `ramTargetFile` | | Koniec | `flushFile` — tmpdir → `workspaces/` | | Shutdown | `unmountAll` — kasuje cały `gema0_ram_workspaces` | **Uwaga migracji RAM-first:** po flush plik RAM nie jest usuwany per misja; brak „tylko RAM” bez zapisu na dysk w obecnym kodzie. --- ## 7. Niepodpięte / niedokończone | Element | Problem | |---------|---------| | `assemblyAdapter.parseAssemblyJob` | Brak route HTTP, brak importu w `server.mjs` — misje z `.gema0/assembly//` nie startują z API | | `oraculumDispatch` missionPayload | **Nie przekazuje:** `assemblyDir`, `mechanicalGate`, `traceExpectations` | | `fireSwarm` → `llmProvider` | Parametr **nieużywany**; agenci wołają tylko `generateContent` z `aiGateway.mjs` | | `oraculumDispatch` → `createLlm()` | **Brak `await`** przy async `resolveMissionLlm` (faktycznie bez wpływu na swarm) | | `postDemoMission` / `demoMission.js` | Plik w frontendzie **nieimportowany** | | `sequencer-ui/README.md` | Opisuje demo `/api/mission` na SWARM_START; kod używa `/api/oraculum` | | Marketing routes | `registerMarketingRoutes` — brak UI w sequencer | | RAM cleanup | Brak `unmount` po pojedynczej misji | --- ## 8. Drugie rurociągi obok V10.1 ``` POST /api/oraculum ──┐ POST /api/mission ───┼──► dispatchOraculumMissions ──► Orchestrator ──► fireSwarm ──► PhantomVM ──► flushFile (pełny JSON) ──────┘ (tylko skrót) ▲ │ assemblyAdapter (BRAK HTTP) ───────────────────────────────┘ (niepodłączony) Osobno: provision/dev API, marketing API, CLI workspace-*, legacy server (npm run start:legacy) ``` | Wejście | Zachowanie | |---------|------------| | `POST /api/oraculum` | Await dispatch, HTTP **200** + `manifest` | | `POST /api/mission` + pełny payload | Bezpośrednio `executeMission`, HTTP **202** | | `POST /api/mission` + tylko `projectId`+`prompt` | Ten sam dispatch co Oraculum, HTTP **202** | | Assembly files | Zaimplementowany parser, **brak endpointu** | | Legacy monolit | Osobny kod w `legacy/`, nie współdzieli orchestratora V10 | --- ## 9. Frontend sequencer-ui **Lokalizacja:** `frontend/sequencer-ui/` (React + Vite, proxy `/api` i `/ws` → port 7878). | Tryb | Zachowanie | |------|------------| | **Live** | WebSocket `/ws` — zdarzenia `EventBroker`; SWARM_START → `POST /api/oraculum` z `{ projectId, prompt }` | | **Mock** | Lokalna symulacja agentów — bez backendu | **Podpięte API (poza generacją):** projekty, import, szablony, `/environment`, provision, dev start/stop. **UI vs backend:** - Stałe **5 agentów** w UI; manifest może mieć `swarmSize` 3–20 - Pola `targetFile` / `operationMode` w formularzu — **zakomentowane**; tryb i plik z manifestu Oraculum - `missionQueue` / `currentMissionIndex` — tylko wizualizacja postępu - Brak wywołań marketing API **Rola frontendu:** panel operatorski + telemetria, **nie** drugi orchestrator. --- ## 10. Tabela trybów CREATE vs GRAFT | Aspekt | CREATE_NEW_FILE | GRAFT_EXISTING_AST | |--------|-----------------|---------------------| | `fireSwarm` functionName | `'FULL_FILE'` | nazwa z manifestu | | `fireSwarm` targetFile (VM) | `ramTargetFile` | `absoluteTargetFile` | | Zapis przed flush | `writeFile` całego pliku | `graftFunctionBody` | | PhantomVM (NODE, bez gate) | AST validation | `vm.Script` + wywołanie funkcji | | Semantic lock | nie | `lockManager` na zakresie węzła | --- ## 11. Pola misji — kto ustawia / kto konsumuje | Pole | Oraculum manifest | oraculumDispatch | /api/mission pełny | Orchestrator | fireSwarm | PhantomVM | |------|-------------------|------------------|--------------------|--------------|-----------|-----------| | targetFile | tak | tak | tak | tak | tak (path VM) | tak | | functionName | tak | tak | tak | tak | tak | tak | | mode | tak | tak | tak | tak | — | — | | oraclePrompt | tak | tak | tak | tak (prompt) | — | — | | validationArgs | tak | tak | tak | tak | tak | tak | | profile | tak | tak | tak | tak | tak | tak | | swarmSize | tak | tak | tak | tak | tak | — | | domainRules | z `.project_rules` | tak | opcjonalnie | tak | tak | — | | traceExpectations | — | **nie** | tak | tak | tak | tak | | mechanicalGate | — | **nie** | tak | tak | — | — | | assemblyDir | — | **nie** | tak | tak | tak (gate JSON) | tak | | llmProvider | — | Promise? | await | przekazany | **ignorowany** | — | --- ## Pliki źródłowe (indeks) | Plik | Rola | |------|------| | `backend/server.mjs` | HTTP, kolejki, `/api/oraculum`, `/api/mission` | | `backend/api/oraculumDispatch.mjs` | Oraculum → manifest → kolejka | | `backend/ai/oraculum.mjs` | LLM → JSON misji | | `backend/ast/workspaceIndexer.mjs` | `buildProjectMap` | | `backend/core/orchestrator.mjs` | RAM, tryby, swarm, graft, flush | | `backend/ai/shotgunSwarm.mjs` | `fireSwarm` | | `backend/core/phantomVM.mjs` | Sędzia | | `backend/ast/byteGrafter.mjs` | Współrzędne AST, graft | | `backend/core/ramWorkspaceManager.mjs` | mount / flush | | `backend/core/assemblyAdapter.mjs` | Parser assembly (**niepodpięty**) | | `frontend/sequencer-ui/src/App.jsx` | UI Live/Mock | | `frontend/sequencer-ui/src/hooks/useGemaWebSocket.js` | WS zdarzeń | --- *Raport wygenerowany na podstawie analizy kodu w repozytorium GEMA-0 APEX **10.1.0** (backend Node.js, `package.json`).*