fix: polish live administration table and record overhaul qualification

This commit is contained in:
snowspeeder committed 2026-10-03 13:30:32 -04:00
1 parent e59c7123cf
commit 19df338c5c
4 files changed
+70 -1

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
# Approved Hope web interface overhaul
The user approved the standalone HTML proposal, including personal settings and administration, with “do it.” This document records the implementation boundary and evidence.
## Implemented
- Square 48px Lightwell realtime action inside the composer; direct intentional connection initiation, not dictation and not a portal to another Start button.
- Inline voice console with actual connection, agent and microphone state, mute/end, selected-conversation ownership, and retained editable typed draft. Text send stays disabled while voice owns the conversation.
- Compact header and conversation-action overflow; workspace editing behind progressive controls; sidebar Library, Activity, and Account & settings.
- Library mounts existing files/artifact controls. Activity mounts actual scheduled tasks. Memory controls are mounted in personal settings without duplicating owners or handlers.
- Real personal settings: readonly account identity, saved appearance, actual voice catalog, server-managed model/thinking, memory, security guidance, current-device sign-out.
- Real administrator account list, creation, password reset, deletion, and retry for failed provisioning. No invented profile writes, existing-role editor, device-session list, connector management or temporary-chat privacy.
- Existing cookie auth, role enforcement and backend contracts preserved. Account change closes dialogs and clears private UI. Appearance loads/saves are account-epoch guarded.
- Shared semantic theme surfaces fix the legacy light-theme voice transcript contrast defect; reduced-motion matrix avoids live layout size mutations.
## Qualification before deployment
- Integrated browser/theme/package/token/rollback selection: 45 passed, 304 subtests.
- Final conversation/settings recheck after appearance-save epoch guard: 12 passed.
- Responsive captures verified 1440/390/320 widths: no horizontal overflow, composer action exactly 48×48.
- Mocked SDK lifecycle covers direct start, real-readiness gating, mute/unmute, cid binding, stop and microphone rejection. This is not acoustic evidence.
- Account/backend isolation regression selection: 25 passed.
## Deployment
Clean committed archive e59c712, separate NAS staging path (no overwrite of dirty NAS checkout), voice image sha256:02bd8e47c2a802ac2232f1403de570e7fb843472b03037167e0ea1e124a048dc. Existing control API image retained. Deployment script produced healthy services with protected quiesced account-state backup and retained rollback containers suffix 20261003T172419Z. External Hope Music is outside this release.
## Live verification
Live qualification scripts are explicit, credential-protected and use disposable conversations. Personal settings/admin verification is read-only: no account or memory changes. Text verification exercises stream completion, overflow Pin, reload and cleanup. Synthetic microphone verification exercises Azure STT → Hermes → Azure TTS → browser audio, not physical acoustic quality. Collected live release verification passed: all personal settings, actual admin list and mobile settings navigation; text response/overflow Pin/reload; direct composer-start synthetic speech with Azure user transcription, expected Hermes answer, playing LiveKit TTS track, 32,067 received audio bytes, zero browser errors, and successful disposable voice-conversation cleanup. No live accounts or memory were mutated by settings verification.
## Remaining boundaries
This release changes the web interface; it does not install a native redesign. Physical microphone/speaker quality and device-specific mobile keyboard behavior remain separate human/device qualification. Native prior signed app installation is not evidence of this web overhaul. Unsupported capabilities remain unavailable rather than simulated in production.
+1
View File
@@ -19,6 +19,7 @@ with sync_playwright() as p:
expect(page.locator('#cancelRun')).to_be_hidden(timeout=180000) expect(page.locator('#cancelRun')).to_be_hidden(timeout=180000)
cid=page.evaluate('HopeChat.conversationId') cid=page.evaluate('HopeChat.conversationId')
expect(page.locator('#chatTimeline')).to_contain_text('Hope') expect(page.locator('#chatTimeline')).to_contain_text('Hope')
page.locator('#conversationMenu').click()
page.locator('#pinConversation').click() page.locator('#pinConversation').click()
expect(page.locator('#pinConversation')).to_contain_text('Unpin') expect(page.locator('#pinConversation')).to_contain_text('Unpin')
page.reload(wait_until='networkidle') page.reload(wait_until='networkidle')
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env python3
"""Read-only deployed settings/admin browser qualification; no account mutations."""
import json
from pathlib import Path
from playwright.sync_api import sync_playwright, expect
values=json.loads(Path('.runtime/deployment.json').read_text())
with sync_playwright() as p:
browser=p.chromium.launch(headless=True)
context=browser.new_context(ignore_https_errors=True,viewport={'width':1440,'height':1000})
page=context.new_page();errors=[]
page.on('pageerror',lambda e:errors.append(str(e)))
page.goto('https://192.168.86.2:9178/',wait_until='networkidle')
page.locator('#loginUsername').fill('admin');page.locator('#loginPassword').fill(values['admin_password']);page.locator('#loginSubmit').click()
expect(page.locator('#primaryInput')).to_be_enabled(timeout=30000)
page.locator('#accountMenuBtn').click();expect(page.locator('#settingsDialog')).to_be_visible()
expect(page.locator('#settingsAccountRole')).to_contain_text('Administrator')
page.locator('[data-settings-target=appearance]').click();expect(page.locator('#paletteSelect')).to_be_enabled(timeout=15000)
page.locator('[data-settings-target=preferences]').click();expect(page.locator('#modelSelect')).to_be_enabled(timeout=30000)
expect(page.locator('#voiceList [role=radio]').first).to_be_visible(timeout=30000)
page.locator('[data-settings-target=privacy]').click();expect(page.locator('#settingsMemoryStatus')).to_contain_text('saved memory',timeout=30000)
page.locator('[data-settings-target=security]').click();expect(page.locator('[data-settings-panel=security]')).to_be_visible()
page.locator('#adminBtn').click();expect(page.locator('#usersBody tr').first).to_be_visible(timeout=15000)
page.screenshot(path='.runtime/hope-approved-admin-live.png',full_page=True)
assert page.evaluate('document.documentElement.scrollWidth<=innerWidth')
page.locator('#settingsClose').click();page.set_viewport_size({'width':390,'height':844})
page.locator('#drawerOpen').click();page.locator('#accountMenuBtn').click();expect(page.locator('#settingsDialog')).to_be_visible()
assert page.evaluate('document.documentElement.scrollWidth<=innerWidth')
page.screenshot(path='.runtime/hope-approved-settings-mobile-live.png',full_page=True)
page.locator('#settingsClose').click();assert not errors,errors
page.evaluate("HopeAuth.request('/api/auth/logout',{method:'POST'})")
context.close();browser.close()
print('live_settings_account_appearance_voice_model_memory_security_admin_mobile=PASS; console_errors=0; no_mutations')
+8 -1
View File
@@ -807,7 +807,14 @@ dialog p{
overflow-wrap:anywhere} overflow-wrap:anywhere}
.admin-section th{ .admin-section th{
color:var(--ink-soft); color:var(--ink-soft);
font-weight:500} font-weight:500;
white-space:nowrap}
.admin-section td:nth-child(2),.admin-section td:nth-child(3){
white-space:nowrap;
overflow-wrap:normal}
.admin-section td:nth-child(4){
overflow-wrap:break-word;
min-width:140px}
.user-actions .btn{ .user-actions .btn{
font-size:11px; font-size:11px;
padding:8px; padding:8px;