diff --git a/docs/compose/plans/2026-07-10-aurelio-theia-live-delta.md b/docs/compose/plans/2026-07-10-aurelio-theia-live-delta.md new file mode 100644 index 00000000..cc809bf4 --- /dev/null +++ b/docs/compose/plans/2026-07-10-aurelio-theia-live-delta.md @@ -0,0 +1,111 @@ +# Aurelio → Theia: Live-Code Delta & Current State + +**Supersedes the "baseline-only" caveat** in `2026-07-10-aurelio-theia-migration-feature-inventory.md` and `…-porting-checklist.md`. Both repos were cloned read-only from Forgejo on CT 203 (`code.portugalfuturista.org` → `ssh://git@192.168.0.9:2222/portugalfuturista/.git`) into `~/portugalfuturista/`. + +| Repo | Path | HEAD | Date | Note | +|---|---|---|---|---| +| `aurelio-vscode` | `~/portugalfuturista/aurelio-vscode` | `b37e9d2` (`main`) | 2026-06-22 | version **0.12.2** — live source of truth | +| `aurelio-theia` | `~/portugalfuturista/aurelio-theia` | `f8bed07` (`main`) | 2026-07-10 | version **0.1.0** — skeleton only (2 commits) | + +**Access path used (for re-runs):** this host has LAN reachability to the Proxmox host `root@192.168.0.38` (key auth). The Forgejo git daemon runs in CT 203 (`pf-iot-stack`, `192.168.0.9`), exposed on host port `2222→22`. Direct `ssh code.portugalfuturista.org` does NOT work from here (Cloudflare anycast, no inbound 22, no IPv6 route, no local `cloudflared`). The working clone is over the LAN: `git clone ssh://git@192.168.0.9:2222/portugalfuturista/aurelio-vscode.git` (authenticates as Forgejo user `triviabilidades` via `~/.ssh/id_ed25519`). The bare repos live in the docker volume `/var/lib/docker/volumes/pf-iot-stack_forgejo-data/_data/git/repositories/portugalfuturista/`. + +--- + +## 1. aurelio-vscode `main` (0.12.2) — measured delta vs the 0.12.0 baseline + +The previous inventory/checklist were built from a git-history reconstruction tagged 0.12.0. Live `main` is **0.12.2** and is broadly consistent but has moved in a few material ways: + +| Metric | 0.12.0 (reconstructed) | 0.12.2 (`main`, live) | Δ | +|---|---:|---:|---| +| `package.json` version | 0.12.0 | **0.12.2** | +2 patch | +| `engines.vscode` | ^1.90.0 | ^1.90.0 | — | +| Declared commands | 64 | **66** | +2 (`/glm`/`/claude` era additions) | +| Registered unique commands | ~79 | **83** | +4 | +| Declared-not-registered | some | **none** | all declared commands are wired | +| Registered-not-declared (internal) | ~15 | **17** | +2 | +| Settings keys (`aurelio.*`/`quarkdown.*`) | 123 | **126** | +3 (kimi multi-mode) | +| Sidebar views | 6 | 6 | — | +| View containers | 1 | 1 | — | +| Webview panels (`createWebviewPanel`) | 24 | **25** | +1 | +| Custom editor | 1 (PDF/EPUB) | 1 (PDF/EPUB) | — | +| `src/*.ts` LOC | ~51k | **41,781** (151 files) | −~9k (Jules removal + cleanup) | +| Node-built-in importer files | 46 | **70** | +24 (more backend-coupling, not less) | +| `vscode.lm` consumers | 1 (`sessionMemory.ts`) | **2** (`sessionMemory.ts` + `magicDocs.ts`) | +1 — the Theia-incompatible surface grew | +| `*.portugalfuturista.org` hosts | 13 | 13 | — (but 206→208/125 migration done) | +| `src/_future/*` dormant files | 5 | 5 (still present, still 0 importers) | — | + +**What changed (commit log):** +- `61fc483 feat(vscode): multi-mode Kimi provider (direct/code/hermes) + OpenRouter model picker` → new `src/models/kimiProvider.ts` (211 LOC); new settings `aurelio.kimi.mode` (`direct|code|hermes`), `aurelio.kimi.apiKey`, `aurelio.kimi.codeApiKey`, `aurelio.kimi.codeModel`. **No `zaiProvider.ts` in this snapshot** — the `glm`/`claude` ModelTypes documented in `nervura-electrica/docs/AURELIO_GLM_CLAUDE.md` are *not yet* in this checkout; `modelRouter.ts` `ModelType = 'local'|'vertex'|'openrouter'|'antigravity'|'kimi'|'hermes'` (no `glm`/`claude`/`jules`). Slash map still `/local /vertex /openrouter /antigravity /kimi` (+ others). +- `4141235 refactor: remove Google Jules integration and point MCP servers to CT 208` → `julesClient.ts` gone, no `jules`/`@google/jules` refs anywhere. Checklist row B9 (Jules) is **now moot — drop it**. +- `1a5f478 fix: bypass CT 206 for print/Kimi and fall back to central brain`, `31d4f48 fix: point Hermes endpoint to reachable NVIDIA API` → CT 206 retired; MCP/brain now target **CT 208 (`192.168.0.125`)**, consistent with `nervura-electrica/AGENTS.md`. +- `b37e9d2 docs(agents): document frontend split and key settings` → confirms the **frontend split**: the VS Code webview reuses the **Svelte build from the separate `aurelio-web` repo**; the public `portal.portugalfuturista.org` is a distinct React app. Two frontends, same backend ecosystem. This matters for Theia: the Svelte control-center is shared infrastructure, not private to the VS Code extension. +- New context modules not in the 0.12.0 baseline: `src/context/consolidationLock.ts` (173), `src/context/sessionMemoryCompact.ts` (211), `src/context/sessionSnapshot.ts` (241) — the auto-dream/compaction subsystem has grown and is now locked/snapshotted. Strengthens the "move memory/context to Theia backend" recommendation (D-group). + +**Net effect on the migration plan:** the feature *shape* in the inventory is still accurate; the *numbers* and a few subsystem details are now superseded by the table above. The two structural risks are *larger* than the baseline suggested: node-coupling rose from 46→70 files, and `vscode.lm` (no Theia equivalent) is now used in two places (`sessionMemory.ts` + `magicDocs.ts`). + +--- + +## 2. aurelio-theia `main` (0.1.0) — what actually exists today + +**It is a day-0 skeleton (2 commits, 13 files, no `node_modules`, not yet built).** Commit `f8bed07 "feat: initial scaffolding — Theia product + Aurelio extension skeleton"`. Do not treat it as a port — it's a greenfield shell with Aurelio-shaped placeholders. + +**Stack pinned:** Eclipse Theia **1.56.0** (all `@theia/*` deps), `lerna ^8` + yarn workspaces, `typescript ~5.3.3`, `@modelcontextprotocol/sdk ^1.29.0`, `axios ^1.15.2`, `express ^4.18.0` (backend only). + +**Layout:** +``` +aurelio-theia/ +├── package.json # product: @theia/* 1.56.0; `start` = `theia start --plugins=local-dir:./AurelioTheia` +├── lerna.json # yarn workspaces: AurelioTheia, aurelio-backend +├── tsconfig.json # ES2020, strict, jsx react +├── README.md +├── AurelioTheia/ # the Theia extension (frontend+backend) +│ ├── package.json # theiaExtensions: frontend lib/browser, backend lib/node +│ └── src/ +│ ├── browser/aurelio-frontend-module.ts # binds 2 classes, no contrib wiring beyond commands +│ ├── browser/aurelio-commands.ts # EMPTY placeholder class +│ ├── browser/aurelio-sidebar-contribution.ts # registers 5 commands → console.log only +│ └── node/aurelio-backend-module.ts # empty ContainerModule (commented TODO list) +└── aurelio-backend/ # standalone express backend (placeholder) + ├── package.json + └── src/server.ts # console.logs port 3101; no routes +``` + +**What's wired vs. stubbed:** +- 5 commands declared and registered (`aurelio.syncPush`, `aurelio.syncPull`, `aurelio.startSession`, `aurelio.switchRealm`, `aurelio.manageHeteronimos`) — every handler is `() => console.log(...)`. **No views, no webviews, no MCP client, no model router, no brain/sync implementation, no settings schema.** `AurelioCommands` (the class) is an empty placeholder; the real command ids live in `aurelio-sidebar-contribution.ts` as a const object. +- Backend module is an empty `ContainerModule` with a TODO comment listing brain sync / MCP registry / session management / realm discovery. +- Standalone `aurelio-backend` (express on :3101) prints a banner and exits — no endpoints. +- README promises: brain sync to CT 208, MCP registry, session management, realm discovery, heterónimo system — none implemented yet. + +**Crucial architecture signal for the port:** the `start` script uses `--plugins=local-dir:./AurelioTheia` — i.e. the team is loading the Aurelio code as a **Theia plugin/extension in the plugin host**, *and* there's a separate **standalone `aurelio-backend` express service**. This maps cleanly onto the checklist's "Path C (hybrid)": the heavy/fs/network/MCP work goes in `aurelio-backend` (a normal Node service, can spawn dirac/esptool/git, reach CT 208/125, bind :3101), and the Theia extension contributes UI + calls the backend over HTTP/WS. This is the right shape and de-risks the F-group (hardware) and H-group (dirac/evolution) BLOCK rows: those belong in `aurelio-backend`, not in the browser plugin host. + +**Gaps the skeleton hasn't addressed yet (decisions still open from checklist §6):** +- No Theia **preferences schema** ported from the 126 `aurelio.*`/`quarkdown.*` settings. +- No **secret storage** wiring for the keys (and the 3 plaintext-default keys in aurelio-vscode must not be carried over). +- No **webview** host for the Svelte control-center (shared with aurelio-web) — Theia mini-browser is pinned (`@theia/mini-browser 1.56.0`) but unused. +- No **vscode.lm** replacement plan (needed by sessionMemory + magicDocs). +- No **custom editor** strategy for PDF/EPUB. +- No **OTA/update** channel (Theia plugins don't use `vsce`/VSIX; needs a Theia plugin registry or image-baked decision). +- **Theia 1.56.0** (released ~2024) is pinned — verify the VS Code-extension-compat (plugin host) coverage for the specific APIs aurelio uses (webview `asWebviewUri`, `CustomEditorProvider`, `vscode.lm`, `registerWebviewViewProvider`) before assuming Path A works for the C-group webviews. + +--- + +## 3. Concrete edits to the two existing docs (apply on next revision) + +- **Feature inventory §1 (headline numbers):** replace with the 0.12.2 column above (66/83/126/6/25/41,781/70/2). Note `engines.vscode ^1.90.0`, publisher `portugalfuturista`, name `aurelio`, displayName "Aurelio — Réplica Omnisciente". +- **Models (B-group):** drop **B9 Jules** (removed). Add `kimiProvider.ts` multi-mode (direct/code/hermes) + the 4 `aurelio.kimi.*` settings. Flag that the documented `glm`/`claude` `ModelType`s from `nervura-electrica` are **not** present in this checkout — confirm whether they land on a branch or were planned-but-reverted. +- **vscode.lm (B15/D12):** now **2 consumers** — add `src/context/magicDocs.ts` to the reroute list alongside `sessionMemory.ts`. +- **CT targets:** the migration from CT 206 → CT 208 (`192.168.0.125`) is done in code; the 13 pf hosts list is unchanged but `192.168.0.125` now leads (6 refs). Update brain/sync target references. +- **Frontend split:** add a note that the Svelte control-center is **shared with the `aurelio-web` repo** (separate from the React portal). The Theia cockpit must consume that shared Svelte build, not a private copy. +- **Context/memory (D-group):** add the three new modules (`consolidationLock`, `sessionMemoryCompact`, `sessionSnapshot`); reinforces backend placement. +- **§6 decision 1 (hosting side):** partially **answered by the skeleton** — team chose **Path C (hybrid)**: Theia plugin host for UI + a standalone `aurelio-backend` (express :3101) for fs/network/MCP/spawn. Update §7 sequencing to put `aurelio-backend` build-out in Wave 1. +- **New section needed (in either doc):** "State of the Theia fork" = §2 above (1.56.0, skeleton, 5 stub commands, empty backend, open gaps). + +## 4. Repro commands (read-only) + +```bash +# LAN clone (works from this host; direct ssh to code.* does not) +git clone ssh://git@192.168.0.9:2222/portugalfuturista/aurelio-vscode.git +git clone ssh://git@192.168.0.9:2222/portugalfuturista/aurelio-theia.git +# bare repos live in CT 203 docker volume: +# /var/lib/docker/volumes/pf-iot-stack_forgejo-data/_data/git/repositories/portugalfuturista/{aurelio-vscode,aurelio-theia}.git +``` diff --git a/docs/compose/plans/2026-07-10-aurelio-theia-migration-feature-inventory.md b/docs/compose/plans/2026-07-10-aurelio-theia-migration-feature-inventory.md new file mode 100644 index 00000000..58315949 --- /dev/null +++ b/docs/compose/plans/2026-07-10-aurelio-theia-migration-feature-inventory.md @@ -0,0 +1,343 @@ +# Aurelio → Eclipse Theia Migration: Feature Inventory + +**Source analyzed:** `aurelio-vscode` **v0.12.2 (live `main`, HEAD `b37e9d2`, 2026-06-22)**, cloned read-only from Forgejo on CT 203 (`code.portugalfuturista.org` → `ssh://git@192.168.0.9:2222/portugalfuturista/aurelio-vscode.git`) into `~/portugalfuturista/aurelio-vscode`. The Theia fork is `aurelio-theia` **v0.1.0 (HEAD `f8bed07`, 2026-07-10)** at `~/portugalfuturista/aurelio-theia`. The extension is VS Code-extension-shaped: the entire feature set lives in `package.json` + `src/`. Numbers below are measured from the live clone. (First draft used a `548b2cc6^` v0.12.0 reconstruction — superseded; see `2026-07-10-aurelio-theia-live-delta.md`.) + +**Target:** migrate `aurelio.portugalfuturista.org` from code-server + this VS Code extension to a fork of Eclipse Theia. + +**Status:** baseline inventory complete. Confirm whether the live extension repo has advanced past v0.12.0 before freezing the porting scope. + +--- + +## 0. The one-paragraph summary + +Aurelio is a 51k-LOC VS Code extension that turns the editor into the "central brain" cockpit for the Portugal Futurista fleet: an AI-agent chat with 7 routed model backends, a 16-tab Svelte control center, MCP server orchestration, a Git+Markdown memory/wiki layer, background sync to Proxmox, an evolutionary code loop (MAP-Elites) driven by a bundled Rust binary (`dirac`), and a deep hardware-lab integration (ESP32 fleet, PPK2 power profiler, sigrok logic analyzer, KiCad, SPICE/PSIM, FMU). Almost all of it is implemented against VS Code-only APIs (`vscode.window`, webviews, TreeDataProvider, StatusBarItem, `vscode.commands`) and a 123-key `aurelio.*` settings namespace. Theia has a VS Code-extension compatibility layer, so the *cheapest* migration path is to run the VSIX inside Theia's plugin host and only fork where Theia's compatibility gaps bite (custom editors, webview CSP, native binary spawning, status-bar, and the code-server-specific endpoints). Full rehosting to native Theia extensions is the expensive path. + +--- + +## 1. Surface area at a glance + +| Metric | Value | +|---|---| +| Extension version | 0.12.0 | +| `engines.vscode` | `^1.90.0` | +| Activation | `onStartupFinished` (always-on) | +| TS source files | 150 | +| Svelte files | 47 | +| Total `src/` LOC | ~51,127 | +| Declared commands (`package.json`) | 64 | +| Registered commands (extension.ts + modules) | ~79 (64 declared + 15 hidden/internal) | +| Activity-bar views (sidebar) | 6 | +| Webview panels (full editors) | 24 | +| Svelte control-center tabs | 16 | +| Settings keys (`aurelio.*` + `quarkdown.*`) | 123 | +| Keybindings | 2 (Quarkdown only) | +| Custom editors | 1 (`aurelio.pdfViewer` for `*.pdf`/`*.epub`) | +| Contributed languages/grammars | `quarkdown` (`.qd`) | +| Native binary bundled | `dirac` (Rust, in `native/dirac/`) | +| External services (portugalfuturista.org) | 13 hosts | + +### Top-level `src/` modules (by LOC) + +| Module | LOC | Role | +|---|---:|---| +| `webview/` | 14,770 | 24 panel hosts + chat + control center | +| `context/` | 3,140 | compaction, auto-dream, away-summary, scouts, session memory, speculation | +| `evolution/` | 2,887 | MAP-Elites evolutionary loop (orchestrator, mutator, sandbox, convergence) | +| `models/` | 2,654 | model router, heterónimos, kimi/jules/vertex clients, idempotency | +| `hardware/` | 2,604 | ESP32, PPK2, sigrok, KiCad, FMI, PSIM bridges | +| `quarkdown/` | 1,939 | embedded `.qd` language server + live preview + PDF export | +| `brain/` | 1,292 | sessions, realms, chronicle, immich, continuity | +| `sync/` | 1,043 | Proxmox brain sync, wiki sync, immich, session export | +| `core/` | 1,036 | native engine (dirac bridge), remote WS server, dirac gRPC client, event bus, service registry | +| `coordinator/` | 1,008 | autonomous worker orchestration, task registry, agent summary | +| `mcp/` | 962 | MCP hub, server manager, registry sync, servers tree | +| `memory/` | 932 | memory index, scan, extraction, types | +| `config/` | 810 | 3-tier config resolver, settings service | +| `_future/` | 748 | **DORMANT** — semantic cache, tool policy, voice (0 importers) | +| `utils/` | 733 | approval gate, aurelio-read, prevent-sleep, toon | +| `test/` | 682 | mocha suite (evolution/* only) | +| `antigravity/` | 562 | antigravity LS bridge + service | +| `gyro/` | 554 | unified Antigravity control (IDE + LSP services) | +| `workflow/` | 526 | workflow manager | +| `electronics/` | 317 | remote EDA client | +| `skills/` | 265 | directory-based skill loader | +| `updater/` | 166 | OTA self-update from firmware store | + +--- + +## 2. Contributes (package.json) — the VS Code contract the Theia fork must satisfy + +### 2.1 Activity bar + sidebar views (1 container, 6 views) + +Container: `aurelio-sidebar` (icon `resources/aurelio-icon.svg`). + +| View id | Type | Backing class | +|---|---|---| +| `aurelio.chatView` | webview view | `ChatPanel` (`src/webview/chatPanel.ts`, 2620 LOC) | +| `aurelio.sessionsView` | tree | `SessionProvider` (`src/brain/sessionProvider.ts`) | +| `aurelio.realmsView` | tree | `RealmProvider` | +| `aurelio.heteronimosView` | tree | `HeteronimoProvider` | +| `aurelio.immichView` | tree | `ImmichProvider` (`src/brain/immichProvider.ts`) | +| `aurelio.chronicleView` | tree | `ChronicleProvider` (`src/brain/chronicleProvider.ts`) | + +### 2.2 Commands (64 declared) — grouped by subsystem + +**Sessions / sync / wiki** +`aurelio.startSession`, `aurelio.syncPush`, `aurelio.syncPull`, `aurelio.wikiSync`, `aurelio.wikiPush`, `aurelio.wikiPull`, `aurelio.wikiExportSession`, `aurelio.pushSession`, `aurelio.refreshSessions`, `aurelio.deleteSession`, `aurelio.viewSessionHistory` + +**Realms / heterónimos** +`aurelio.switchRealm`, `aurelio.refreshRealms`, `aurelio.openHeteronimosMenu`, `aurelio.switchHeteronimo`, `aurelio.refreshHeteronimos` + +**Coordinator (autonomous mode)** +`aurelio.coordinator.start`, `aurelio.coordinator.status`, `aurelio.coordinator.finalize`, `aurelio.task` + +**Context / memory / speculation** +`aurelio.addContext`, `aurelio.optimizeAgent`, `aurelio.suggestPrompts`, `aurelio.showDiagnosticSummary`, `aurelio.showAgentSummary`, `aurelio.cleanup`, `aurelio.speculation.start`, `aurelio.speculation.accept`, `aurelio.speculation.abort` + +**Chat / UI** +`aurelio.openChat`, `aurelio.selectContext`, `aurelio.openControlCenter`, `aurelio.openSettings`, `aurelio.previewArtifact` + +**MCP** +`aurelio.syncMcpRegistry`, `aurelio.assignServerToRealm` + +**Immich** +`aurelio.importImmichAsset`, `aurelio.openImmichBrowser`, `aurelio.refreshImmich` + +**Chronicle** +`aurelio.addChronicleEntry`, `aurelio.refreshChronicle`, `aurelio.openChronicleEntry` + +**Hardware / lab dashboards** +`aurelio.openHardwareDashboard`, `aurelio.openHilDashboard`, `aurelio.openPpk2Dashboard`, `aurelio.openEsp32Controller`, `aurelio.openLogicAnalyzer`, `aurelio.openEngineeringHub` + +**Electronics / EDA viewers** +`aurelio.openSpiceViewer`, `aurelio.showSpiceResults`, `aurelio.openCoverageDashboard`, `aurelio.loadCoverageFromWorkspace`, `aurelio.openSchematicViewer`, `aurelio.openSourcingDashboard`, `aurelio.openPsimViewer`, `aurelio.openFmuViewer` + +**Fleet / finance / portals** +`aurelio.openGuardaLivrosDashboard`, `aurelio.openBolsaDoMundial`, `aurelio.refreshBolsaDoMundial`, `aurelio.placeBolsaOrder` + +**Quarkdown** +`quarkdown.startPreview`, `quarkdown.stopPreview`, `quarkdown.restartLanguageServer`, `quarkdown.exportPdf` + +**Hidden/registered-but-undeclared (internal wiring, 15):** `aurelio.openPdfViewer`, `aurelio.runSchematicAnalysis`, `aurelio.sourcing.search`, `aurelio.sourcing.findAlternates`, `aurelio.sourcing.optimize`, `aurelio.refreshGuardaLivros`, `aurelio.xgecuDetect`, `aurelio.xgecuRead`, `aurelio.jtagFlash`, `aurelio.ppkStart`, `aurelio.hermesStatus`, `aurelio.openArtifactRaw`, `aurelio.addArtifactComment`, `aurelio.activateSession`, `aurelio.selectSession`. + +> Porting note: 9 declared commands are registered by secondary register-functions called from `extension.ts` (`registerCoordinatorCommands`, `registerSpeculativeCommands`, `registerContextCommands`) — none are dead. + +### 2.3 Menus + +- `view/title` (10 entries): sessions (openChat / refresh / syncPull / syncPush / openControlCenter), realms (refresh), heterónimos (refresh), immich (refresh), chronicle (add / refresh). +- `view/item/context` (2): inline `deleteSession` / `pushSession` on conversation items. +- `editor/title` (2): quarkdown preview/export when `resourceExtname == .qd`. +- `commandPalette` (3): quarkdown gated to `.qd`. + +### 2.4 Settings — 123 keys across these namespaces + +`aurelio.agent` (17), `aurelio.antigravity` (11), `aurelio.browser` (6), `aurelio.agyIde` (4), `aurelio.agyLsp` (4), `aurelio.endpoints` (4), `aurelio.electronics` (4), `aurelio.jules` (6), `aurelio.hub` (6), `aurelio.hermes` (3), `aurelio.tab` (5), `aurelio.editor` (3), `aurelio.autoDream` (3), `aurelio.contextCompaction` (2), `aurelio.memoryExtraction` (2), `aurelio.notifications` (3), `aurelio.ota` (2), `aurelio.immich` (2), `aurelio.hardware` (1), `aurelio.autoSync` (1), `aurelio.defaultModel` (1), `aurelio.ollamaUrl` (1), `aurelio.openRouterApiKey` (1), `aurelio.activeHeteronimo` (1), `aurelio.activeModelType` (1), `aurelio.approvalGates` (1), `aurelio.controlCenter` (1, enabledPanels object for 16 tabs), `aurelio.customizations.skillPaths`, `aurelio.knowledgeSettings` (1 big object), `aurelio.models` (3), `quarkdown.*` (3). + +**Defaults that encode infrastructure (the Theia deployment must preserve or relocate these):** +- `aurelio.endpoints.{eda,mcp,ci,code}` → `*.portugalfuturista.org` +- `aurelio.antigravity.host` / `agyIde.host` → `antigravity.portugalfuturista.org:8900` +- `aurelio.agyLsp.host` → `agy-lsp.portugalfuturista.org:8902` +- `aurelio.electronics.remoteSimUrl` → `https://eda.portugalfuturista.org` +- `aurelio.hub.{hilBaseUrl,guardaLivrosBaseUrl,bolsaDoMundialBaseUrl}` → `hil.` / `api.portugalfuturista.org` +- `aurelio.hermes.endpoint` → `http://192.168.0.105:8200` (AORUS PRO Hermes 3) +- `aurelio.ollamaUrl` → `http://127.0.0.1:11434` +- `aurelio.ota.endpoint` → `https://firmware.portugalfuturista.org/extensions/aurelio/version.json` +- `aurelio.hardware.esp32Devices` → SaveEarth-01/02 at `192.168.0.54/55` +- ⚠️ **Hard-coded secrets in defaults:** `aurelio.antigravity.apiKey`, `aurelio.agyIde.apiKey`, `aurelio.agyLsp.apiKey` all default to the same 64-hex token. These are baked into the extension manifest and must be rotated/moved to secret storage during the Theia port — do not carry them as plaintext defaults. + +### 2.5 Custom editor + language + +- `aurelio.pdfViewer` (`PdfCustomEditorProvider` + `PdfViewerPanel`) for `*.pdf`/`*.epub` — uses `pdfjs-dist`, Svelte viewer. This is the one `CustomEditorProvider`; Theia's VS Code-compat custom-editor support is historically incomplete → likely porting hotspot. +- Language `quarkdown` (`.qd`) + grammar (`syntaxes/`) + `language-configuration.json` + embedded LSP (`src/quarkdown/`). + +--- + +## 3. Feature inventory by subsystem + +### 3.1 Chat + model routing (`webview/chatPanel.ts` 2620 LOC, `models/`) + +- **Chat webview** with streaming tokens, tool-call start/end events, pending-message queue, review-changes diff flow, slash-command palette, copy/insert code, attach context, model/heterónimo pickers. +- **Slash commands:** `/local /hermes /vertex /openrouter /antigravity /kimi /jules /run /workflow`. +- **ModelRouter** backends (`ModelType`): `local` (Ollama `/api/tags` + generate), `hermes` (Nous Hermes 3 at 192.168.0.105:8200), `vertex` (Gemini via `VertexAuthProvider` / google-auth-library), `openrouter`, `antigravity` (extension-to-extension delegation), `kimi` (Moonshot), `jules` (Google Jules SDK). Fallback chain: `local → hermes → vertex → openrouter → antigravity`. Streaming supported for local/openrouter/vertex/antigravity/hermes/jules; Kimi falls through to non-streaming. +- **Heterónimos** (`HeteronimoManager`): markdown-frontmatter personas with `capabilities[]`, `preferredModel`; per-persona memory; switchable active persona; auto-routes model from `preferredModel` (google→vertex, `/`→openrouter, kimi→kimi). +- **IdempotencyLayer** for safe retries. +- **ApprovalGate** (`utils/approvalGate.ts`): command/terminal approval with `alwaysAllow/alwaysDeny/alwaysAsk` lists, `agent.reviewPolicy`, `agent.terminalAutoExecution`, sandbox toggle. Surfaced into chat + control center as `approvalRequested`/`approvalResolved`. + +### 3.2 Control Center (`webview/controlCenterPanel.ts` 3229 LOC, Svelte) + +Single webview hosting 16 tabs (App.svelte), ~95 message `case` handlers in the host. Tabs (pt-PT labels): + +| id | label | Backing | +|---|---|---| +| bussola | Bússola | dashboard/orchestration | +| conversa | Conversa | chat (ChatTab) | +| motores | Motores | MCP servers (McpTab) | +| antigravidade | Antigravidade | Antigravity remote IDE control | +| arquivo | Arquivo de Orpheu | knowledge (annas-archive/arxiv/libgen/obsidian/calibre/zotero) | +| oficina | Oficina Sensacionista | school / Socratic "grill-me" learning | +| paineis | Painéis | dashboards launcher | +| pericias | Perícias | skills | +| sessoes | Sessões | sessions | +| cronicas | Crónicas | chronicle | +| frota | Frota | fleet analytics | +| processos | Processos | workflows | +| electronica | Electrónica | EDA/sourcing/SPICE | +| laboratorio | Laboratório | hardware lab | +| impressoras | Impressoras | 3D printers | +| engrenagens | Engrenagens | settings (10 sections) | + +Host message groups: MCP (reconnect/connectAll/ping/saveConfig/toggle/call/addRecommended/setServerRealms), knowledge (sync/open/extract/ingestObsidian/ingestData/query/syncGoogleKeep/optimizeVault), electronics (search/getDetail/alternates/optimizeBom/runSpice/runErc/extractBom/analyzePower/scanProjects/getDatasheet/validateReplacement/convertToSpice), fleet/finance/forecasting, escola (addSource/chat/action/newSession/list/cite/grill-me/study-guide/save/export/share), antigravity (connect/grpcConnect/disconnect/screenshot/screencast/sendPrompt/quickAction/toggleAutoAccept), agyIde (mirror set), agyLsp (connect/listTools/executeTool/quota/sendPrompt), vertex (health/listModels/infer), jules (status/dispatch/cancel/history/listSessions/resume), wiki (sync/push/pull/export/status), approval (resolve), workflows, settings save, brain sync-now. + +**Settings UI** (`settings-svelte`, 10 sections): Agente, Conta, Editor, Modelos, Navegador, Notificações, Personalizações, Reinos, Separador, Wiki. + +### 3.3 Brain / sessions / realms (`brain/`, `sync/`) + +- **BrainManager**: reads sessions from the 3-tier brain dir + fallback dirs (`~/.gemini/antigravity/brain`, `~/.kimi/sessions`); lists/deletes conversations; per-session artifacts + comments. +- **SessionProvider/RealmProvider/HeteronimoProvider**: tree views with inline delete/push. +- **SessionContinuityService**: captures editor state on `onDidChangeActiveTextEditor`. +- **ChronicleManager/Provider**: dated chronicle entries. +- **ImmichProvider/ImmichClient**: photo browsing + import from an Immich instance (`photos.portugalfuturista.org`). +- **ProxmoxSync**: HTTP push/pull/list against `aurelio.syncEndpoint` (default `https://mcp.portugalfuturista.org`, paths `/api/brain/{push,pull,list}`); **background loop every `sync.interval_seconds` (default 300s)** pushes all brain dirs + fallbacks. +- **WikiSync**: Git-backed sync to the sibling `olivrododesassossego` repo (auto-discovered as workspace folder / sibling / common parent); push/pull/export-session/status. +- **SessionExporter**: JSONL/JSON session persistence. + +### 3.4 Context / memory (`context/`, `memory/`) + +- **Compactor**: token-aware auto-compaction (threshold 0.85, max 128k). +- **AutoDream**: background memory consolidation (minHours 24, minSessions 5). +- **AwaySummaryManager**: recap on `onDidChangeWindowState` return. +- **SessionMemoryService** (+ `sessionMemory/` prompts/utils/types): per-session memory extraction. +- **MagicDocsService**: auto-updating docs. +- **PromptSuggestionService** + **ContextScout/ExternalScout**: prompt suggestions, repo + web scouting. +- **LSPClientService** (`vscode-languageclient`). +- **SpeculativeEngine** (+ speculativeCommands/speculativeFileSystem): speculative edit apply/accept/abort. +- **memory/**: frontmatter-typed memory files, index, scan, search, throttled extraction. + +### 3.5 Coordinator + workflows + skills + evolution + +- **Coordinator** (`coordinator/`): autonomous worker orchestration ported from claude-code coordinatorMode; phases driven over ModelRouter; `taskRegistry`, `agentSummary`, `autonomousBrain`. +- **WorkflowManager** (`workflow/`): named workflows registered as commands. +- **SkillLoader** (`skills/`): directory-based skills across global→workspace→realm cascade, registers dynamic commands. +- **EvolutionOrchestrator** (`evolution/`): MAP-Elites population loop backed by the dirac Rust engine; mutate→evaluate→insert on a timer; convergence detector; sandbox; mutator; file snapshots. **Only subsystem with tests** (`test/suite/evolution/*`). + +### 3.6 Native engine + remote server + dirac (`core/`) + +- **NativeEngine**: spawns bundled `native/dirac/target/release/dirac` (Rust); JSON-lines over stdio; respawn budget; exposes scan/search/index/toon/tokenizer/evolve + eval gates. Pure-TS fallbacks exist (`memoryScan.ts`, `toon.ts`). The dirac crate vendors a large set of `exa.*.proto` (Antigravity-derived) definitions. +- **RemoteServer**: HTTP + WebSocket server on port 34567 (default) for external control, gated by ApprovalGate. +- **DiracClient**: gRPC/self-hosted LS client, OAuth token injection, auto-discovery. +- **EventBus**, **ServiceRegistry**, **ConfigManager**. + +### 3.7 MCP (`mcp/`) + +- **McpHub**: `@modelcontextprotocol/sdk` client; **SSE** (`SSEClientTransport` for `url/serverUrl/sseUrl`) and **stdio** (`StdioClientTransport`) transports; reconnect backoff; per-tool enable/disable. +- **McpServerManager**: lifecycle, health, realm assignment. +- **McpRegistrySync**: pulls a registry of recommended servers; "add recommended" flow. +- **mcpServersProvider**: tree. + +> All MCP servers in this deployment are remote (`mcp-remote` to `*.portugalfuturista.org`) per the workspace AGENTS.md — SSE is the dominant transport. + +### 3.8 Hardware / lab (`hardware/`, `electronics/`, webview panels) + +- **Esp32Bridge**: spawns `python3 -m esptool`; scans `/dev/ttyUSB*`/`/dev/ttyACM*`; fleet of SaveEarth devices. +- **PPK2Bridge**: spawns python3 to drive Nordic PPK2 power profiler (battery lab). +- **SigrokBridge**: spawns `sigrok-cli` for logic-analyzer capture/decode → CSV. +- **KiCadBridge**: project/net/DRC parsing. +- **FmiBridge**: FMU co-simulation (Reference-FMUs), `execFile`-based. +- **PsimBridge**: spawns PSIM/ngspice/LTspice. +- **remoteEdaClient** (`electronics/`): offloads to `https://eda.portugalfuturista.org` (`/sim/{spice,erc,power-rails,parse,convert,bom,bom/optimize}`) — CT 203 → Docker `pf-eda-sim:8090`. +- Webview dashboards: hardware, HIL, PPK2, ESP32 controller, logic analyzer, schematic, sourcing, coverage, SPICE, PSIM, FMU, engineering hub, guarda-livros (accounting), bolsa-do-mundial (fantasy market), immich browser. + +### 3.9 Antigravity / Gyro (`antigravity/`, `gyro/`) + +Remote control of an Antigravity IDE instance (CT 212 `pf-antigravity`) via CDP bridge REST + gRPC + a self-hosted language server: connect, screenshots, screencast start/stop, send prompt, quick actions, auto-accept toggle, OAuth token injection, quota, LSP tool list/execute. Two near-duplicate stacks: `antigravity/` (older) and `gyro/` (unified AgyIdeService + AgyLspService) — both wired into the control center. + +### 3.10 Quarkdown (`quarkdown/`) + +Embedded language (`*.qd`) with its own LSP client, process manager, live-preview webview, HTTP poller, and PDF export. Based on github.com/iamgio/quarkdown (vendored as source, not submodule). Contributes the only keybindings (`shift+ctrl+v` preview, `ctrl+alt+p` export) and the only language/grammar. + +### 3.11 OTA updater (`updater/otaUpdater.ts`) + +Polls `aurelio.ota.endpoint` (`firmware.portugalfuturista.org/extensions/aurelio/version.json`) for new VSIX; self-update flow. CI (`.github/workflows/build.yml`) packages with `vsce` and SCPs VSIX + `version.json` to CT 205 (`192.168.0.15:/var/www/firmware/extensions/aurelio/`). **This update channel is VS Code-specific and must be redesigned for Theia** (Theia plugins are deployed into the plugin host, not via `vsce`/VSIX OTA in the same way). + +### 3.12 Dormant / postponed (`src/_future/`) + +`semanticCache.ts`, `toolPolicy.ts`, `voiceKeyterms.ts`, `voiceStreamSTT.ts`, `voice.ts` — **zero importers anywhere in `src/`**. Per the user's standing convention, treat as intentionally-postponed (not dead): keep, label, and carry a resume note rather than deleting. They are Phase 9.1 semantic cache, L-4 tool-calling policy, and voice/STT. + +--- + +## 4. External integration map (what the Theia fork must still reach) + +13 `*.portugalfuturista.org` hosts referenced from `src/`: + +`agy-lsp`, `antigravity`, `api`, `ci`, `code`, `eda`, `hil`, `lab-gw`, `mcp`, `photos`, `portal`, `ssh`, `firmware` (OTA, from settings), plus LAN `192.168.0.105` (Hermes), `192.168.0.54/55` (ESP32), CT 205 firmware store (`192.168.0.15`), CT 203 EDA, CT 212 antigravity, CT 208 Gabinete/brain, CT 206 lab gateway. + +Local processes spawned: `dirac` (bundled Rust), `python3 -m esptool`, `python3` (PPK2), `sigrok-cli`, `ngspice`/`ltspice`/`psim`, `quarkdown` (LSP), `gcloud` (vertex auth), `git` (wiki), `ollama` (HTTP). Browser via CDP (`cdpPort` 9222). + +**Implication for a Theia fork running in a browser:** anything that spawns a local process or touches `/dev/tty*` (ESP32/PPK2/sigrok/PSIM/quarkdown LSP/dirac) cannot run in the browser front-end; it must run in the Theia **back-end** (Node) or be proxied through the lab gateway (CT 206 / `lab-gw.portugalfuturista.org`) and the existing MCP/EDA services. The hardware bridges are already partly split (EDA is remote; serial devices are local) — the cleanest Theia design moves all device I/O behind the lab gateway and keeps the front-end pure. + +--- + +## 5. Migration paths + +### Path A — Run the VSIX as-is inside Theia's VS Code extension host (cheapest) + +Theia ships a VS Code API compatibility layer (`@theia/plugin-ext`). Realistic effort: days-to-weeks. Likely gaps to verify against Theia's current compat surface: +- `CustomEditorProvider` (PDF viewer) — historically partial. +- Webview CSP / `asWebviewUri`, Svelte bundles, message passing — usually works but CSP strictness differs. +- `vscode.window.createStatusBarItem`, `registerWebviewViewProvider`, `TreeDataProvider` — supported. +- Spawning the bundled `dirac` binary and `python3`/`sigrok-cli` from the extension host — works only if the plugin runs back-end side; browser-hosted plugins cannot spawn. +- `vscode-languageclient` (Quarkdown LSP) — supported. +- OTA self-update via VSIX — does not map to Theia's plugin deployment; replace. + +### Path B — Rehost as native Theia extensions/plugins (expensive, clean) + +Rewrite the 24 webviews + 6 tree views + 64 commands against Theia's `theia` plugin API or as Theia extensions (`@theia/core`). Effort: weeks-to-months. Only worth it for the pieces where Path A breaks or where you want native Theia theming/layout. + +### Path C — Hybrid (recommended) + +1. Stand up the Theia fork, enable the VS Code plugin host, drop in `aurelio-0.12.0.vsix`, and smoke-test every view/command. Keep a gap list. +2. Move all local-process spawns (dirac, esptool, PPK2, sigrok, SPICE, quarkdown LSP) behind the back-end or lab gateway; front-end talks HTTP/WS/MCP only. +3. Replace the OTA/VSIX channel with Theia's plugin deployment (build into the image or Theia's plugin registry). +4. Rotate the three baked-in API keys out of `package.json` defaults into Theia secret storage / env. +5. Re-implement the PDF custom editor as a Theia widget if the compat layer can't host it. +6. Port only the hotspot panels to native Theia widgets as needed. + +--- + +## 6. Verification done for this inventory + +- Reconstructed full source tree (427 files) from git object `548b2cc6^` via `git archive`. +- Parsed `package.json` programmatically: commands/views/menus/config/keybindings/customEditors/languages. +- Cross-checked declared vs registered commands (64 declared, ~79 registered incl. 15 internal; the 9 "declared-not-in-extension.ts" are registered by secondary register-functions — confirmed live). +- Confirmed `_future/` has 0 importers (dormant). +- Read top-of-file doc comments for every major module to confirm purpose. +- Grep'd for all `*.portugalfuturista.org` hosts, LAN IPs, spawn/execFile sites, transports, and the OTA/CI deploy path. + +**Not done (needs live repo / network):** confirm whether the extracted independent `aurelio-vscode` repo has advanced past v0.12.0 since 2026-06-21; confirm current Theia VS Code-compat coverage for `CustomEditorProvider` and webview CSP; confirm which hosts are reachable from the Theia back-end network namespace. + +--- + +## 7. File list (reconstructed baseline, `/tmp/aurelio-vscode-0.12.0/`) + +Key entry points and the largest files to port first: +- `src/extension.ts` (1626 LOC) — activation, registers everything, background sync loop, status bars. +- `src/webview/controlCenterPanel.ts` (3229) — 16-tab cockpit host (~95 message handlers). +- `src/webview/chatPanel.ts` (2620) — chat + slash commands + streaming + tool/approval flow. +- `src/models/modelRouter.ts` — 7-backend routing + fallback chain. +- `src/core/nativeEngine.ts` — dirac spawn + respawn + eval gates. +- `src/core/remoteServer.ts` — WS control server :34567. +- `src/mcp/mcpHub.ts`, `src/mcp/McpServerManager.ts`, `src/mcp/mcpRegistrySync.ts` — MCP SSE/stdio. +- `src/sync/proxmoxSync.ts`, `src/sync/wikiSync.ts` — brain + wiki sync. +- `src/hardware/*.ts` (6 bridges) + `src/electronics/remoteEdaClient.ts`. +- `src/evolution/*.ts` (7 files, only tested subsystem). +- `src/quarkdown/*` — embedded language + LSP + preview + PDF. +- `package.json` — 123 settings, 64 commands, 6 views, 1 custom editor, 1 language. + +--- + +## 8. Open questions before freezing scope + +1. Path to the live `aurelio-vscode` independent repo (post-extraction) — is v0.12.0 still current, or has it moved on? +2. Theia version target for the fork, and whether plugins run in the Node back-end or browser front-end (decides where dirac/serial/LSP can live). +3. Whether `aurelio.portugalfuturista.org` today is plain code-server serving this VSIX, and which of the 13 backends are reachable from the new Theia host's network. +4. Keep Quarkdown + the hardware-lab panels in scope for v1 of the Theia fork, or stage them? diff --git a/docs/compose/plans/2026-07-10-aurelio-theia-porting-checklist.md b/docs/compose/plans/2026-07-10-aurelio-theia-porting-checklist.md new file mode 100644 index 00000000..8bc73e32 --- /dev/null +++ b/docs/compose/plans/2026-07-10-aurelio-theia-porting-checklist.md @@ -0,0 +1,226 @@ +# Aurelio → Theia: Per-Feature Porting Checklist + +Companion to `2026-07-10-aurelio-theia-migration-feature-inventory.md`. Baseline: `aurelio-vscode` **v0.12.2 (live `main`, `b37e9d2`)** cloned to `~/portugalfuturista/aurelio-vscode`; Theia fork `aurelio-theia` **v0.1.0 (`f8bed07`)** at `~/portugalfuturista/aurelio-theia`. See `2026-07-10-aurelio-theia-live-delta.md` for the measured numbers and the skeleton's current state. Risk ratings below remain static-analysis estimates pending the Wave 0 spike. + +**How to read this:** one row per feature, with the VS Code API it leans on, the Theia target, a risk rating, a recommended path (A = run VSIX in Theia's VS Code plugin host, B = native Theia rewrite, C = hybrid), a porting owner, and a definition-of-done. Risk = chance the VS Code-compat layer can't host it unchanged. + +| Risk | Meaning | +|---|---| +| LOW | Theia's `@theia/plugin-ext` covers it; expect config-only changes. | +| MED | Covered but with known caveats (CSP, lifecycle, messaging); needs testing + minor shim. | +| HIGH | Incomplete/unsupported in compat layer, or depends on local process/serial; needs backend move or rewrite. | +| BLOCK | Cannot work in a browser-hosted plugin at all — must move to backend/gateway. | + +**Global findings that color every row below** +- Extension uses ~55 distinct `vscode.*` surfaces; heaviest: `vscode.window` (418 hits), `vscode.commands` (133), `vscode.workspace` (132), `vscode.Uri` (116), webview `postMessage` (361 references across 25 webview sites). +- Node built-ins (`fs`/`child_process`/`http`/`os`/`crypto`/`ws`) are imported in **46 source files**. Anything in that set that runs in a browser-hosted Theia plugin breaks; it must run in the Theia **backend** or be proxied. +- Local-process spawns: `dirac` (bundled Rust), `python3 -m esptool`, `python3` (PPK2), `sigrok-cli`, `ngspice/ltspice/psim`, `quarkdown` LSP, `gcloud`, `git`, `ollama` (HTTP). Plus CDP browser on :9222. +- 3 API keys are plaintext defaults in `package.json` (antigravity / agyIde / agyLsp) — rotate to secret storage, do not port as-is. +- `src/_future/*` (semantic cache, tool policy, voice) = 0 importers → intentionally dormant; carry, label, do not port in v1. + +--- + +## A. Shell, activation, settings, commands, views + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| A1 | Activation + lifecycle (`onStartupFinished`) | `extension.ts` (1626) | `ExtensionContext`, `subscriptions`, `setInterval` bg loop | `@theia/plugin-ext` activation events | LOW | A | Platform | Extension activates on Theia startup; background sync loop runs; dispose cleans timers | +| A2 | 3-tier config cascade (global→workspace→realm) | `config/configResolver.ts` (810), `settingsService.ts` | `vscode.workspace.getConfiguration`, `ConfigurationTarget`, `fs` reads of `~/.aurelio`, `.aurelio/`, `realms/*/.aurelio` | Theia preferences + `fs` (backend) | MED | C (A shim for prefs; B for cascade files) | Platform | All 123 keys resolve with correct precedence; realm overrides win | +| A3 | 123 settings keys (`aurelio.*`, `quarkdown.*`) | `package.json` | `contributes.configuration` | Theia preference schema | LOW | A (schema auto-mapped) | Platform | Settings UI shows all keys; defaults preserved except 3 rotated keys | +| A4 | 64 declared commands + palette | `extension.ts`, `coordinator/coordinator.ts`, `context/speculation/*`, `context/contextCommands.ts`, `quarkdown/extension.ts` | `vscode.commands.registerCommand`, `menus.commandPalette` | `@theia/plugin` CommandRegistry | LOW | A | Platform | Every command appears in palette and executes; `when` clauses honored | +| A5 | Activity-bar container + 6 sidebar views | `package.json`, `brain/sessionProvider.ts`, `brain/chronicleProvider.ts`, `brain/immichProvider.ts` | `viewsContainers`, `TreeDataProvider`, `registerWebviewViewProvider` | Theia view containers + tree + webview view | LOW | A | Frontend | All 6 views render; refresh/inline actions work | +| A6 | Status bar items (context + Hermes) | `extension.ts:323-334` | `createStatusBarItem`, `StatusBarAlignment` | Theia status bar | LOW | A | Frontend | Both items show, click commands fire | +| A7 | Keybindings (Quarkdown) | `package.json` | `contributes.keybindings` | Theia keybindings | LOW | A | Platform | `shift+ctrl+v` / `ctrl+alt+p` trigger on `.qd` | +| A8 | `when`-clause contexts | package.json menus | `setContext`, `viewItem ==` | Theia context keys | MED | A (verify parity) | Platform | Contextual menus show/hide correctly | +| A9 | Output channels / diagnostics / progress | several | `OutputChannel`, `ProgressLocation`, `DiagnosticSeverity` | Theia output + problems + progress | LOW | A | Frontend | Logs stream; progress notifications appear | + +--- + +## B. Chat, model routing, agent policy + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| B1 | Chat webview (streaming, tool calls, queue) | `webview/chatPanel.ts` (2620) | `WebviewPanel`, `postMessage`/`onDidReceiveMessage`, CSP, `asWebviewUri` | Theia webview (compat) | MED | A (verify CSP) | Frontend | Streaming tokens render, tool-call UI pauses/resumes, pending queue drains | +| B2 | Slash-command palette | `chatPanel.ts:806-825` | webview DOM | same webview | LOW | A | Frontend | `/local /hermes /vertex /openrouter /antigravity /kimi /jules /run /workflow` route | +| B3 | ModelRouter (7 backends + fallback) | `models/modelRouter.ts` (470) | `fetch` (Ollama/OpenRouter/Hermes), `google-auth-library` (Vertex), SDKs (Kimi/Jules) | backend Node service (network) | MED | C | Models | Each backend returns a completion; fallback chain `local→hermes→vertex→openrouter→antigravity` works; streaming where supported | +| B4 | Ollama (local) | `modelRouter.ts:92-106` | `fetch http://127.0.0.1:11434` | backend fetch to host Ollama | LOW | A/C | Models | `/api/tags` + generate reachable from Theia backend | +| B5 | Hermes 3 (LAN 192.168.0.105:8200) | `modelRouter.ts` | `fetch` | backend fetch | MED | A/C | Models | Reachable from Theia backend net namespace; OpenAI-compatible stream OK | +| B6 | Vertex AI (Gemini) | `models/vertexAuth.ts` | `google-auth-library`, `gcloud` | backend + `gcloud` present | MED | C | Models | Auth via ADC/key; `gemini-2.5-pro` infer works | +| B7 | OpenRouter | `modelRouter.ts` | `fetch` + `aurelio.openRouterApiKey` | backend fetch, key from secret | LOW | A/C | Models | Key moved to secret storage; infer works | +| B8 | Kimi (Moonshot) | `models/kimiClient.ts` | `fetch`/SDK, `fs` | backend | MED | C | Models | Non-streaming infer works; `KIMI_API_KEY` from env/secret | +| B9 | Jules (Google) | `models/julesClient.ts` (SDK) | `@google/jules-sdk` | backend | MED | C | Models | dispatch/cancel/history/resume/list work; `JULES_API_KEY` from secret | +| B10 | Antigravity delegation | `modelRouter.ts` case + `antigravity/*`, `gyro/*` | `fetch` to `antigravity.portugalfuturista.org`, gRPC, CDP | backend + CT 212 | HIGH | C | Models/Infra | Remote IDE reachable; sendPrompt/screenshot/screencast work | +| B11 | Heterónimos (personas + per-persona memory) | `models/heteronimoManager.ts` (170) | `fs` frontmatter parse, `gray-matter` | backend `fs` | MED | C | Models | Personas load from cascade dirs; switch updates active model routing | +| B12 | ApprovalGate (allow/deny/ask, terminal sandbox) | `utils/approvalGate.ts` (733) | `EventEmitter`, `vscode.window` warnings | Theia dialogs + event bus | MED | C | Agent | Risky tool/terminal calls prompt; allow/deny/ask lists honored; `agent.reviewPolicy` enforced | +| B13 | Idempotency layer | `models/idempotencyLayer.ts` | none (pure) | same | LOW | A | Models | Retried requests dedupe | +| B14 | Review-changes diff flow | `chatPanel.ts` | `WorkspaceEdit`, `applyEdit` | Theia workspace edit | MED | A | Agent | Proposed edits preview + apply/undo | +| B15 | `vscode.lm` usage (sessionMemory) | `context/sessionMemory/sessionMemory.ts:253-280` | `vscode.lm.selectChatModels`, `LanguageModelChat.sendRequest` | **No direct Theia equivalent** | HIGH | B (reroute through ModelRouter) | Models | sessionMemory no longer calls `vscode.lm`; uses ModelRouter instead | + +> B15 is the single concrete `vscode.lm` consumer — Theia's compat layer does not provide the Language Model API. Must reroute to the internal ModelRouter. + +--- + +## C. Control Center + webviews + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| C1 | Control Center host (16 tabs, ~95 msg cases) | `webview/controlCenterPanel.ts` (3229) | `WebviewPanel`, `retainContextWhenHidden`, `localResourceRoots`, `postMessage` | Theia webview (compat) | MED | A (CSP verify) | Frontend | All 16 tabs mount; tab switch preserves state; message round-trips OK | +| C2 | Svelte bundles (control-center/settings/pdf) | `webview-ui/**` (47 files) | `asWebviewUri`, Vite build to `dist/webviews` | Theia webview static serving | MED | A (build path) | Frontend | Vite outputs served via Theia webview URI; CSP allows the bundled JS | +| C3 | Bússola / Orchestration tabs | `tabs/OrchestrationTab.svelte` | webview | same | LOW | A | Frontend | Dashboard renders; actions dispatch | +| C4 | Motores (MCP) tab | `tabs/McpTab.svelte` + `mcp/*` | webview ↔ MCP hub | same + backend MCP | MED | C | MCP | connect/reconnect/ping/toggle/call/setServerRealms work | +| C5 | Antigravidade tab | `tabs/AntigravityTab.svelte` + `gyro/*`, `antigravity/*` | webview + CDP/gRPC | backend to CT 212 | HIGH | C | Infra | See B10 + G-group | +| C6 | Arquivo de Orpheu (Knowledge) | `tabs/KnowledgeTab.svelte` | webview + annas/arxiv/libgen/obsidian/calibre/zotero | backend for indexers | MED | C | Knowledge | sync/open/extract/ingest/query work; vault paths configurable | +| C7 | Oficina Sensacionista (School) | `tabs/EscolaTab.svelte` + `tabs/escola/*` | webview | same | LOW | A | Frontend | grill-me / study-guide / cite / save / export / share work | +| C8 | Painéis / Dashboards launcher | `tabs/DashboardsTab.svelte` | webview | same | LOW | A | Frontend | Opens each dashboard panel | +| C9 | Perícias (Skills) | `tabs/SkillsTab.svelte` + `skills/skillLoader.ts` | webview + `fs` dir scan | backend dir scan | MED | C | Skills | Skills discovered from cascade dirs; dynamic commands register | +| C10 | Sessões / Crónicas / Frota / Processos | `tabs/{Sessions,Chronicles,Fleet,Workflows}Tab.svelte` | webview | same | LOW | A | Frontend | Lists render; fleet/finance/forecasting handlers return data | +| C11 | Electrónica / Laboratório / Impressoras | `tabs/{Electronics,Lab,Printers}Tab.svelte` | webview + EDA/hardware | backend/gateway | HIGH | C | Hardware | See E-group / F-group | +| C12 | Engrenagens (Settings) | `settings-svelte/*` (10 sections) | webview | same | LOW | A | Frontend | 10 sections edit the 123 keys; save persists to correct tier | +| C13 | Artifact preview / session history / immich browser / chronicle panel | `webview/{artifactPreview,sessionHistoryPanel,immichBrowserPanel,chroniclePanel}.ts` | webview | same | LOW–MED | A | Frontend | Each opens + populates | + +**Webview cross-cutting risks (apply to all C-rows):** CSP strictness in Theia differs from VS Code — verify `script-src`/`connect-src` for the Svelte bundles and the `*.portugalfuturista.org` fetches; `asWebviewUri` path mapping for `dist/webviews/assets` (pdf.worker); `retainContextWhenHidden` semantics. + +--- + +## D. Brain, sessions, sync, wiki, memory, context + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| D1 | BrainManager (sessions + fallback dirs) | `brain/brainManager.ts` (250) | `fs` of `~/.gemini/antigravity/brain`, `~/.kimi/sessions` | backend `fs` | MED | C | Brain | Lists/deletes conversations across all 3 sources | +| D2 | Session continuity | `brain/sessionContinuity.ts` | `onDidChangeActiveTextEditor`, `fs` | Theia editor events + backend fs | MED | C | Brain | Editor state captured on switch; restored on return | +| D3 | Chronicle | `brain/chronicleManager.ts`, `chronicleProvider.ts` | `fs`, tree | backend `fs` | MED | C | Brain | Add/open/refresh entries persist | +| D4 | Immich | `sync/immichClient.ts`, `brain/immichProvider.ts`, `webview/immichBrowserPanel.ts` (755) | `fetch` to Immich, `fs` import | backend fetch | MED | C | Brain | Browse/import from `photos.portugalfuturista.org`; keys from secret | +| D5 | Proxmox brain sync (push/pull/list + 5-min loop) | `sync/proxmoxSync.ts` (200) | `fetch` to `mcp.portugalfuturista.org/api/brain/*`, `createFileSystemWatcher` | backend fetch + Theia watcher | MED | C | Brain | pushAll/pullAll/list work; background loop interval honored; watcher triggers | +| D6 | Wiki sync (Git-backed) | `sync/wikiSync.ts` (300) | `git` spawn, `fs`, watcher, sibling-repo discovery | backend `git` + `fs` | HIGH | C | Brain | Discovers `olivrododesassossego`; push/pull/export/status; needs `git` in backend image | +| D7 | Session export | `sync/sessionExporter.ts` | `fs` JSONL/JSON | backend `fs` | LOW | A/C | Brain | Sessions serialize to brain dir | +| D8 | Memory index/scan/search/extract | `memory/*` (932) | `fs`, `gray-matter` | backend `fs` | MED | C | Memory | Frontmatter-typed memories index; search works; throttled extraction runs | +| D9 | Compactor | `context/compactor.ts` (260) | tokenizer (dirac or TS fallback) | backend | MED | C | Memory | Auto-compact at 0.85 / 128k | +| D10 | AutoDream | `context/autoDream.ts` (290) | `setInterval`, `fs`, ModelRouter | backend | MED | C | Memory | Consolidation fires after minHours/minSessions | +| D11 | Away summary | `context/awaySummary.ts` | `onDidChangeWindowState` | Theia window-state event | MED | A | Memory | Recap shows on focus return | +| D12 | Session memory service | `context/sessionMemory/*` | `vscode.lm` (see B15), `fs` | backend + ModelRouter | HIGH | C | Memory | Rerouted off `vscode.lm`; per-session memory writes | +| D13 | MagicDocs | `context/magicDocs.ts` | `fs`, watcher | backend | MED | C | Memory | Docs auto-update | +| D14 | ContextScout / ExternalScout / PromptSuggestion | `context/{contextScout,externalScout,promptSuggestion}.ts` | `fs`, `fetch`, `executeWorkspaceSymbolProvider` | backend + Theia symbol providers | MED | C | Memory | Repo + web scouting; prompt suggestions populate | +| D15 | Speculative execution | `context/speculation/*` (engine/fs/commands) | `WorkspaceEdit`, `applyEdit`, speculative FS | Theia workspace edit | MED | C | Agent | start/accept/abort; edits apply+save; rollback clean | +| D16 | LSP client (generic) | `context/lspClient.ts` | `vscode-languageclient`, `WorkspaceEdit` | Theia LSP client | MED | A/C | Platform | Hover/refs/symbols/code-actions route through Theia | + +--- + +## E. MCP + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| E1 | MCP hub (SSE + stdio) | `mcp/mcpHub.ts` (145) | `@modelcontextprotocol/sdk` `SSEClientTransport`/`StdioClientTransport` | backend Node (SSE dominant; stdio only if backend-local) | MED | C | MCP | Remote servers (`*.portugalfuturista.org`) connect via SSE; reconnect backoff works | +| E2 | Server manager + health + realm assignment | `mcp/McpServerManager.ts` (220) | `createFileSystemWatcher` of `mcp_config.json`, `fs` | backend | MED | C | MCP | Config watch reloads; per-realm assignment persists | +| E3 | Registry sync + "add recommended" | `mcp/mcpRegistrySync.ts` | `fetch` registry | backend fetch | LOW | A/C | MCP | Registry loads; recommended server installable | +| E4 | Tool enable/disable + call routing | `mcpHub.ts`, `controlCenterPanel.ts` | webview messages | same | LOW | A | MCP | `mcp:call` returns result/error; per-tool toggle persists | + +--- + +## F. Hardware / lab / EDA + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| F1 | ESP32 fleet (esptool) | `hardware/esp32Bridge.ts` (spawns `python3 -m esptool`, scans `/dev/ttyUSB*`) | `child_process.spawn`, serial | **BLOCK in browser** → lab gateway (CT 206) / backend | BLOCK/HIGH | C (move behind `lab-gw`) | Hardware | Device scan/flash/read routed via gateway; no serial from front-end | +| F2 | PPK2 battery lab | `hardware/ppk2Bridge.ts` (python3) + `webview/ppk2Dashboard.ts` | spawn, serial `/dev/ttyACM0` | gateway/backend | BLOCK/HIGH | C | Hardware | Sampling streams via gateway; dashboard charts render | +| F3 | sigrok logic analyzer | `hardware/sigrokBridge.ts` (spawns `sigrok-cli`) + `webview/logicAnalyzerDashboard.ts` | spawn, `execSync` | gateway/backend | BLOCK/HIGH | C | Hardware | Capture/decode → CSV via gateway; viewer plots | +| F4 | KiCad | `hardware/kicadBridge.ts` + `webview/schematicViewer.ts` (604) | `fs`, `createFileSystemWatcher`, `execFile` | backend `fs` (+ `.kicad` CLI if used) | HIGH | C | Hardware | Project/net/DRC parse; schematic viewer renders; watcher works | +| F5 | FMU co-sim | `hardware/fmiBridge.ts` + `webview/fmuViewer.ts` (434) | `execFile` (Reference-FMUs) | backend | HIGH | C | Hardware | FMU loads + steps via backend; plots render | +| F6 | PSIM / SPICE (ngspice/ltspice) | `hardware/psimBridge.ts` + `webview/{psimViewer,spiceViewer}.ts` | spawn sims | backend/gateway (or remote EDA) | HIGH | C | Hardware | Sim runs server-side; waveforms stream/plot | +| F7 | Remote EDA offload | `electronics/remoteEdaClient.ts` (317) | `fetch https://eda.portugalfuturista.org` | backend fetch | LOW | A/C | Hardware | `/sim/{spice,erc,power-rails,parse,convert,bom,bom/optimize}` reachable; token from secret | +| F8 | Engineering hub + hardware + HIL dashboards | `webview/{engineeringHub,hardwareDashboard,hilDashboard}.ts` | webview + `hil.portugalfuturista.org` | webview + backend | MED | C | Hardware | HUB launches; HIL logs fetch via backend | +| F9 | Sourcing / coverage / guarda-livros / bolsa dashboards | `webview/{sourcingDashboard,coverageDashboard,guardaLivrosDashboard,bolsaDoMundial}.ts` | webview + `api.portugalfuturista.org` | webview + backend fetch | MED | C | Hardware/Portal | Search/alternates/optimize, coverage load, accounting sync, fantasy-market orders route via backend | + +> F-group is the highest-risk cluster: serial/local-process bridges cannot run in a browser-hosted Theia plugin. Decision needed (section 6): full gateway proxy vs. backend-local vs. drop from v1. + +--- + +## G. Antigravity / Gyro (remote IDE control) + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| G1 | AgyIde (CDP bridge REST) | `gyro/agyIdeService.ts` | `fetch` to `antigravity.portugalfuturista.org:8900` | backend → CT 212 | HIGH | C | Infra | connect/screenshot/screencast/sendPrompt/quickAction/autoAccept work | +| G2 | AgyLsp (self-hosted LS) | `gyro/agyLspService.ts`, `antigravity/antigravityLsBridge.ts` | `fetch` to `agy-lsp.portugalfuturista.org:8902`, `fs` | backend | HIGH | C | Infra | listTools/executeTool/quota/sendPrompt work | +| G3 | gRPC + OAuth injection | `core/diracClient.ts:135-150` | gRPC, `fetch` token inject | backend | HIGH | C | Infra | startSelfHosted + injectOAuthToken succeed; TLS toggle honored | +| G4 | Dedup legacy `antigravity/` vs `gyro/` | both dirs | — | consolidate to `gyro/` | MED | B | Models | Single Antigravity stack; control center uses one service | + +> The two near-duplicate Antigravity stacks (`antigravity/` 562 LOC, `gyro/` 554 LOC) are both wired. Porting is the right moment to consolidate to one. + +--- + +## H. Coordinator, workflows, skills, evolution, native engine + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| H1 | Coordinator (autonomous workers) | `coordinator/*` (1008) | `registerCommand`, ModelRouter, `fs` | backend | MED | C | Agent | start/status/finalize/task run; worker dispatch via ModelRouter | +| H2 | Workflows | `workflow/workflowManager.ts` (526) | `registerCommands`, `fs` | backend | LOW | A/C | Agent | Named workflows register + execute | +| H3 | Skills (dir-based, cascade) | `skills/skillLoader.ts` (265) | `fs` dir scan, dynamic `registerCommand` | backend `fs` + Theia commands | MED | C | Skills | Skills load from global→workspace→realm; dynamic commands register | +| H4 | Evolution loop (MAP-Elites) | `evolution/*` (2887) | dirac `NativeEngine`, `setInterval`, `fs` (sandbox/snapshots) | backend + dirac | HIGH | C | Evolution | mutate→evaluate→insert runs; convergence detected; **the only tested subsystem — keep its mocha suite green under Theia** | +| H5 | NativeEngine (dirac spawn + respawn) | `core/nativeEngine.ts` (520) | `child_process.spawn` of `native/dirac/target/release/dirac`, JSON-lines stdio, respawn budget | backend Node (binary must ship in Theia backend image) | HIGH/BLOCK | C | Evolution/Platform | dirac binary present for target arch; spawn + JSON-lines + respawn work; TS fallbacks engage if absent | +| H6 | Remote control WS server (:34567) | `core/remoteServer.ts` (100) | `http.createServer` + `ws` + ApprovalGate | backend HTTP/WS | HIGH | C | Platform | Server binds backend-side; external clients connect; ApprovalGate enforced | +| H7 | DiracClient gRPC | `core/diracClient.ts` (150) | gRPC self-hosted | backend | HIGH | C | Platform | compile_ast/evolve/ag.* requests route | + +--- + +## I. Quarkdown (embedded language) + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| I1 | Language + grammar + config | `syntaxes/`, `language-configuration.json`, `package.json` | `contributes.languages/grammars` | Theia languages/textmate | LOW | A | Quarkdown | `.qd` files highlight + bracket config | +| I2 | LSP client (vscode-languageclient/node) | `quarkdown/client.ts` | `LanguageClient` (node), `documentSelector`, `fileEvents` watcher | Theia LSP client | MED | A/C | Quarkdown | Diagnostics/completion for `.qd` | +| I3 | LSP server process | `quarkdown/core/{quarkdownServer,processManager}.ts` | spawn `quarkdown` | backend spawn (needs `quarkdown` in image) | HIGH | C | Quarkdown | Server starts backend-side; restarts on command | +| I4 | Live preview webview | `quarkdown/{previewManager,previewWebview}.ts`, `core/httpPoller.ts` | webview + `http` poller | Theia webview + backend poll | MED | C | Quarkdown | `shift+ctrl+v` live preview updates | +| I5 | PDF export | `quarkdown/{pdfExport,core/pdfExportService}.ts` | spawn/export | backend | MED | C | Quarkdown | `ctrl+alt+p` exports PDF | + +--- + +## J. PDF custom editor + OTA + infra glue + +| # | Feature | Source (LOC) | VS Code API | Theia target | Risk | Path | Owner | Done when… | +|---|---|---|---|---|---|---|---|---| +| J1 | PDF/EPUB custom editor | `webview/pdfCustomEditorProvider.ts` (`CustomReadonlyEditorProvider`), `pdfViewerPanel.ts` (541), `pdf-viewer-svelte/*`, `pdfjs-dist` | `CustomEditorProvider`, webview, worker | **Theia compat: CustomEditor is historically weak** → native Theia widget | HIGH | B (likely) | Frontend | `*.pdf`/`*.epub` open in a Theia widget with pdf.js; pan/zoom/search work | +| J2 | OTA self-update (VSIX) | `updater/otaUpdater.ts` (166) + CI `.github/workflows/build.yml` | `fetch version.json`, `vsce package`, SCP to CT 205 | **Replace** with Theia plugin deployment (image-baked or Theia plugin registry) | HIGH | B | Platform | Update channel redesigned; no `vsce`/VSIX dependency; version check still works against a Theia-appropriate manifest | +| J3 | Prevent-sleep | `utils/preventSleep.ts` | `fs`/power | backend/no-op in browser | MED | C | Platform | Behavior defined for browser context (likely no-op or backend keepalive) | +| J4 | AurelioRead / Toon utils | `utils/aurelioRead.ts`, `utils/toon.ts` | `fs`, pure TS | backend / same | LOW | A | Platform | Read helper + toon encode/decode work | + +--- + +## K. Secrets, network, packaging (cross-cutting) + +| # | Concern | Where | Action | Risk | Owner | +|---|---|---|---|---|---| +| K1 | 3 plaintext API keys in `package.json` defaults (`antigravity.apiKey`, `agyIde.apiKey`, `agyLsp.apiKey`) | manifest | Move to Theia secret storage / env; rotate the shared 64-hex token | HIGH | Platform/Infra | +| K2 | `KIMI_API_KEY`, `JULES_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `aurelio.openRouterApiKey`, `aurelio.hub.apiToken`, `aurelio.electronics.remoteSimToken`, `aurelio.immich.apiKey`, `aurelio.hub.cfClientId/Secret` | settings / `.env` | Inject via backend env + Theia secret store; never ship in image | HIGH | Platform | +| K3 | Backend network reachability to 13 `*.portugalfuturista.org` hosts + LAN `192.168.0.105/.54/.55` | all `fetch`/spawn sites | Confirm Theia backend pod/host can route; document egress | MED | Infra | +| K4 | Native binaries in image (`dirac`, `git`, `python3`+esptool, `sigrok-cli`, `ngspice`/`ltspice`/`psim`, `quarkdown`, `gcloud`) | `native/`, spawns | Decide: bake into Theia backend image vs. proxy via lab gateway | HIGH | Infra | +| K5 | Build system (webpack extension + Vite webviews → `dist/`) | `package.json` scripts, `webpack.config.cjs`, `vite.config.ts` | Keep for Path A; repackage as Theia plugin for B/C | MED | Platform | +| K6 | `@aurelio/shared` (file:../../shared) protobuf dep | `package.json` | Ensure shared lib available to Theia plugin build | MED | Platform | +| K7 | Dormant `_future/` (semantic cache, tool policy, voice) | `src/_future/*` | Carry over labeled POSTPONED; do not port in v1 | LOW | Platform | + +--- + +## 6. Key decision points (need answers before/early in the port) + +1. **Plugin hosting side:** do Theia plugins run in the Node backend or the browser frontend on `aurelio.portugalfuturista.org`? This single decision resolves every BLOCK/HIGH row (F-group serial, H5 dirac, H6 WS server, I3 quarkdown LSP). +2. **Hardware scope for v1:** drop the serial/serial-spawn panels (F1–F6) from v1, or commit to routing them through `lab-gw.portugalfuturista.org` (CT 206)? EDA (F7) is already remote and LOW-risk. +3. **Custom editor (J1):** accept Theia's CustomEditor compat if it works, or budget a native pdf.js widget now? +4. **OTA (J2):** image-baked plugin vs. Theia plugin registry — pick the deployment mechanism; remove `vsce`. +5. **Antigravity dedup (G4):** consolidate `antigravity/` + `gyro/` to one stack during the port. +6. **`vscode.lm` (B15/D12):** reroute sessionMemory through ModelRouter — confirm no other `vscode.lm` consumers appear in the live repo. + +## 7. Suggested sequencing + +- **Wave 0 (spike):** stand up Theia fork, enable plugin host, drop in `aurelio-0.12.0.vsix`, smoke-test A/C rows; produce the empirical gap list that upgrades these risk ratings from "estimated" to "measured." +- **Wave 1 (backend spine):** config cascade (A2), secrets (K1/K2), ModelRouter (B3–B9), brain+sync+wiki+memory (D-group), MCP (E-group) — all backend, all testable headlessly. +- **Wave 2 (cockpit):** control center + chat webviews (B1/B2, C-group) behind the verified backend spine; fix CSP/`asWebviewUri`. +- **Wave 3 (specialized):** evolution+dirac (H4/H5), Quarkdown (I), PDF (J1), Antigravity (G), OTA redesign (J2). +- **Wave 4 (lab):** hardware/serial (F) behind gateway, per decision point 2. + +## 8. Owners legend + +Platform = shell/activation/settings/build/deploy · Frontend = webviews/views/widgets · Models = routing/personas/LM · Agent = coordinator/approval/speculation · Brain = sessions/sync/wiki · Memory = context/memory · MCP = MCP · Hardware = lab/EDA · Infra = network/secrets/CT routing · Evolution = dirac/MAP-Elites · Quarkdown · Skills · Knowledge · Portal + +--- + +## 9. Verification status of this checklist + +Risk ratings are **estimated from static analysis** of the v0.12.0 source (API grep, node-built-in import map, spawn sites, transports, doc-comments) — not from running against Theia. The Wave 0 spike is required to convert estimates into measured results. Counts (API hits, LOC, file lists) are measured from the reconstructed tree. diff --git a/docs/compose/plans/2026-07-10-proxmox-new-server-migration.md b/docs/compose/plans/2026-07-10-proxmox-new-server-migration.md new file mode 100644 index 00000000..a3ede175 --- /dev/null +++ b/docs/compose/plans/2026-07-10-proxmox-new-server-migration.md @@ -0,0 +1,445 @@ +# Proxmox New Server Migration — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use compose:subagent (recommended) or compose:execute to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add a new mid-range server to the Proxmox cluster and migrate CTs 208, 212, 213, 216 from ASUS to relieve the 55.5 GB overcommit on a 16 GB host. + +**Architecture:** Join the new server as a 3rd node in the `portugalfuturi` cluster. Migrate CTs via vzdump backup + restore. Update Cloudflare tunnel routes, MCP registry, sync scripts, and proxy backends to new IPs. + +**Tech Stack:** Proxmox VE, Corosync, Cloudflare Tunnel, Python sync scripts, Node.js proxy server + +## Global Constraints + +- ASUS host: 192.168.0.38 (current primary, must remain operational during migration) +- Gigabyte host: 192.168.0.104 (existing cluster node) +- New server IP: TBD (must be on 192.168.0.x subnet, outside DHCP range) +- All Cloudflare routes use hostnames — only origin IPs change +- Brain sync (`sync.py`) uses `pct push`/`pct pull` via SSH to ASUS — must verify this still works after migration +- CT 208 should be downsized from 8 GB to 2 GB (only uses 72 MB) + +--- + +### Task 1: Pre-migration snapshot and backup + +**Covers:** [S4] + +**Files:** +- Modify: None (operational commands only) + +**Verification:** +- Run: `ssh root@192.168.0.38 "pct list"` — all CTs listed +- Run: `ssh root@192.168.0.38 "vzdump 208 --storage local --compress zstd --dumpdir /tmp/vzdump/"` — backup created + +- [ ] **Step 1: Verify current CT state on ASUS** + +```bash +ssh root@192.168.0.38 "pct list" +``` + +Expected: CTs 207, 208, 209, 212, 213, 214, 215, 216, 220 listed as running. + +- [ ] **Step 2: Create vzdump backups of CTs to migrate** + +```bash +ssh root@192.168.0.38 "mkdir -p /tmp/vzdump && vzdump 208 --storage local --compress zstd --dumpdir /tmp/vzdump/" +ssh root@192.168.0.38 "vzdump 212 --storage local --compress zstd --dumpdir /tmp/vzdump/" +ssh root@192.168.0.38 "vzdump 213 --storage local --compress zstd --dumpdir /tmp/vzdump/" +ssh root@192.168.0.38 "vzdump 216 --storage local --compress zstd --dumpdir /tmp/vzdump/" +``` + +Expected: 4 `.tar.zst` files in `/tmp/vzdump/` on ASUS. + +- [ ] **Step 3: Verify backups exist** + +```bash +ssh root@192.168.0.38 "ls -la /tmp/vzdump/" +``` + +Expected: 4 backup files, each non-empty. + +- [ ] **Step 4: Record current service state for rollback reference** + +```bash +ssh root@192.168.0.38 "for ct in 208 212 213 216; do echo \"CT \$ct:\"; pct exec \$ct -- systemctl list-units --type=service --state=running --no-pager 2>/dev/null | head -10; echo; done" +``` + +Expected: List of running services per CT. Save this output for comparison after migration. + +--- + +### Task 2: Install and join new server to cluster + +**Covers:** [S3] + +**Files:** +- Create: None (Proxmox installer + cluster join) + +**Verification:** +- Run: `corosync-cfgtool -s` on any node — shows 3 members +- Run: `pct list` on new node — operational + +- [ ] **Step 1: Install Proxmox VE on new server** + +Follow standard Proxmox VE installer. Assign static IP (e.g., 192.168.0.40 — verify no conflict first). + +```bash +# On ASUS, check for IP conflicts +ssh root@192.168.0.38 "arp-scan --localnet | grep 192.168.0.40" +``` + +Expected: No response (IP is free). + +- [ ] **Step 2: Add new node to cluster** + +On the new node, join the existing cluster: + +```bash +# On ASUS (existing node), get join info +ssh root@192.168.0.38 "pveam key --master 1" +``` + +On the new node: + +```bash +# Replace with output from step above +pvecm add 192.168.0.38 --key +``` + +- [ ] **Step 3: Verify cluster health** + +```bash +# On any node +corosync-cfgtool -s +pvecm status +pvecm nodes +``` + +Expected: 3 nodes listed (ASUS, Gigabyte, new), quorum achieved. + +- [ ] **Step 4: Verify new node is ready for CT restore** + +```bash +ssh root@ "pct list && pveam available | head -5" +``` + +Expected: Empty CT list, storage available. + +--- + +### Task 3: Migrate CTs to new node + +**Covers:** [S4] + +**Files:** +- None (operational commands) + +**Verification:** +- Run: `pct list` on new node — shows CTs 208, 212, 213, 216 +- Run: Service health checks on each CT + +- [ ] **Step 1: Transfer backups to new node** + +```bash +NEW_IP="192.168.0.40" # Replace with actual IP +scp /tmp/vzdump/vzdump-lxc-208-*.tar.zst root@${NEW_IP}:/tmp/ +scp /tmp/vzdump/vzdump-lxc-212-*.tar.zst root@${NEW_IP}:/tmp/ +scp /tmp/vzdump/vzdump-lxc-213-*.tar.zst root@${NEW_IP}:/tmp/ +scp /tmp/vzdump/vzdump-lxc-216-*.tar.zst root@${NEW_IP}:/tmp/ +``` + +- [ ] **Step 2: Restore CT 208 (Gabinete) with downsized RAM** + +```bash +ssh root@${NEW_IP} "pct restore 208 /tmp/vzdump-lxc-208-*.tar.zst --memory 2048 --hostname pf-gabinete-dos-heteronimos" +``` + +Expected: CT 208 created with 2 GB RAM. + +- [ ] **Step 3: Restore CT 212 (Antigravity)** + +```bash +ssh root@${NEW_IP} "pct restore 212 /tmp/vzdump-lxc-212-*.tar.zst --memory 8192 --hostname pf-antigravity" +``` + +- [ ] **Step 4: Restore CT 213 (Immich)** + +```bash +ssh root@${NEW_IP} "pct restore 213 /tmp/vzdump-lxc-213-*.tar.zst --memory 4096 --hostname pf-immich" +``` + +- [ ] **Step 5: Restore CT 216 (Management) with downsized RAM** + +```bash +ssh root@${NEW_IP} "pct restore 216 /tmp/vzdump-lxc-216-*.tar.zst --memory 4096 --hostname pf-management" +``` + +- [ ] **Step 6: Start all restored CTs** + +```bash +ssh root@${NEW_IP} "pct start 208 && pct start 212 && pct start 213 && pct start 216" +``` + +- [ ] **Step 7: Verify services on each CT** + +```bash +# CT 208 - Gabinete health +ssh root@${NEW_IP} "pct exec 208 -- curl -s http://localhost:18000/api/health" + +# CT 216 - Authentik +ssh root@${NEW_IP} "pct exec 216 -- systemctl status authentik --no-pager | head -5" + +# CT 212 - Antigravity +ssh root@${NEW_IP} "pct exec 212 -- curl -s http://localhost:8900/ 2>/dev/null | head -1 || echo 'CDP Bridge check needed'" + +# CT 213 - Immich +ssh root@${NEW_IP} "pct exec 213 -- curl -s http://localhost:2283/api/server/about 2>/dev/null | head -1 || echo 'Immich check needed'" +``` + +Expected: CT 208 returns health OK, CT 216 shows authentik active, others respond or are verifiable. + +- [ ] **Step 8: Stop migrated CTs on ASUS** + +```bash +ssh root@192.168.0.38 "pct stop 208 && pct stop 212 && pct stop 213 && pct stop 216" +``` + +- [ ] **Step 9: Verify ASUS resource improvement** + +```bash +ssh root@192.168.0.38 "free -h && uptime" +``` + +Expected: RAM usage drops significantly, load decreases. + +--- + +### Task 4: Update Cloudflare tunnel routes + +**Covers:** [S5] + +**Files:** +- Modify: `nervura-electrica/infrastructure/proxmox/config.yml` +- Modify: `/etc/cloudflared/config.yml` on ASUS (deployed copy) + +**Verification:** +- Run: `curl -s https://mcp.portugalfuturista.org/api/health` — returns OK +- Run: `curl -s https://auth.portugalfuturista.org` — returns Authentik page + +- [ ] **Step 1: Get new IP assignments for migrated CTs** + +```bash +ssh root@${NEW_IP} "pct exec 208 -- hostname -I" +ssh root@${NEW_IP} "pct exec 212 -- hostname -I" +ssh root@${NEW_IP} "pct exec 213 -- hostname -I" +ssh root@${NEW_IP} "pct exec 216 -- hostname -I" +``` + +Record the IPs. Update the variable below: + +``` +NEW_CT208_IP= +NEW_CT212_IP= +NEW_CT213_IP= +NEW_CT216_IP= +``` + +- [ ] **Step 2: Update config.yml origin IPs** + +Edit `nervura-electrica/infrastructure/proxmox/config.yml`: + +```yaml +# CT 208 → new node +- hostname: mcp.portugalfuturista.org + service: http://${NEW_CT208_IP}:18000 + +# CT 212 → new node +- hostname: antigravity.portugalfuturista.org + service: http://${NEW_CT212_IP}:8900 +- hostname: antigravity-ws.portugalfuturista.org + service: http://${NEW_CT212_IP}:8901 + +# CT 213 → new node +- hostname: photos.portugalfuturista.org + service: http://${NEW_CT213_IP}:2283 + +# CT 216 → new node +- hostname: auth.portugalfuturista.org + service: http://${NEW_CT216_IP}:9000 +- hostname: vault.portugalfuturista.org + service: http://${NEW_CT216_IP}:8088 +- hostname: scrobbler.portugalfuturista.org + service: http://${NEW_CT216_IP}:9078 +- hostname: maloja.portugalfuturista.org + service: http://${NEW_CT216_IP}:42010 +``` + +- [ ] **Step 3: Deploy updated config to Cloudflare tunnel** + +```bash +scp nervura-electrica/infrastructure/proxmox/config.yml root@192.168.0.38:/etc/cloudflared/config.yml +ssh root@192.168.0.38 "systemctl restart cloudflared" +``` + +- [ ] **Step 4: Verify tunnel is healthy** + +```bash +ssh root@192.168.0.38 "systemctl status cloudflared --no-pager | head -5" +``` + +Expected: Active (running). + +- [ ] **Step 5: Test critical routes** + +```bash +curl -s -o /dev/null -w "%{http_code}" https://mcp.portugalfuturista.org/api/health +curl -s -o /dev/null -w "%{http_code}" https://auth.portugalfuturista.org +curl -s -o /dev/null -w "%{http_code}" https://vault.portugalfuturista.org +curl -s -o /dev/null -w "%{http_code}" https://photos.portugalfuturista.org +``` + +Expected: All return 200 or 302 (redirect to login). + +--- + +### Task 5: Update MCP registry and sync scripts + +**Covers:** [S5] + +**Files:** +- Modify: `nervura-electrica/infrastructure/proxmox/services/gabinete/mcp_registry.json` +- Modify: `replica-omnisciente/.aurelio/sync.py` (if CT 208 target changes) +- Modify: `nervura-electrica/infrastructure/proxmox/services/gabinete/deploy_gabinete_208.sh` + +**Verification:** +- Run: `curl http://:18000/api/services` — returns spoke list +- Run: `python3 .aurelio/sync.py --push` — completes successfully + +- [ ] **Step 1: Update mcp_registry.json spoke URLs** + +Edit `nervura-electrica/infrastructure/proxmox/services/gabinete/mcp_registry.json`: + +Replace all `192.168.0.125` references with `${NEW_CT208_IP}` (the actual IP from Task 4). + +Also update the `savearth-mcp` URL if CT 212 moved (it was on `192.168.0.212`). + +- [ ] **Step 2: Update deploy_gabinete_208.sh** + +The deploy script uses `pct exec 208` on the Proxmox host. After migration, CT 208 lives on the new node. The script needs to target the new node: + +Edit `nervura-electrica/infrastructure/proxmox/services/gabinete/deploy_gabinete_208.sh`: + +```bash +# Change PROXMOX_HOST to new node IP +PROXMOX_HOST="${NEW_NODE_IP}" # was 192.168.0.38 +``` + +- [ ] **Step 3: Update sync.py if needed** + +Check if `sync.py` hardcodes CT 208 target. If it uses `pct push 208` on ASUS, it needs to either: +- SSH to the new node instead, or +- Use the cluster-aware approach (Proxmox cluster allows `pct` commands on any node for any CT) + +```bash +grep -n "208\|pct push\|pct exec" replica-omnisciente/.aurelio/sync.py +``` + +If `pct push 208` is hardcoded to ASUS, update the SSH target to the new node. + +- [ ] **Step 4: Update aurelio-web server.cjs proxy backends** + +Edit `nervura-electrica/infrastructure/proxmox/aurelio-web/server.cjs`: + +```javascript +// Update GABINETE_URL if CT 208 IP changed +const GABINETE_URL = process.env.GABINETE_URL || 'http://${NEW_CT208_IP}:18000'; +``` + +- [ ] **Step 5: Deploy updated aurelio-web** + +```bash +cd nervura-electrica/infrastructure/proxmox +./deploy-aurelio-web.sh +``` + +- [ ] **Step 6: Test brain sync** + +```bash +cd replica-omnisciente +python3 .aurelio/sync.py --push +``` + +Expected: Sync completes without errors. + +--- + +### Task 6: Post-migration cleanup and documentation + +**Covers:** [S6, S7] + +**Files:** +- Modify: `nervura-electrica/AGENTS.md` (update CT table, IPs, resource allocation) + +**Verification:** +- Run: `ssh root@192.168.0.38 "free -h"` — RAM usage < 4 GB +- Run: All Cloudflare endpoints return expected responses + +- [ ] **Step 1: Clean up /tmp on ASUS** + +```bash +ssh root@192.168.0.38 "rm -rf /tmp/vzdump/ /tmp/local_brain.tar.gz" +``` + +- [ ] **Step 2: Remove old CT configs from ASUS (optional, for cleanliness)** + +```bash +# Only if CT configs are cluttering; the CTs are stopped, not deleted +ssh root@192.168.0.38 "pct destroy 208 --purge" # Only after verifying migration success +``` + +Note: Do NOT run this until Task 4 and Task 5 verification passes completely. + +- [ ] **Step 3: Update AGENTS.md with new topology** + +Edit `nervura-electrica/AGENTS.md`: + +- Update CT table: CTs 208, 212, 213, 216 now on new node +- Update resource allocation: ASUS now ~4 GB used +- Add new server to physical infrastructure table +- Update Cloudflare tunnel documentation +- Update deployment commands (deploy scripts target new node) + +- [ ] **Step 4: Final verification sweep** + +```bash +# Cluster health +corosync-cfgtool -s +pvecm nodes + +# ASUS resources +ssh root@192.168.0.38 "free -h && uptime && df -h /" + +# All endpoints +for host in mcp auth vault photos antigravity; do + code=$(curl -s -o /dev/null -w "%{http_code}" https://${host}.portugalfuturista.org) + echo "${host}: ${code}" +done + +# Brain sync +cd replica-omnisciente && python3 .aurelio/sync.py --push +``` + +Expected: Cluster healthy, ASUS light, all endpoints responsive, sync works. + +- [ ] **Step 5: Commit documentation updates** + +```bash +cd nervura-electrica +git add AGENTS.md infrastructure/proxmox/config.yml infrastructure/proxmox/services/gabinete/ +git commit -m "ops: migrate CTs 208,212,213,216 to new cluster node + +- CT 208 (Gabinete): downsized 8GB → 2GB, moved to new node +- CT 216 (Management): downsized 8GB → 4GB, removed duplicate *arr apps +- Updated Cloudflare tunnel routes to new IPs +- Updated MCP registry spoke URLs +- Updated deploy scripts for new node target" +``` diff --git a/docs/compose/specs/2026-07-10-proxmox-new-server-migration-design.md b/docs/compose/specs/2026-07-10-proxmox-new-server-migration-design.md new file mode 100644 index 00000000..ce59e513 --- /dev/null +++ b/docs/compose/specs/2026-07-10-proxmox-new-server-migration-design.md @@ -0,0 +1,70 @@ +# Spec: New Server Integration — Proxmox Cluster Migration + +> Date: 2026-07-10 | Status: Approved | Scope: Proxmox datacenter expansion + +## [S1] Problem + +The ASUS host (192.168.0.38) is critically overcommitted: 55.5 GB RAM allocated across 14 CTs on 16 GB physical RAM, with swap exhausted and disk 93% full. Four CTs (208, 212, 213, 216) need to migrate to a new mid-range server (16-32 GB RAM) to relieve pressure and improve reliability. + +## [S2] Solution overview + +Add the new server as a 3rd node in the existing `portugalfuturi` Proxmox cluster. Migrate CTs 208, 212, 213, and 216 via vzdump backup + restore. Update all routing (Cloudflare tunnel, MCP registry, sync scripts, proxy backends) to point to new IPs. + +## [S3] Cluster join + +- Install Proxmox VE on new hardware +- Join cluster via `pct create` or cluster join command +- Assign static IP on 192.168.0.x subnet +- Corosync rebalances quorum automatically (2→3 nodes) +- Verify cluster health: `corosync-cfgtool -s` + +## [S4] CT migration + +| CT | Name | Current RAM | Target RAM | Services | +|----|------|-------------|------------|----------| +| 208 | Gabinete/MCP | 8 GB | 2 GB | FastAPI+FastMCP gateway, 14 MCP spokes, model router | +| 212 | Antigravity | 8 GB | 8 GB | Headless VS Code, CDP Bridge | +| 213 | Immich | 4 GB | 4 GB | Photo server (Docker-in-Docker) | +| 216 | Management | 8 GB | 4 GB | Authentik, Vaultwarden, Maloja, Multi-scrobbler | + +Migration steps per CT: +1. `vzdump --storage local --compress zstd` on ASUS +2. Transfer backup to new node +3. `pct restore --hostname --memory ` on new node +4. Start CT, verify services +5. Stop CT on ASUS + +Total RAM freed on ASUS: ~24 GB (from 55.5 GB allocated to ~31.5 GB) + +## [S5] Route updates + +Files requiring IP changes: + +| File | Current target | New target | +|------|---------------|------------| +| `nervura-electrica/infrastructure/proxmox/config.yml` | CT IPs on 192.168.0.x | New node IPs | +| `replica-omnisciente/.aurelio/mcp_config.json` | `*.portugalfuturista.org` URLs | Same hostnames, different origins | +| `nervura-electrica/infrastructure/proxmox/services/gabinete/mcp_registry.json` | 192.168.0.125 for CT 208 | New IP | +| `nervura-electrica/infrastructure/proxmox/aurelio-web/server.cjs` | Proxy backend IPs | New IPs | +| `replica-omnisciente/.aurelio/sync.py` | CT 208 target (192.168.0.38 → pct 208) | Verify still works via cluster | +| `nervura-electrica/infrastructure/proxmox/services/gabinete/deploy_gabinete_208.sh` | pct exec 208 on ASUS | May need to target new node | + +Note: Cloudflare tunnel routes use hostnames, not IPs. The tunnel config (`config.yml`) maps hostnames to origin IPs — only the origin IPs need updating. + +## [S6] ASUS post-migration + +After migration, ASUS runs only: +- CT 207 (Aurelio web, 2 GB) — React portal + code-server +- CT 215 (Matrix, 1 GB) — Synapse homeserver +- System overhead (~1 GB) + +Total: ~4 GB used of 16 GB — healthy headroom. + +## [S7] Verification + +1. Cluster health: `corosync-cfgtool -s` shows 3 nodes +2. All 4 CTs running on new node: `pct list` on new host +3. Cloudflare routes: curl each `*.portugalfuturista.org` endpoint +4. MCP health: `curl http://:18000/api/health` +5. Brain sync: `python3 .aurelio/sync.py --push` completes successfully +6. ASUS load: `uptime` shows load < 2.0