diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index 8a1fb285..b77c96c2 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -1,6 +1,6 @@ # ThothII — Project State -> Starting-point snapshot for new sessions. Last updated: 2026-07-14 (Pi-enabled model selector live). +> Starting-point snapshot for new sessions. Last updated: 2026-07-14 (Qwen connectivity and Resume recovery live). > Point a fresh session here ("read PROJECT_STATE.md") before substantial work. ## Deployment — Docker locale (Profile A, co-located) — LIVE 2026-07-12 @@ -81,6 +81,33 @@ ThothII gira in Docker sul server co-locato, **embedded nel portale omics_portal ID and running container image ID both equal `sha256:577f99754fd0731251c8ddd8608b1b8baee09d02fad66c759b23f8221083e676`. +### Qwen connectivity + state-aware Resume recovery — LIVE 2026-07-14 + +- **Pi turns have an explicit lifecycle.** The bridge tracks `idle`, `running`, `waiting`, + and `failed`; a reviewer gate is `waiting`, responses/steering return to `running`, and an + assistant provider error becomes `failed`. Provider error details are never forwarded to the + client; the UI receives a fixed sanitized recovery message. +- **Resume preserves only active work.** `running`/`waiting` runtimes return as already active. + `idle`/`failed` runtimes are torn down, their SSE buffer/subscribers are cleared, and the normal + cold path restarts from the persisted provider/model/thinking with `/riprendi-sessione`. A + successful Resume of the currently selected session also closes and recreates its EventSource, + so the replacement runtime cannot be left behind an old same-ID stream. +- **Private Qwen routing is live.** Core is attached to both `omics_portal_omics_network` and + external `localllm_default`; frontend remains only on the portal network. The mounted Pi profile + resolves `local-qwen/qwen3.6-35b-a3b` at the sanitized base URL + `http://localllm-vllm:8000/v1`. A direct probe from core verified the model catalog and received + a non-empty real chat completion. +- **Verification/deploy (`2026-07-14T21:08:04+02:00`):** backend **164/164** and frontend + **253/253** passed; both TypeScript gates, both production builds, the Qwen Compose network + contract, and `git diff --check` exited 0. Compose built and force-recreated only `core` and + `frontend`; core is healthy. Built and running image IDs match: core + `sha256:ef23123767fa4b10eec5712dbf7bc4e74eee1501dca542b8807921b6d6cb31be`, frontend + `sha256:5a47f81bc887423e05cef8fd3feb075aa600cb33217247186124f60ca5a3005b`. + The frontend entry hash changed, so only `omics_portal-web-1` was restarted to invalidate its + indefinite Vite-manifest cache. The application-level Qwen smoke reached its first + `ui_request`, persisted the expected provider/model, deleted only its uniquely named smoke + session, restored the exact saved settings object, and left no smoke session or Pi runtime. + ## What ThothII is A **human-in-the-loop datamart builder**: it turns a natural-language question into @@ -135,7 +162,7 @@ All three layers' deps installed (`npm install` in each, `python -m venv + pip i - frontend: `cd frontend && npm run dev` (Vite; `VITE_BACKEND_URL` → backend) - harness install: `cd harness && python -m venv .venv && pip install -e ".[dev]"` → `tht` on PATH -## How to test (green 2026-07-14: harness pytest 798 / gate JS 126 / backend 154 / frontend 251) +## How to test (green 2026-07-14: harness pytest 798 / gate JS 126 / backend 164 / frontend 253) - harness: `cd harness && .venv/bin/pytest -q` (5 L2/real-DB tests are deselected by default) - backend: `cd backend && npx vitest run` · typecheck `npx tsc --noEmit -p .` - frontend: `cd frontend && npx vitest run` · typecheck `npx tsc -b` · e2e `npm run e2e` (Playwright) diff --git a/brain/codebase/pi-model-selection.md b/brain/codebase/pi-model-selection.md index 153ff3e6..37a489bf 100644 --- a/brain/codebase/pi-model-selection.md +++ b/brain/codebase/pi-model-selection.md @@ -6,5 +6,6 @@ - Lo spawn di enumerazione deve comunque passare da `buildPiChildEnv({})` per rimuovere credenziali ambientali e metadati dei secret. - `local-qwen` è un provider custom locale esplicito; non richiede la chiave generica dei provider hosted. Provider sconosciuti e composti restano fail-closed. - Il profilo Pi live è montato da `/home/chirone/thothii-data/pi-config` a `/home/thoth/.pi`; non leggere né stampare mai i valori di `auth.json`. -- Le worktree non contengono `deploy/thothii.env` perché è ignorato: per un rebuild dalla worktree rendere disponibile quel file senza copiarne o stamparne il contenuto. -- La directory host `pi-config` può essere non attraversabile dall'utente di sviluppo. Per una patch autorizzata, concedere accesso minimo temporaneo, usare `apply_patch`, poi ripristinare subito owner e mode e verificarli. +- Il provider live `local-qwen` usa `http://localllm-vllm:8000/v1` e il modello `qwen3.6-35b-a3b`; il file montato conserva owner/mode e non contiene modifiche alle credenziali. +- In Compose solo `core` entra nella rete esterna `localllm_default`, oltre alla rete del portale; `frontend` non deve avere accesso diretto alla rete del modello. +- La connettività è verificata dal namespace di `core`: catalogo `/v1/models`, modello atteso presente e completion reale non vuota, senza stampare il testo della risposta. diff --git a/brain/codebase/workflow-ui-contracts.md b/brain/codebase/workflow-ui-contracts.md index 92281015..75ed73aa 100644 --- a/brain/codebase/workflow-ui-contracts.md +++ b/brain/codebase/workflow-ui-contracts.md @@ -13,5 +13,12 @@ normalize legacy malformed entries defensively in the viewer so one object cannot crash React. - `SqlViewer`'s horizontal/vertical layout control is meaningful only with multiple SQL blocks; hide it for the single CTE result shown by `CteResultViewer`. -- Deployment lifecycle details live in [[datamart-builder-deployment-gotchas]]: a rebuilt image - does not update a running Compose service until the containers are recreated. +- A Pi turn is `idle`, `running`, `waiting`, or `failed`. Reviewer input moves it to `waiting`; + responses and steering move it back to `running`; provider failures remain `failed` after + `agent_end` and emit only the fixed sanitized recovery message. +- Resume preserves `running`/`waiting` runtimes. It replaces `idle`/`failed` runtimes, clears the + old SSE buffer/subscribers before cold resume, and reuses the persisted provider/model/thinking. +- A successful Resume of the already selected session increments the stream generation so React + closes the old EventSource and opens the same session URL again. Failed Resume must not reconnect. +- SSE endpoints are intentionally keep-alive. Browser cleanup and one-off probes must explicitly + close the EventSource or cancel/abort the response reader after their terminal event.