Reset the activity panel when starting a new question so the landing navigation is restored. Detect and persist the original question language, pass it through runtime and widget descriptors, and scope HITL controls to that language.
Validated with gate, session, backend and frontend tests, TypeScript checks, Ruff and strict docs build. Rebuilt and restarted local core/frontend; both healthy and serving HTTP successfully.
Implement approved specification #32 and tickets #33-#37. Keep host authentication server-verified and pin session interaction language. Compile scoped base selectors for browser compatibility and retain full gutters during CSS pruning.
Add PostgreSQL-backed memory, editable evidence with source review and activation, and human-approved archive repairs across the harness, API, and UI. Include migrations, deployment support, regression coverage, and validation documentation.
Refresh permissions from validated session roles so existing administrator logins can access newly deployed archive management features.
Add catalog-owned logical relationships and runtime snapshots, extend the database-management UI and validation coverage, and document the updated operational workflow.
Keep active sensitive-generation status in a tooltip and indicator, and update the layout E2E to follow the history action in its new database-scoped location.
Keep upstream identity visible while limiting logout to local auth. Inject the restore privilege gate so the deterministic core tests do not depend on the host OS, and confine descriptor-backed projection tests to Linux. Accept the real remaining Pi timeout budget instead of an exact millisecond.
Backend: GET /health/dwh (unauthenticated) calls tht db ping with a 5s
timeout. Frontend: checkDwhHealth() races a 5s timer against the fetch;
on failure a non-dismissable Dialog with Retry appears immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Embedded in the Omics Portal the SPA sits to the right of the portal sidebar,
but dialogs used `fixed left-1/2` — centered on the whole browser window, so
gates rendered visibly off-center (overlapping the sidebar).
- AppShell publishes the app area's horizontal geometry (--app-area-left/width)
as CSS vars on <html> via ResizeObserver + window resize.
- DialogContent centers on those vars (falls back to the viewport when the app
is standalone, where the two coincide).
- ArtifactGateWidget: narrower — cap at 52rem instead of 70vw.
- tools/replay: resume now returns {id, alreadyActive} JSON — the post-f979ada
frontend reads result.alreadyActive and a bare 204 broke replay resume.
Verified on the replay harness: with a simulated 300px portal sidebar the gate
centers on the app area (center 790 = 300 + 980/2); standalone unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Give live feedback that something is happening the moment a session starts
processing: the red stop dot in the composer beats with a soft heartbeat + halo
while the harness is actively working (running — not waiting at a gate or
finalized), and settles the instant the model hands control back to the reviewer
or the session ends. Ring/scale only (no layout properties animated); honors
prefers-reduced-motion.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New session now refuses to spawn a Pi runtime that would only die in bootstrap
retrieval when the DWH/vector host is unreachable (e.g. a dropped VPN). Before
`session new`, POST /sessions probes the DWH via `tht db ping`; if it is down it
returns 503 {code:"dwh_unreachable"} with a clear message and creates nothing.
- Gated behind the THT_DWH_PRECHECK flag (default off), enabled only by the local
dev launcher (run-stack.sh) — containers/CI never pay the probe, and existing
tests that don't set it are unaffected.
- ThtRunner.dbPing() runs `tht db ping` with a 10s timeout (run() gains an optional
timeout that SIGKILLs a hung child).
- Frontend: apiFetch throws a typed ApiError (status + parsed payload); the new-
session composer shows the specific alert on `dwh_unreachable` instead of the
generic retry hint, keeping the question for retry.
Verified live on an isolated backend (precheck on + broken DWH host → 503
dwh_unreachable, no session created) and via unit tests (backend 228, frontend 308).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Opening an in-progress session that has a live Pi runtime now reconnects to
its pending gate instead of the empty landing screen that read as "stopped".
Cold/completed sessions keep the read-only documents panel with its explicit
Resume, so a mere click never spawns a runtime. Backend GET /sessions now
reports a per-session `active` flag (live runtime bound) to drive this.
Also:
- "New session" now closes any open session detail panel (left box).
- The model-activity separator can be dragged to a full 50/50 split
(was capped at 576px); central-min still guards narrow viewports.
Test fixes uncovered along the way:
- Node 25 ships an experimental global localStorage that shadows jsdom's and
lacks clear(), failing every jsdom test at setup; install a spec-compliant
in-memory Storage (feature-detected, inert on CI/LTS).
- Fix 4 pre-existing session-mgmt tests that used an ambiguous getByText for a
session shown in both nav and header; target the nav item by test id.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The central column was top-anchored with no fixed header, so the user's
question was never shown while the model worked and the activity/gate
content drifted upward. Render the active session's question as a sticky,
always-present first row of the central area so it stays evident and
anchored at the top of the form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>