mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-28 04:30:18 +00:00
Merge pull request #2162 into stage-348
docs: refresh project snapshot and agent onboarding entrypoint (franksong2702)
This commit is contained in:
@@ -21,6 +21,9 @@
|
||||
# Default workspace directory shown on first launch
|
||||
# HERMES_WEBUI_DEFAULT_WORKSPACE=~/workspace
|
||||
|
||||
# Optional model override. Leave unset to use the active Hermes provider default.
|
||||
# HERMES_WEBUI_DEFAULT_MODEL=
|
||||
|
||||
# Base directory for all Hermes state (affects all paths above if set)
|
||||
# HERMES_HOME=~/.hermes
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ archive/
|
||||
!.env.docker.example
|
||||
.claude/
|
||||
CLAUDE.md
|
||||
AGENTS.md
|
||||
AGENTS.local.md
|
||||
.cursorrules
|
||||
.windsurfrules
|
||||
.aider*
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# Agent instructions for Hermes WebUI
|
||||
|
||||
This file is the shared entry point for AI assistants working in this
|
||||
repository. Keep it project-specific and safe to publish. Do not put personal
|
||||
machine setup, private network details, credentials, tokens, or local-only
|
||||
workflow notes here.
|
||||
|
||||
## Read first
|
||||
|
||||
Before making changes, read:
|
||||
|
||||
1. `README.md`
|
||||
2. `CONTRIBUTING.md`
|
||||
3. `CHANGELOG.md`
|
||||
|
||||
For architecture, testing, or setup work, also read the matching reference:
|
||||
|
||||
- `ARCHITECTURE.md` for design constraints and current module layout
|
||||
- `TESTING.md` for local verification commands and manual test guidance
|
||||
- `docs/onboarding.md` for first-run onboarding behavior
|
||||
- `docs/troubleshooting.md` for diagnostic flows
|
||||
|
||||
## Onboarding and reinstall support
|
||||
|
||||
If the task involves install, reinstall, bootstrap, first-run onboarding,
|
||||
provider setup, local model server setup, Docker onboarding, WSL onboarding, or
|
||||
support for a failed first run, read `docs/onboarding-agent-checklist.md`
|
||||
before running commands or inspecting logs.
|
||||
|
||||
Follow that checklist's safety rules:
|
||||
|
||||
- use isolated `HERMES_HOME` and `HERMES_WEBUI_STATE_DIR` for trials unless the
|
||||
human explicitly asks to use real state
|
||||
- do not delete or overwrite a real `~/.hermes` directory without explicit
|
||||
approval
|
||||
- do not print API keys, OAuth tokens, cookies, full `.env` files, full
|
||||
`auth.json` files, or password hashes
|
||||
- collect non-secret status and log evidence before recommending a fix
|
||||
|
||||
## Contribution style
|
||||
|
||||
- Keep changes focused on one logical problem.
|
||||
- Prefer the existing Python + vanilla JavaScript structure over new
|
||||
dependencies or build steps.
|
||||
- Update docs when changing setup, onboarding, runtime behavior, architecture,
|
||||
or testing guidance.
|
||||
- Update `CHANGELOG.md` for user-visible behavior, setup, workflow, or
|
||||
documentation changes that should be release-note ready.
|
||||
- For UI or UX changes, follow `CONTRIBUTING.md`: include before/after evidence
|
||||
and test relevant responsive states.
|
||||
|
||||
## Local state and secrets
|
||||
|
||||
Hermes WebUI can read and write real agent state, sessions, workspaces,
|
||||
credentials, and cron data. Treat local validation as potentially destructive
|
||||
unless you have confirmed the active state directories.
|
||||
|
||||
Prefer isolated trial state for experiments:
|
||||
|
||||
```bash
|
||||
HERMES_HOME=/tmp/hermes-webui-agent-home \
|
||||
HERMES_WEBUI_STATE_DIR=/tmp/hermes-webui-agent-state \
|
||||
HERMES_WEBUI_PORT=8789 \
|
||||
python3 bootstrap.py
|
||||
```
|
||||
|
||||
Do not include private machine instructions in this tracked file. Use a
|
||||
git-ignored local note for personal workflow details.
|
||||
+88
-91
@@ -7,10 +7,10 @@
|
||||
>
|
||||
> Keep this document updated as architecture changes are made.
|
||||
|
||||
> Current shipped build: `v0.50.245` (April 30, 2026).
|
||||
> Automated coverage: 3309 tests via `pytest tests/ --collect-only -q`. CI runs on Python 3.11, 3.12, and 3.13 against every PR.
|
||||
> Current shipped build: `v0.51.54` (May 13, 2026).
|
||||
> Automated coverage: 5303 tests via `pytest tests/ --collect-only -q`. CI runs on Python 3.11, 3.12, and 3.13 against every PR.
|
||||
>
|
||||
> Notable architecture state as of v0.50.245: workspace panel closed/open state is preloaded via a `documentElement` dataset marker before `style.css` paints to avoid first-load flash; transcript disclosure cards animate via transitionable `max-height`/`opacity` states; thinking cards share rounded bordered card chrome with tool cards (gold palette); incremental streaming-markdown via vendored `streaming-markdown@0.2.15` (no CDN); HTTP byte-range streaming for large media; SSE-driven session sidebar with `pending_user_message` + `active_stream_id` lifecycle tracking; configurable model badges (`primary` / `fallback N`) computed in `_build_configured_model_badges()` and provider-aware in the dropdown picker.
|
||||
> Notable architecture state as of v0.51.54: the bootstrap and first-run onboarding flow own setup discovery; the default WebUI state directory is `~/.hermes/webui`; `ctl.sh` provides a daemon wrapper for homelab installs; chat streaming is still WebUI-owned SSE with stream-ownership guards, cancellation, async manual compression, and turn-journal audit plumbing; provider/model discovery is profile-aware with live-model cache invalidation and custom-provider scoping.
|
||||
|
||||
---
|
||||
|
||||
@@ -43,42 +43,42 @@ actions. The topbar remains focused on conversation context and the workspace/fi
|
||||
## 2. File Inventory
|
||||
|
||||
<repo>/
|
||||
server.py Thin routing shell + HTTP Handler + auth middleware. ~81 lines.
|
||||
server.py Thin routing shell + HTTP Handler + auth middleware. ~446 lines.
|
||||
Delegates all route handling to api/routes.py.
|
||||
bootstrap.py One-shot launcher: optional agent install, deps, health wait, browser open.
|
||||
start.sh Thin wrapper around bootstrap.py for shell-based startup.
|
||||
Dockerfile python:3.12-slim container image (~23 lines)
|
||||
docker-compose.yml Compose config with named volume and optional auth (~22 lines)
|
||||
Dockerfile python:3.12-slim container image (~89 lines)
|
||||
docker-compose.yml Compose config with named volume and optional auth (~57 lines)
|
||||
.dockerignore Excludes .git, tests/, .env* from Docker builds
|
||||
api/
|
||||
__init__.py Package marker
|
||||
auth.py Optional password authentication, signed cookies (~149 lines)
|
||||
config.py Discovery, globals, model detection, reloadable config (~701 lines)
|
||||
helpers.py HTTP helpers: j(), bad(), require(), safe_resolve(), security headers (~71 lines)
|
||||
models.py Session model + CRUD, per-session profile tracking (~137 lines)
|
||||
profiles.py Profile state management, hermes_cli wrapper (~246 lines)
|
||||
onboarding.py First-run onboarding status, real provider config writes, and readiness detection.
|
||||
routes.py All GET + POST route handlers (~1180 lines)
|
||||
startup.py Startup helpers: auto_install_agent_deps() (~50 lines)
|
||||
streaming.py SSE engine, run_agent, cancel, HERMES_HOME save/restore (~236 lines)
|
||||
upload.py Multipart parser, file upload handler (~78 lines)
|
||||
workspace.py File ops: list_dir, read_file_content, workspace helpers (~77 lines)
|
||||
auth.py Optional password authentication, signed cookies (~366 lines)
|
||||
config.py Discovery, globals, model detection, reloadable config (~4139 lines)
|
||||
helpers.py HTTP helpers: j(), bad(), require(), safe_resolve(), security headers (~302 lines)
|
||||
models.py Session model + CRUD, per-session profile tracking (~1927 lines)
|
||||
profiles.py Profile state management, hermes_cli wrapper (~1056 lines)
|
||||
onboarding.py First-run onboarding status, real provider config writes, OAuth linking, and readiness detection (~1002 lines)
|
||||
routes.py All GET + POST route handlers (~9772 lines)
|
||||
startup.py Startup helpers: auto_install_agent_deps() (~128 lines)
|
||||
streaming.py SSE engine, run_agent, cancel, HERMES_HOME save/restore (~4420 lines)
|
||||
upload.py Multipart parser, file upload handler (~284 lines)
|
||||
workspace.py File ops: list_dir, read_file_content, workspace helpers (~810 lines)
|
||||
static/
|
||||
index.html HTML template (~364 lines)
|
||||
style.css All CSS incl. mobile responsive (~670 lines)
|
||||
ui.js DOM helpers, renderMd, tool cards, model dropdown, file tree (~977 lines)
|
||||
workspace.js File preview, file ops, loadDir, clearPreview (~185 lines)
|
||||
sessions.js Session CRUD, list rendering, search, SVG icons, dropdown actions (~533 lines)
|
||||
messages.js send(), SSE event handlers, approval, transcript (~297 lines)
|
||||
panels.js Cron, skills, memory, workspace, profiles, todo, settings (~974 lines)
|
||||
commands.js Slash command registry, parser, autocomplete dropdown (~156 lines)
|
||||
index.html HTML template (~1323 lines)
|
||||
style.css All CSS incl. mobile responsive (~3767 lines)
|
||||
ui.js DOM helpers, renderMd, tool cards, model dropdown, file tree (~7216 lines)
|
||||
workspace.js File preview, file ops, loadDir, clearPreview (~369 lines)
|
||||
sessions.js Session CRUD, list rendering, search, SVG icons, dropdown actions (~3517 lines)
|
||||
messages.js send(), SSE event handlers, approval, transcript (~2301 lines)
|
||||
panels.js Cron, skills, memory, workspace, profiles, todo, settings (~6480 lines)
|
||||
commands.js Slash command registry, parser, autocomplete dropdown (~1302 lines)
|
||||
onboarding.js First-run wizard overlay, provider setup flow, and settings/workspace orchestration.
|
||||
boot.js Event wiring, mobile sidebar/workspace nav, voice input, boot IIFE (~338 lines)
|
||||
boot.js Event wiring, mobile sidebar/workspace nav, voice input, boot IIFE (~1607 lines)
|
||||
tests/
|
||||
conftest.py Isolated test server (port 8788, separate HERMES_HOME) (~240 lines)
|
||||
test_sprint{1-20b}.py Feature tests per sprint (21 files, 415 test functions)
|
||||
test_regressions.py Permanent regression gate (23 tests)
|
||||
AGENTS.md Instruction file for agents working in this directory.
|
||||
conftest.py Isolated test server/state fixtures (~644 lines)
|
||||
488 test files 5303 tests collected via pytest
|
||||
test_regressions.py Permanent regression gate (~976 lines)
|
||||
CONTRIBUTING.md Contributor workflow and PR expectations.
|
||||
ROADMAP.md Feature and product roadmap document.
|
||||
SPRINTS.md Forward sprint plan with CLI + Claude parity targets.
|
||||
ARCHITECTURE.md THIS FILE.
|
||||
@@ -90,7 +90,7 @@ actions. The topbar remains focused on conversation context and the workspace/fi
|
||||
|
||||
State directory (runtime data, separate from source):
|
||||
|
||||
~/.hermes/webui-mvp/
|
||||
~/.hermes/webui/
|
||||
sessions/ One JSON file per session: {session_id}.json
|
||||
workspaces.json Registered workspaces list
|
||||
last_workspace.txt Last-used workspace path
|
||||
@@ -99,7 +99,8 @@ State directory (runtime data, separate from source):
|
||||
|
||||
Log file:
|
||||
|
||||
/tmp/webui-mvp.log stdout/stderr from the background server process
|
||||
~/.hermes/webui/bootstrap-8787.log start.sh/bootstrap background server log
|
||||
~/.hermes/webui.log ctl.sh daemon log
|
||||
|
||||
---
|
||||
|
||||
@@ -118,15 +119,16 @@ Environment variables controlling behavior:
|
||||
HERMES_WEBUI_DEFAULT_WORKSPACE Default workspace path for new sessions
|
||||
HERMES_WEBUI_STATE_DIR Where sessions/ folder lives
|
||||
HERMES_CONFIG_PATH Path to ~/.hermes/config.yaml
|
||||
HERMES_WEBUI_DEFAULT_MODEL Default LLM model string
|
||||
HERMES_WEBUI_DEFAULT_MODEL Optional model override; unset means provider default
|
||||
HERMES_WEBUI_PASSWORD Optional: enable password auth (off by default)
|
||||
HERMES_WEBUI_SKIP_ONBOARDING Optional: bypass the first-run onboarding wizard
|
||||
HERMES_HOME Base directory for Hermes state (~/.hermes by default)
|
||||
|
||||
Test isolation environment variables (set by conftest.py):
|
||||
|
||||
HERMES_WEBUI_PORT=8788 Isolated test port
|
||||
HERMES_WEBUI_STATE_DIR=~/.hermes/webui-mvp-test Isolated test state
|
||||
HERMES_WEBUI_DEFAULT_WORKSPACE=.../test-workspace Isolated test workspace
|
||||
HERMES_WEBUI_TEST_PORT=... Optional pinned test port
|
||||
HERMES_WEBUI_TEST_STATE_DIR=~/.hermes/webui-test-* Optional pinned test state
|
||||
HERMES_WEBUI_DEFAULT_WORKSPACE=.../test-workspace Isolated test workspace
|
||||
|
||||
Tests NEVER talk to the production server (port 8787).
|
||||
The test state dir is wiped before each test session and deleted after.
|
||||
@@ -363,16 +365,18 @@ read_file_content(workspace, rel):
|
||||
### 5.1 Structure
|
||||
|
||||
The frontend is served from static/ as separate files: one HTML template, one CSS file,
|
||||
and six JavaScript modules (~2,786 lines total). External dependencies: Prism.js (syntax
|
||||
highlighting) and Mermaid.js (diagrams) from CDN, both loaded async/deferred with SRI hashes.
|
||||
and multiple JavaScript modules. External dependencies include Prism.js (syntax
|
||||
highlighting), Mermaid.js (diagrams), xterm.js, and KaTeX assets loaded with the
|
||||
current static template's integrity/CSP assumptions.
|
||||
|
||||
Six JS modules loaded in order at end of <body>:
|
||||
1. ui.js (~846 lines) DOM helpers, renderMd, tool card rendering, global state
|
||||
2. workspace.js (~169 lines) File tree, preview, file operations
|
||||
3. sessions.js (~532 lines) Session CRUD, list rendering, search, SVG icons, dropdown actions, project picker
|
||||
4. messages.js (~293 lines) send(), SSE event handlers, approval, transcript
|
||||
5. panels.js (~771 lines) Cron, skills, memory, workspace, todo, switchPanel
|
||||
6. boot.js (~175 lines) Event wiring + boot IIFE
|
||||
Core JS modules loaded by the app include:
|
||||
1. ui.js (~7216 lines) DOM helpers, renderMd, tool card rendering, global state
|
||||
2. workspace.js (~369 lines) File tree, preview, file operations
|
||||
3. sessions.js (~3517 lines) Session CRUD, list rendering, search, SVG icons, dropdown actions, project picker
|
||||
4. messages.js (~2301 lines) send(), SSE event handlers, approval, transcript
|
||||
5. panels.js (~6480 lines) Cron, skills, memory, workspace, profiles, todo, settings
|
||||
6. commands.js (~1302 lines) Slash command registry, parser, autocomplete dropdown
|
||||
7. boot.js (~1607 lines) Event wiring + boot IIFE
|
||||
|
||||
sessions.js defines an `ICONS` constant at module level with hardcoded SVG strings for all
|
||||
session action buttons (pin, unpin, folder, archive, unarchive, duplicate, trash). All icons
|
||||
@@ -680,27 +684,28 @@ Split server.py into a proper package. Completed across Sprints 4-10.
|
||||
Current structure:
|
||||
|
||||
<repo>/
|
||||
server.py Entry point + HTTP Handler dispatch (~76 lines)
|
||||
server.py Entry point + HTTP Handler dispatch (~446 lines)
|
||||
api/
|
||||
__init__.py
|
||||
routes.py All GET + POST route handlers (~1016 lines)
|
||||
config.py Configuration, constants, global state, model discovery (~640 lines)
|
||||
helpers.py HTTP helpers: j(), bad(), require(), safe_resolve() (~57 lines)
|
||||
models.py Session model + CRUD (~132 lines)
|
||||
workspace.py File ops, workspace management (~77 lines)
|
||||
upload.py Multipart parser, file upload handler (~77 lines)
|
||||
streaming.py SSE engine, run_agent, cancel support (~222 lines)
|
||||
routes.py All GET + POST route handlers (~9772 lines)
|
||||
config.py Configuration, constants, global state, model discovery (~4139 lines)
|
||||
helpers.py HTTP helpers: j(), bad(), require(), safe_resolve() (~302 lines)
|
||||
models.py Session model + CRUD (~1927 lines)
|
||||
workspace.py File ops, workspace management (~810 lines)
|
||||
upload.py Multipart parser, file upload handler (~284 lines)
|
||||
streaming.py SSE engine, run_agent, cancel support (~4420 lines)
|
||||
static/
|
||||
index.html HTML document (served from disk)
|
||||
style.css All CSS (~560 lines)
|
||||
ui.js, workspace.js, sessions.js, messages.js, panels.js, boot.js
|
||||
style.css All CSS (~3767 lines)
|
||||
ui.js, workspace.js, sessions.js, messages.js, panels.js, commands.js, boot.js
|
||||
tests/
|
||||
conftest.py Isolated test server on port 8788
|
||||
test_sprint1-16.py Feature tests per sprint (14 files)
|
||||
conftest.py Isolated test server/state fixtures
|
||||
488 test files 5303 tests collected
|
||||
test_regressions.py Permanent regression gate
|
||||
|
||||
Route extraction to api/routes.py completed in Sprint 11. server.py is now a ~76-line
|
||||
thin shell: Handler class with structured logging, dispatch to routes, and main().
|
||||
Route extraction to api/routes.py completed in Sprint 11. server.py remains a
|
||||
thin shell relative to the rest of the app: Handler class with headers,
|
||||
structured logging, dispatch to routes, TLS wrapping, and main().
|
||||
|
||||
### Phase B: Thread-Safe Request Context (Priority: Critical, Effort: Medium)
|
||||
|
||||
@@ -779,7 +784,7 @@ Replacing with marked.js + DOMPurify is a future improvement (not blocking).
|
||||
|
||||
### Phase G: Observability -- MOSTLY COMPLETE
|
||||
|
||||
1. Structured JSON logging: COMPLETE (Sprint 1). Per-request JSON to /tmp/webui-mvp.log.
|
||||
1. Structured JSON logging: COMPLETE (Sprint 1). Per-request JSON is printed to the active launcher log (`~/.hermes/webui/bootstrap-8787.log` for `start.sh`, `~/.hermes/webui.log` for `ctl.sh`).
|
||||
2. Enhanced /health: COMPLETE (Sprint 7). Returns `active_streams`, `uptime_seconds`.
|
||||
3. GET /api/debug/stats: NOT YET IMPLEMENTED. Low priority.
|
||||
|
||||
@@ -795,13 +800,13 @@ Optional password gate for non-SSH-tunnel deployments.
|
||||
|
||||
### Phase I: Test Infrastructure -- COMPLETE
|
||||
|
||||
289 tests across 14 test files + regression gate. Isolated test server on port 8788
|
||||
with separate HERMES_HOME, wiped per run. Production data never touched.
|
||||
5303 tests across 488 test files + regression gates. The pytest fixture derives
|
||||
an isolated port and state directory from the repo path unless
|
||||
`HERMES_WEBUI_TEST_PORT` / `HERMES_WEBUI_TEST_STATE_DIR` pin them explicitly.
|
||||
Production data never touched.
|
||||
|
||||
Test files: `test_sprint1.py` through `test_sprint11.py`, `test_sprint16.py`, `test_regressions.py`.
|
||||
Fixtures in `conftest.py`: auto-cleanup, cron isolation, workspace reset.
|
||||
|
||||
Remaining: no CI (GitHub Actions), no frontend tests (browser-based).
|
||||
Fixtures in `conftest.py`: auto-cleanup, profile/config isolation, cron
|
||||
isolation, workspace reset, and test-server lifecycle.
|
||||
|
||||
### Phase J: Performance (Priority: Low, Effort: High)
|
||||
|
||||
@@ -889,7 +894,8 @@ The api() helper:
|
||||
curl -s http://127.0.0.1:8787/health | python3 -m json.tool
|
||||
|
||||
# Tail the server log live
|
||||
tail -f /tmp/webui-mvp.log
|
||||
tail -f ~/.hermes/webui/bootstrap-8787.log
|
||||
tail -f ~/.hermes/webui.log # when launched through ctl.sh
|
||||
|
||||
# List all sessions (metadata only)
|
||||
curl -s http://127.0.0.1:8787/api/sessions | python3 -m json.tool
|
||||
@@ -899,15 +905,15 @@ The api() helper:
|
||||
curl -s "http://127.0.0.1:8787/api/session?session_id=$SID" | python3 -m json.tool
|
||||
|
||||
# Kill and restart server cleanly
|
||||
pkill -f "python.*webui-mvp/server.py"
|
||||
<agent-dir>/webui-mvp/start.sh
|
||||
pkill -f "python.*server.py"
|
||||
<repo>/start.sh
|
||||
|
||||
# Check if server process is running
|
||||
ps aux | grep "webui-mvp/server.py"
|
||||
ps aux | grep "server.py"
|
||||
|
||||
# Inspect session files on disk
|
||||
ls -lt ~/.hermes/webui-mvp/sessions/
|
||||
cat ~/.hermes/webui-mvp/sessions/SESSION_ID.json | python3 -m json.tool
|
||||
ls -lt ~/.hermes/webui/sessions/
|
||||
cat ~/.hermes/webui/sessions/SESSION_ID.json | python3 -m json.tool
|
||||
|
||||
# Count messages in a session
|
||||
python3 -c "import json; d=json.load(open('sessions/SID.json')); print(len(d['messages']))"
|
||||
@@ -920,9 +926,9 @@ The api() helper:
|
||||
curl -s http://127.0.0.1:8787/health # streams not exposed yet, add in Phase G
|
||||
|
||||
# Find all sessions with messages (not Untitled empty)
|
||||
ls ~/.hermes/webui-mvp/sessions/ | xargs -I{} python3 -c "
|
||||
ls ~/.hermes/webui/sessions/ | xargs -I{} python3 -c "
|
||||
import json, sys
|
||||
d = json.load(open('~/.hermes/webui-mvp/sessions/{}'))
|
||||
d = json.load(open('~/.hermes/webui/sessions/{}'))
|
||||
if d['messages']: print('{}', d['title'][:50])
|
||||
" 2>/dev/null
|
||||
|
||||
@@ -1195,31 +1201,22 @@ will be working on this codebase. Read this before touching any file.
|
||||
### Before Making Any Change
|
||||
|
||||
1. Read this document (ARCHITECTURE.md) fully. Especially sections 4, 5, and the ADRs.
|
||||
2. Read the relevant section of server.py by searching for the SECTION header.
|
||||
2. Inspect the relevant module under `api/` or `static/`; `server.py` is only the routing shell.
|
||||
3. Check the Sprint Log (Section 15) to understand what was recently changed.
|
||||
4. Run the test suite first to confirm baseline: cd <agent-dir> &&
|
||||
venv/bin/python -m pytest webui-mvp/tests/test_sprint1.py -v
|
||||
4. Run the relevant test slice first to confirm baseline, for example:
|
||||
venv/bin/python -m pytest tests/test_regressions.py -q
|
||||
5. Check server health: curl -s http://127.0.0.1:8787/health
|
||||
|
||||
### Making Changes
|
||||
|
||||
Always back up server.py before a non-trivial change:
|
||||
cp server.py server.py.$(date +%Y%m%d_%H%M).bak
|
||||
|
||||
Use exact string matching when patching. The pitfalls are documented in the
|
||||
hermes-webui-mvp skill. Key ones:
|
||||
- Never use sed on this file from the shell. Use execute_code with Python string replace.
|
||||
- Always assert the old string is found before replacing (prevents silent no-op patches).
|
||||
- Unicode escape sequences in JS (\u2026) exist as literal backslash-u in the file.
|
||||
Match the file's raw content, not interpreted Python strings.
|
||||
- The HTML block is a Python raw string (r"""..."""). Standard triple-quote escaping
|
||||
rules do not apply inside it, but Python escape sequences \n etc. work in JS strings
|
||||
inside it as literal two-character sequences.
|
||||
Keep edits scoped to the module that owns the behavior. Use exact string
|
||||
matching when making mechanical patches and verify that the intended old string
|
||||
was found before replacing it.
|
||||
|
||||
After any change:
|
||||
venv/bin/python -m py_compile webui-mvp/server.py # syntax check
|
||||
venv/bin/python -m py_compile server.py # syntax check
|
||||
curl -s http://127.0.0.1:8787/health # server still alive
|
||||
venv/bin/python -m pytest webui-mvp/tests/ -v # tests still pass
|
||||
venv/bin/python -m pytest tests/ -v # tests still pass
|
||||
|
||||
### Critical Rules (do NOT regress these)
|
||||
|
||||
|
||||
@@ -48,6 +48,11 @@
|
||||
|
||||
- **PR #2150** by @Jordan-SkyLF — "Refresh usage" button on the Provider quota card in Settings → Providers. Calls `/api/provider/quota?refresh=1&ts=<now>` with `cache: 'no-store'` to bypass browser, service worker, and reverse-proxy caches that may have stamped a previous quota response, then re-renders just the quota card from the fresh response and shows a `Last checked ...` timestamp. Disabled `Refreshing…` state during the in-flight request; success toast on completion or failure toast if the refresh fails. Note: the `refresh=1` query param is a no-op at the server today (`get_provider_quota()` has no in-process cache layer), so the win is strictly browser-side cache-bust + the `no-store` fetch option. A future maintainer follow-up may add server-side TTL caching of OAuth account-limit fetches, at which point the `refresh=1` param becomes load-bearing on both sides.
|
||||
|
||||
### Documentation
|
||||
|
||||
- Refreshed the README / TESTING / ARCHITECTURE current-state snapshots for `v0.51.54`: default model override semantics, test collection counts, file inventory line counts, default state/log paths, and the top-level docs index now match the current code. Also corrected the Docker init banner for `HERMES_WEBUI_STATE_DIR`.
|
||||
- Added a tracked root `AGENTS.md` entry point plus `docs/onboarding-agent-checklist.md` for assistant-led install/reinstall support, with safety rules for real Hermes state, isolated trial commands, non-secret evidence collection, onboarding pass/fail criteria, and a redacted support-report format. Linked the checklist from the README and first-run onboarding guide so assistants helping with setup see it before running commands.
|
||||
|
||||
## [v0.51.51] — 2026-05-12 — Release AA (stage-344 — 16-PR contributor batch — i18n + insights bucketing/mobile + manual-compress async + workspace recovery + iOS PWA scroll + Cloudflare login health + fr locale)
|
||||
|
||||
### Added
|
||||
|
||||
@@ -135,6 +135,7 @@ The bootstrap will:
|
||||
|
||||
If provider setup is still incomplete after install, the onboarding wizard will point you to finish it with `hermes model` instead of trying to replicate the full CLI setup in-browser.
|
||||
For a step-by-step walkthrough of the wizard, provider choices, local model server Base URLs, and safe re-runs, see [`docs/onboarding.md`](docs/onboarding.md).
|
||||
If an AI assistant is helping with install, reinstall, bootstrap, provider setup, or first-run support, have it read [`docs/onboarding-agent-checklist.md`](docs/onboarding-agent-checklist.md) before running commands or inspecting logs.
|
||||
|
||||
---
|
||||
|
||||
@@ -267,7 +268,7 @@ Full list of environment variables:
|
||||
| `HERMES_WEBUI_PORT` | `8787` | Port |
|
||||
| `HERMES_WEBUI_STATE_DIR` | `~/.hermes/webui` | Where sessions and state are stored |
|
||||
| `HERMES_WEBUI_DEFAULT_WORKSPACE` | `~/workspace` | Default workspace |
|
||||
| `HERMES_WEBUI_DEFAULT_MODEL` | `openai/gpt-5.4-mini` | Default model |
|
||||
| `HERMES_WEBUI_DEFAULT_MODEL` | *(provider default)* | Optional model override; leave unset to use the active Hermes provider default |
|
||||
| `HERMES_WEBUI_PASSWORD` | *(unset)* | Set to enable password authentication |
|
||||
| `HERMES_WEBUI_EXTENSION_DIR` | *(unset)* | Optional local directory served at `/extensions/`; must point to an existing directory before extension injection is enabled |
|
||||
| `HERMES_WEBUI_EXTENSION_SCRIPT_URLS` | *(unset)* | Optional comma-separated same-origin script URLs to inject; see [WebUI Extensions](docs/EXTENSIONS.md) |
|
||||
@@ -367,9 +368,9 @@ Or using the agent venv explicitly:
|
||||
/path/to/hermes-agent/venv/bin/python -m pytest tests/ -v
|
||||
```
|
||||
|
||||
Tests run against an isolated server on port 8788 with a separate state directory.
|
||||
Production data and real cron jobs are never touched. Current count: **3309 tests**
|
||||
across 100+ test files.
|
||||
Tests run against an isolated server with a separate state directory.
|
||||
Production data and real cron jobs are never touched. Current snapshot:
|
||||
**5303 tests collected** across **488 test files**.
|
||||
|
||||
---
|
||||
|
||||
@@ -491,33 +492,33 @@ across 100+ test files.
|
||||
## Architecture
|
||||
|
||||
```
|
||||
server.py HTTP routing shell + auth middleware (~154 lines)
|
||||
server.py HTTP routing shell + auth middleware (~446 lines)
|
||||
api/
|
||||
auth.py Optional password authentication, signed cookies (~201 lines)
|
||||
config.py Discovery, globals, model detection, reloadable config (~1110 lines)
|
||||
helpers.py HTTP helpers, security headers (~175 lines)
|
||||
models.py Session model + CRUD + CLI bridge (~377 lines)
|
||||
onboarding.py First-run onboarding wizard, OAuth provider support (~507 lines)
|
||||
profiles.py Profile state management, hermes_cli wrapper (~411 lines)
|
||||
routes.py All GET + POST route handlers (~2250 lines)
|
||||
state_sync.py /insights sync — message_count to state.db (~113 lines)
|
||||
streaming.py SSE engine, run_agent, cancel support (~660 lines)
|
||||
updates.py Self-update check and release notes (~257 lines)
|
||||
upload.py Multipart parser, file upload handler (~82 lines)
|
||||
workspace.py File ops, workspace helpers, git detection (~288 lines)
|
||||
auth.py Optional password authentication, signed cookies (~366 lines)
|
||||
config.py Discovery, globals, model detection, reloadable config (~4139 lines)
|
||||
helpers.py HTTP helpers, security headers (~302 lines)
|
||||
models.py Session model + CRUD + CLI bridge (~1927 lines)
|
||||
onboarding.py First-run onboarding wizard, OAuth provider support (~1002 lines)
|
||||
profiles.py Profile state management, hermes_cli wrapper (~1056 lines)
|
||||
routes.py All GET + POST route handlers (~9772 lines)
|
||||
state_sync.py /insights sync — message_count to state.db (~118 lines)
|
||||
streaming.py SSE engine, run_agent, cancel support (~4420 lines)
|
||||
updates.py Self-update check and release notes (~545 lines)
|
||||
upload.py Multipart parser, file upload handler (~284 lines)
|
||||
workspace.py File ops, workspace helpers, git detection (~810 lines)
|
||||
static/
|
||||
index.html HTML template (~600 lines)
|
||||
style.css All CSS incl. mobile responsive, themes (~1050 lines)
|
||||
ui.js DOM helpers, renderMd, tool cards, context indicator (~1740 lines)
|
||||
workspace.js File preview, file ops, git badge (~286 lines)
|
||||
sessions.js Session CRUD, collapsible groups, search, reload recovery (~800 lines)
|
||||
messages.js send(), SSE handlers, live streaming, session recovery (~655 lines)
|
||||
panels.js Cron, skills, memory, profiles, settings (~1438 lines)
|
||||
commands.js Slash command autocomplete (~267 lines)
|
||||
boot.js Mobile nav, voice input, boot IIFE (~524 lines)
|
||||
index.html HTML template (~1323 lines)
|
||||
style.css All CSS incl. mobile responsive, themes (~3767 lines)
|
||||
ui.js DOM helpers, renderMd, tool cards, context indicator (~7216 lines)
|
||||
workspace.js File preview, file ops, git badge (~369 lines)
|
||||
sessions.js Session CRUD, collapsible groups, search, reload recovery (~3517 lines)
|
||||
messages.js send(), SSE handlers, live streaming, session recovery (~2301 lines)
|
||||
panels.js Cron, skills, memory, profiles, settings (~6480 lines)
|
||||
commands.js Slash command autocomplete (~1302 lines)
|
||||
boot.js Mobile nav, voice input, boot IIFE (~1607 lines)
|
||||
tests/
|
||||
conftest.py Isolated test server (port 8788)
|
||||
61 test files 961 test functions
|
||||
conftest.py Isolated test server/state fixtures
|
||||
488 test files 5303 tests collected
|
||||
Dockerfile python:3.12-slim container image
|
||||
docker-compose.yml Compose with named volume and optional auth
|
||||
.github/workflows/ CI: multi-arch Docker build + GitHub Release on tag
|
||||
@@ -537,8 +538,14 @@ State lives outside the repo at `~/.hermes/webui/` by default
|
||||
- `CHANGELOG.md` -- release notes per sprint
|
||||
- `SPRINTS.md` -- forward sprint plan with CLI + Claude parity targets
|
||||
- `THEMES.md` -- theme system documentation, custom theme guide
|
||||
- `docs/docker.md` -- Docker compose setup, common failures, and bind-mount migration
|
||||
- `docs/supervisor.md` -- launchd, systemd, supervisord, runit, and s6 process-supervisor setup
|
||||
- `docs/onboarding.md` -- first-run wizard, provider setup, local model server Base URLs, and safe re-runs
|
||||
- `docs/onboarding-agent-checklist.md` -- safety rules, evidence commands, and pass/fail checks for assistant-led install or reinstall support
|
||||
- `docs/troubleshooting.md` -- diagnostic flows for common failures (e.g. "AIAgent not available")
|
||||
- `docs/wsl-autostart.md` -- WSL2 auto-start at Windows login
|
||||
- `docs/EXTENSIONS.md` -- administrator-controlled WebUI extension injection
|
||||
- `docs/rfcs/README.md` -- RFC index for larger architecture and durability proposals
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
+6
-5
@@ -8,7 +8,7 @@
|
||||
> Prerequisites: SSH tunnel is active on port 8787. Open http://localhost:8787 in browser.
|
||||
> Server health check: curl http://127.0.0.1:8787/health should return {"status":"ok"}.
|
||||
>
|
||||
> Automated coverage: 3648 tests collected via `pytest tests/ --collect-only -q`. Tests run on every PR via GitHub Actions on Python 3.11, 3.12, and 3.13. The suite covers the bootstrap/static wizard, real provider config persistence (`config.yaml` + `.env`), the `/api/onboarding/*` backend, the onboarding skip/existing-config guard, CSS regression coverage for thinking/tool card animation, streaming session persistence, mobile layout breakpoints, locale parity across 9 languages, and ~700 issue/PR-pinned regression tests.
|
||||
> Automated coverage: 5303 tests collected via `pytest tests/ --collect-only -q`. Tests run on every PR via GitHub Actions on Python 3.11, 3.12, and 3.13. The suite covers the bootstrap/static wizard, real provider config persistence (`config.yaml` + `.env`), the `/api/onboarding/*` backend, the onboarding skip/existing-config guard, CSS regression coverage for thinking/tool card animation, streaming session persistence, mobile layout breakpoints, locale parity across 11 languages, and hundreds of issue/PR-pinned regression tests.
|
||||
> Run: `pytest tests/ -v --timeout=60`
|
||||
>
|
||||
> Local regression focus: verify that a previously closed workspace panel stays visually closed from first paint through boot completion on desktop refresh; there should be no brief open-then-close flash.
|
||||
@@ -533,7 +533,8 @@ FAIL: Sidebar causes layout overflow or blocks chat.
|
||||
### T11.3: Structured Log Output
|
||||
SETUP: SSH access to the server.
|
||||
STEPS:
|
||||
1. In a terminal: tail -f /tmp/webui-mvp.log
|
||||
1. In a terminal: tail -f ~/.hermes/webui/bootstrap-8787.log
|
||||
(or tail -f ~/.hermes/webui.log when launched through `ctl.sh`)
|
||||
2. In browser: perform any action (load page, send message, click file)
|
||||
EXPECT:
|
||||
- Log entries appear in terminal as JSON: {"ts":"...","method":"GET","path":"/health","status":200,"ms":0.1}
|
||||
@@ -577,7 +578,7 @@ FAIL: Browser freezes, crash, or security issue.
|
||||
|
||||
## Automated Test Coverage Reference
|
||||
|
||||
These behaviors are verified by pytest (run: venv/bin/python -m pytest webui-mvp/tests/ -v):
|
||||
These behaviors are verified by pytest (run: venv/bin/python -m pytest tests/ -v):
|
||||
|
||||
Sprint 1 tests (test_sprint1.py):
|
||||
- Server health, session CRUD (create/load/update/delete/sort)
|
||||
@@ -1835,8 +1836,8 @@ Bridged CLI sessions:
|
||||
|
||||
---
|
||||
|
||||
*Last updated: v0.51.31, May 9, 2026*
|
||||
*Total automated tests collected: 4977*
|
||||
*Last updated: v0.51.54, May 13, 2026*
|
||||
*Total automated tests collected: 5303*
|
||||
*Regression gate: tests/test_regressions.py*
|
||||
*Run: pytest tests/ -v --timeout=60*
|
||||
*Source: <repo>/*
|
||||
|
||||
+1
-1
@@ -277,7 +277,7 @@ rm -f $it || error_exit "Failed to delete test file in /app"
|
||||
|
||||
echo ""; echo "== Checking required environment variables for hermes-webui"
|
||||
|
||||
echo ""; echo "-- HERMES_WEBUI_VERSION: Where to store sessions, workspaces, and other state (default: ~/.hermes/webui-mvp)"
|
||||
echo ""; echo "-- HERMES_WEBUI_STATE_DIR: Where to store sessions, workspaces, and other state (default: ~/.hermes/webui)"
|
||||
if [ -z "${HERMES_WEBUI_STATE_DIR+x}" ]; then error_exit "HERMES_WEBUI_STATE_DIR not set"; fi;
|
||||
echo "-- HERMES_WEBUI_STATE_DIR: $HERMES_WEBUI_STATE_DIR"
|
||||
if [ ! -d "$HERMES_WEBUI_STATE_DIR" ]; then mkdir -p $HERMES_WEBUI_STATE_DIR || error_exit "Failed to create state directory at $HERMES_WEBUI_STATE_DIR"; fi
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
# Agent-assisted onboarding checklist
|
||||
|
||||
This checklist is for an AI assistant helping a human install, reinstall, or
|
||||
debug Hermes WebUI onboarding. It does not replace the human first-run wizard.
|
||||
Use it before running bootstrap commands, inspecting logs, or recommending a
|
||||
cleanup path.
|
||||
|
||||
If you are an AI assistant, read this file before assisting with onboarding,
|
||||
bootstrap, provider setup, reinstall, or first-run support.
|
||||
|
||||
## Role split
|
||||
|
||||
The human operator owns:
|
||||
|
||||
- choosing the install path
|
||||
- choosing the provider and model
|
||||
- entering API keys, OAuth codes, and passwords
|
||||
- approving any cleanup of a real Hermes home
|
||||
- approving any external exposure outside localhost
|
||||
|
||||
The assistant owns:
|
||||
|
||||
- using isolated trial directories unless the human explicitly says otherwise
|
||||
- checking non-secret status endpoints and logs
|
||||
- explaining which step passed or failed
|
||||
- collecting redacted evidence for Discord or GitHub support
|
||||
- stopping before destructive cleanup, credential handling, or public exposure
|
||||
|
||||
## Hard safety rules
|
||||
|
||||
- Do not delete, move, or overwrite the real `~/.hermes` directory unless the
|
||||
human explicitly asks for that exact action.
|
||||
- Do not print API keys, OAuth tokens, cookies, full `.env` files, full
|
||||
`auth.json` files, or password hashes.
|
||||
- Do not modify real cron jobs, real sessions, real profiles, or real memory
|
||||
files during an onboarding trial.
|
||||
- Do not expose WebUI on a public interface without password protection and
|
||||
explicit human approval.
|
||||
- Do not proxy or tunnel local service checks such as `localhost`,
|
||||
`127.0.0.1`, private LAN addresses, or Docker container loopback paths.
|
||||
|
||||
## Pre-flight
|
||||
|
||||
Confirm the basic context:
|
||||
|
||||
```bash
|
||||
pwd
|
||||
git branch --show-current
|
||||
git rev-parse --short HEAD
|
||||
python3 --version
|
||||
```
|
||||
|
||||
Check whether repo-local environment overrides will affect bootstrap:
|
||||
|
||||
```bash
|
||||
test -f .env && grep -n 'HERMES_HOME\|HERMES_WEBUI_STATE_DIR\|HERMES_WEBUI_PORT\|HERMES_WEBUI_HOST' .env
|
||||
```
|
||||
|
||||
If `.env` exists, do not print the full file. Inspect only the specific
|
||||
non-secret keys needed to understand the active Hermes home, WebUI state
|
||||
directory, port, or host.
|
||||
|
||||
## Isolated local trial
|
||||
|
||||
Use an isolated Hermes home and WebUI state directory for a reinstall or support
|
||||
trial. This keeps the test away from the operator's real memory, sessions,
|
||||
profiles, credentials, and cron state.
|
||||
|
||||
```bash
|
||||
mkdir -p ~/hermes-onboarding-test
|
||||
HERMES_HOME=~/hermes-onboarding-test/.hermes \
|
||||
HERMES_WEBUI_STATE_DIR=~/hermes-onboarding-test/webui \
|
||||
HERMES_WEBUI_PORT=8789 \
|
||||
python3 bootstrap.py
|
||||
```
|
||||
|
||||
Open:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8789
|
||||
```
|
||||
|
||||
The bootstrap writes a port-specific log under the selected WebUI state
|
||||
directory:
|
||||
|
||||
```text
|
||||
~/hermes-onboarding-test/webui/bootstrap-8789.log
|
||||
```
|
||||
|
||||
For daemon-style installs, `ctl.sh` writes the daemon log to the active
|
||||
`HERMES_HOME` by default:
|
||||
|
||||
```text
|
||||
~/.hermes/webui.log
|
||||
```
|
||||
|
||||
When using the isolated trial environment, prefer the bootstrap command above
|
||||
unless the human specifically wants to validate `ctl.sh`.
|
||||
|
||||
## Non-secret evidence commands
|
||||
|
||||
After the server starts, collect status without secrets:
|
||||
|
||||
```bash
|
||||
curl -sS http://127.0.0.1:8789/health
|
||||
curl -sS http://127.0.0.1:8789/api/onboarding/status
|
||||
find ~/hermes-onboarding-test -maxdepth 3 -type f | sort
|
||||
tail -n 120 ~/hermes-onboarding-test/webui/bootstrap-8789.log
|
||||
```
|
||||
|
||||
When summarizing `/api/onboarding/status`, focus on:
|
||||
|
||||
- `completed`
|
||||
- `system.hermes_found`
|
||||
- `system.imports_ok`
|
||||
- `system.config_path`
|
||||
- `system.config_exists`
|
||||
- `system.setup_state`
|
||||
- `system.provider_configured`
|
||||
- `system.provider_ready`
|
||||
- `system.chat_ready`
|
||||
- `system.current_provider`
|
||||
- `system.current_model`
|
||||
- `system.current_base_url`
|
||||
- `system.env_path`
|
||||
|
||||
Do not paste the full payload if it contains unexpected sensitive local paths
|
||||
or values. Redact paths and provider details when the human asks for a public
|
||||
GitHub or Discord support report.
|
||||
|
||||
## Pass criteria
|
||||
|
||||
A local onboarding trial passes when:
|
||||
|
||||
- `/health` returns successfully.
|
||||
- `/api/onboarding/status` returns JSON.
|
||||
- The wizard appears when `completed` is false.
|
||||
- The wizard stays out of the way when `completed` is true or
|
||||
`HERMES_WEBUI_SKIP_ONBOARDING=1` is intentionally set.
|
||||
- `system.hermes_found` and `system.imports_ok` match the expected bootstrap
|
||||
state.
|
||||
- `system.provider_ready` and `system.chat_ready` become true after the human
|
||||
completes a provider path that should support chat.
|
||||
- `system.config_path` and `system.env_path` point inside the intended isolated
|
||||
`HERMES_HOME` during a trial.
|
||||
- WebUI files are written under the intended `HERMES_WEBUI_STATE_DIR`.
|
||||
|
||||
If the human chooses a provider that must be completed in the CLI, passing can
|
||||
mean the wizard correctly points them to `hermes model` or `hermes auth` rather
|
||||
than trying to collect unsupported credentials in the browser.
|
||||
|
||||
## Failure triage
|
||||
|
||||
If the server does not start:
|
||||
|
||||
- check the bootstrap log
|
||||
- check for a port conflict on `8789`
|
||||
- confirm Python can run `bootstrap.py`
|
||||
- confirm `.env` is not overriding the isolated directories or port
|
||||
|
||||
If onboarding reports `agent_unavailable`:
|
||||
|
||||
- confirm the bootstrap found or installed Hermes Agent
|
||||
- check whether the running Python can import `run_agent.AIAgent`
|
||||
- use `docs/troubleshooting.md`, especially the `AIAgent not available` flow
|
||||
|
||||
If onboarding reports `provider_incomplete`:
|
||||
|
||||
- confirm whether the provider is API-key based, OAuth based, or local
|
||||
- let the human enter credentials or run the CLI auth flow
|
||||
- do not ask the human to paste secrets into chat
|
||||
|
||||
If a local model server does not probe successfully:
|
||||
|
||||
- from native macOS/Linux, use `http://127.0.0.1:<port>/v1` when the server is
|
||||
on the same host
|
||||
- from Docker Desktop, use `http://host.docker.internal:<port>/v1`
|
||||
- from another LAN machine, use the server's LAN IP and `/v1`
|
||||
- remember that `localhost` inside a container is the container itself
|
||||
|
||||
If password or reverse-proxy behavior is confusing:
|
||||
|
||||
- keep the first pass on `127.0.0.1`
|
||||
- require password protection before exposing WebUI beyond localhost
|
||||
- include the reverse proxy shape in the support report without pasting tokens
|
||||
or cookies
|
||||
|
||||
## Final support report
|
||||
|
||||
Use this shape when reporting results to the human, Discord, or GitHub:
|
||||
|
||||
```text
|
||||
Install path:
|
||||
OS / Python:
|
||||
Repo commit:
|
||||
Command used:
|
||||
WebUI URL:
|
||||
State isolation:
|
||||
Health result:
|
||||
Onboarding status summary:
|
||||
Files created or changed:
|
||||
Log excerpt:
|
||||
Pass/fail:
|
||||
Next recommended action:
|
||||
```
|
||||
|
||||
Redact secrets and private paths before posting publicly.
|
||||
@@ -3,6 +3,11 @@
|
||||
This guide explains what happens the first time Hermes WebUI starts, which
|
||||
setup path to choose, and how to recover when the wizard cannot finish.
|
||||
|
||||
If an AI assistant is helping with install, reinstall, bootstrap, provider
|
||||
setup, or first-run support, read
|
||||
[`docs/onboarding-agent-checklist.md`](onboarding-agent-checklist.md) before
|
||||
running commands or inspecting logs.
|
||||
|
||||
The short version: run the bootstrap, open the WebUI, choose a provider, choose
|
||||
a workspace, optionally set a password, then start a chat. If you are using a
|
||||
local model server from Docker, pay special attention to the Base URL section
|
||||
@@ -55,6 +60,10 @@ python3 bootstrap.py
|
||||
|
||||
Then open `http://127.0.0.1:8789`.
|
||||
|
||||
For an assistant-led trial run, follow the safety rules, evidence commands, and
|
||||
pass/fail criteria in
|
||||
[`docs/onboarding-agent-checklist.md`](onboarding-agent-checklist.md).
|
||||
|
||||
If your repo has a `.env` file, remember that the bootstrap loads it. Remove or
|
||||
adjust any `HERMES_HOME`, `HERMES_WEBUI_STATE_DIR`, or `HERMES_WEBUI_PORT`
|
||||
entries there before using the isolated command above.
|
||||
|
||||
+3
-3
@@ -2,8 +2,8 @@
|
||||
Shared pytest fixtures for webui-mvp tests.
|
||||
|
||||
TEST ISOLATION:
|
||||
Tests run against a SEPARATE server instance on port 8788 with a
|
||||
completely separate state directory. Production data is never touched.
|
||||
Tests run against a SEPARATE server instance on an auto-derived test port
|
||||
with a completely separate state directory. Production data is never touched.
|
||||
The test state dir is wiped before each full test run and again on teardown.
|
||||
|
||||
PATH DISCOVERY:
|
||||
@@ -32,7 +32,7 @@ HERMES_HOME = pathlib.Path(os.getenv('HERMES_HOME', str(HOME / '.hermes')))
|
||||
|
||||
# ── Test server config ────────────────────────────────────────────────────
|
||||
# Port and state dir auto-derive from the repo path when no env var is set,
|
||||
# giving every worktree its own isolated port (8800-8899) and state directory.
|
||||
# giving every worktree its own isolated port (20000-29999) and state directory.
|
||||
# Override with HERMES_WEBUI_TEST_PORT / HERMES_WEBUI_TEST_STATE_DIR to pin.
|
||||
|
||||
def _auto_test_port(repo_root) -> int:
|
||||
|
||||
@@ -20,6 +20,12 @@ def test_new_top_level_markdown_docs_are_trackable():
|
||||
assert _git_check_ignore("docs/example-new-guide.md").returncode == 1
|
||||
|
||||
|
||||
def test_root_agents_entrypoint_is_trackable():
|
||||
"""AGENTS.md is the shared repo entrypoint; local overrides stay ignored."""
|
||||
assert _git_check_ignore("AGENTS.md").returncode == 1
|
||||
assert _git_check_ignore("AGENTS.local.md").returncode == 0
|
||||
|
||||
|
||||
def test_docs_scratch_files_remain_ignored():
|
||||
"""The broad docs/* ignore rule should still keep arbitrary scratch files out."""
|
||||
assert _git_check_ignore("docs/local-scratch.tmp").returncode == 0
|
||||
|
||||
Reference in New Issue
Block a user