Extract Cortex OS Hermes WebUI Host Adapter

This commit is contained in:
Svrnty 2026-05-29 02:53:40 -04:00
parent 8b6c810f4a
commit 1707a7b09d
6 changed files with 116 additions and 20 deletions

View File

@ -2,7 +2,7 @@
**Upstream version:** v0.51.118
**Plugin version:** 0.5.0
**Total dependencies:** 61 (40 public API · 0 forced internal · 21 frontend)
**Total dependencies:** 62 (41 public API · 0 forced internal · 21 frontend)
> **Auto-generated by `scripts/ast-connection-map.py`. Do not hand-edit.**
> To change a justification, edit the `# CONNECTION:` comment above the
@ -14,21 +14,19 @@
| Plugin location | Upstream symbol | Snippet |
|---|---|---|
| `plugin.py:29` | `api.logger` | `log = api.logger("svrnty.plugin")` |
| `plugin.py:34` | `api.register_static` | `api.register_static(STATIC_PREFIX, str(STATIC_DIR))` |
| `plugin.py:35` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/app.css")` |
| `plugin.py:36` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/app.js")` |
| `plugin.py:39` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/svrnty_nav.js")` |
| `plugin.py:42` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/adwright.css")` |
| `plugin.py:43` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/adwright.js")` |
| `plugin.py:45` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/bte.css")` |
| `plugin.py:46` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/bte.js")` |
| `plugin.py:48` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/canvas.css")` |
| `plugin.py:49` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/canvas.js")` |
| `plugin.py:51` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/umbrella_inline.css")` |
| `plugin.py:52` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/umbrella_inline.js")` |
| `plugin.py:54` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/cortex-os/runtime-health/runtime_health.c` |
| `plugin.py:55` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/cortex-os/runtime-health/runtime_health.js")` |
| `plugin.py:31` | `api.logger` | `log = api.logger("svrnty.plugin")` |
| `plugin.py:36` | `api.register_static` | `api.register_static(STATIC_PREFIX, str(STATIC_DIR))` |
| `plugin.py:37` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/app.css")` |
| `plugin.py:38` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/app.js")` |
| `plugin.py:41` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/svrnty_nav.js")` |
| `plugin.py:44` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/adwright.css")` |
| `plugin.py:45` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/adwright.js")` |
| `plugin.py:47` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/bte.css")` |
| `plugin.py:48` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/bte.js")` |
| `plugin.py:50` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/canvas.css")` |
| `plugin.py:51` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/canvas.js")` |
| `plugin.py:53` | `api.inject_stylesheet` | `api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/umbrella_inline.css")` |
| `plugin.py:54` | `api.inject_script` | `api.inject_script(f"/plugins/{STATIC_PREFIX}/umbrella_inline.js")` |
| `routes/adwright.py:68` | `api.logger` | `log = api.logger("svrnty.routes.adwright")` |
| `routes/adwright.py:69` | `api.register_route` | `api.register_route(` |
| `routes/adwright.py:71` | `api.register_route` | `api.register_route(` |
@ -44,6 +42,9 @@
| `routes/canvas.py:57` | `api.register_route` | `api.register_route("/api/canvas/command", "POST", _handle_command)` |
| `routes/canvas.py:58` | `api.register_route` | `api.register_route("/api/canvas/design-context", "GET", _handle_design_context)` |
| `routes/canvas.py:59` | `api.register_route` | `api.register_route("/api/canvas/events", "GET", _handle_events)` |
| `routes/cortex_os_extension.py:17` | `api.logger` | `log = api.logger("svrnty.routes.cortex_os_extension")` |
| `routes/cortex_os_extension.py:21` | `api.inject_stylesheet` | `api.inject_stylesheet(stylesheet)` |
| `routes/cortex_os_extension.py:22` | `api.inject_script` | `api.inject_script(script)` |
| `routes/cortex_os_runtime_health.py:26` | `api.logger` | `log = api.logger("svrnty.routes.cortex_os_runtime_health")` |
| `routes/cortex_os_runtime_health.py:27` | `api.register_route` | `api.register_route(ROUTE_PATH, ROUTE_METHOD, _handle_runtime_health)` |
| `routes/transcribe.py:37` | `api.logger` | `log = api.logger("svrnty.routes.transcribe")` |

View File

@ -35,12 +35,14 @@ assets:
- /plugins/svrnty/bte.js
- /plugins/svrnty/canvas.js
- /plugins/svrnty/umbrella_inline.js
- /plugins/svrnty/cortex-os/runtime-health/runtime_health.js
stylesheets:
- /plugins/svrnty/app.css
- /plugins/svrnty/adwright.css
- /plugins/svrnty/bte.css
- /plugins/svrnty/canvas.css
- /plugins/svrnty/umbrella_inline.css
- /plugins/svrnty/cortex-os/runtime-health/runtime_health.css
# Routes this plugin registers at load time (declarative cross-check vs runtime).
# Each row maps to a routes/<file>.py.
@ -59,6 +61,7 @@ routes:
- { path: /api/canvas/command, method: POST, file: routes/canvas.py, status: live }
- { path: /api/canvas/design-context, method: GET, file: routes/canvas.py, status: seed }
- { path: /api/canvas/events, method: GET, file: routes/canvas.py, status: seed }
- { path: /api/cortex-os/runtime-health, method: GET, file: routes/cortex_os_extension.py, status: live }
# Audio-attachment processors (called by streaming.py before agent receives message).
audio_processors:

View File

@ -14,6 +14,8 @@ in `static/`. The map of every upstream dependency is in CONNECTION-MAP.md
import os
from pathlib import Path
from routes import cortex_os_extension
# Static + asset URL prefix (per protocol §12, decision Q5: /plugins/svrnty/<asset>)
STATIC_PREFIX = "svrnty"
STATIC_DIR = Path(__file__).resolve().parent / "static"
@ -50,11 +52,11 @@ def register(api):
# Inline Umbrella graph for the Hermes Workspace right panel.
api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/umbrella_inline.css")
api.inject_script(f"/plugins/{STATIC_PREFIX}/umbrella_inline.js")
# Cortex OS Runtime Health slice: read-only route status display.
api.inject_stylesheet(f"/plugins/{STATIC_PREFIX}/cortex-os/runtime-health/runtime_health.css")
api.inject_script(f"/plugins/{STATIC_PREFIX}/cortex-os/runtime-health/runtime_health.js")
log.info("static + assets wired at /plugins/%s/", STATIC_PREFIX)
# Cortex OS Plugin development mount: S23 Runtime Health read-only member.
cortex_os_extension.register(api, STATIC_PREFIX)
# Routes — each feature lives in its own module under routes/.
# Phase 2 will populate these. Import-and-register pattern; failures are
# logged but don't take down the rest of the plugin.
@ -84,5 +86,4 @@ def _phase2_routes():
"bte_proxy", # P2.D — BTE Command Center same-origin proxy (PRD §3) ✓
"canvas", # Sovereign Stitch-like design canvas proxy + event seed
"umbrella", # P2.E — cortex-os umbrella graph viz (UMBRELLA-VIZ-PRD) ✓
"cortex_os_runtime_health", # S23.0-I4 — Cortex OS Runtime Health read-only slice ✓
]

View File

@ -0,0 +1,30 @@
"""Cortex OS Plugin Hermes WebUI Host Adapter extraction surface."""
from routes import cortex_os_runtime_health
PACKAGE_ID = "cortex-os-extension"
MEMBER_ID = "s23-runtime-health-read-only-slice"
ACTIVE_DEVELOPMENT_MOUNT_TARGET = "hermes-webui"
SURFACE_ID = "hermes-webui-host-adapter"
RUNTIME_HEALTH_ROUTE = "/api/cortex-os/runtime-health"
RUNTIME_HEALTH_METHOD = "GET"
RUNTIME_HEALTH_STYLESHEET = "/plugins/{static_prefix}/cortex-os/runtime-health/runtime_health.css"
RUNTIME_HEALTH_SCRIPT = "/plugins/{static_prefix}/cortex-os/runtime-health/runtime_health.js"
def register(api, static_prefix):
"""Register only the Cortex OS Runtime Health member for Hermes WebUI."""
log = api.logger("svrnty.routes.cortex_os_extension")
stylesheet = RUNTIME_HEALTH_STYLESHEET.format(static_prefix=static_prefix)
script = RUNTIME_HEALTH_SCRIPT.format(static_prefix=static_prefix)
api.inject_stylesheet(stylesheet)
api.inject_script(script)
cortex_os_runtime_health.register(api)
log.info(
"cortex-os-extension mounted: %s %s via %s",
RUNTIME_HEALTH_METHOD,
RUNTIME_HEALTH_ROUTE,
SURFACE_ID,
)

View File

@ -13,6 +13,7 @@ import pytest
PLUGIN_REPO = Path(__file__).resolve().parents[2]
FORK_REPO = PLUGIN_REPO.parent / "hermes-webui"
MANIFEST = PLUGIN_REPO / "manifest.yaml"
@pytest.fixture(scope="module")
@ -85,6 +86,15 @@ def test_loader_register_wires_our_plugin(loader, monkeypatch):
assert len(loader._AUDIO_PROCESSORS) == 1
def test_manifest_declares_cortex_os_runtime_health_surface():
manifest = MANIFEST.read_text(encoding="utf-8")
assert "/api/cortex-os/runtime-health" in manifest
assert "routes/cortex_os_extension.py" in manifest
assert "/plugins/svrnty/cortex-os/runtime-health/runtime_health.css" in manifest
assert "/plugins/svrnty/cortex-os/runtime-health/runtime_health.js" in manifest
def test_loader_noop_when_env_unset(loader, monkeypatch):
"""No env var = no plugin loaded. Upstream behavior fully preserved."""
monkeypatch.delenv("HERMES_WEBUI_PYTHON_PLUGIN", raising=False)

View File

@ -0,0 +1,51 @@
from unittest.mock import Mock
from routes import cortex_os_extension
def test_adapter_constants_preserve_s27_identity():
assert cortex_os_extension.PACKAGE_ID == "cortex-os-extension"
assert cortex_os_extension.MEMBER_ID == "s23-runtime-health-read-only-slice"
assert cortex_os_extension.ACTIVE_DEVELOPMENT_MOUNT_TARGET == "hermes-webui"
assert cortex_os_extension.RUNTIME_HEALTH_METHOD == "GET"
assert cortex_os_extension.RUNTIME_HEALTH_ROUTE == "/api/cortex-os/runtime-health"
def test_adapter_registers_runtime_health_route_and_assets_only():
api = Mock()
api.logger.return_value = Mock()
cortex_os_extension.register(api, "svrnty")
api.inject_stylesheet.assert_called_once_with(
"/plugins/svrnty/cortex-os/runtime-health/runtime_health.css"
)
api.inject_script.assert_called_once_with(
"/plugins/svrnty/cortex-os/runtime-health/runtime_health.js"
)
api.register_route.assert_called_once()
method, path = api.register_route.call_args.args[:2]
assert method == "/api/cortex-os/runtime-health"
assert path == "GET"
api.register_static.assert_not_called()
api.config_get.assert_not_called()
api.register_audio_attachment_processor.assert_not_called()
def test_adapter_source_has_no_forbidden_runtime_discovery():
source = cortex_os_extension.__loader__.get_source(cortex_os_extension.__name__)
forbidden = [
"glob(",
"rglob(",
"subprocess",
"os.walk",
"sot/08-OUTPUTS",
"hermes_webui",
"hermes_agent",
"register_static",
"config_get",
"register_audio_attachment_processor",
"product readiness",
]
for snippet in forbidden:
assert snippet not in source