Files
brain-of-reese/frontend/tuning.html
T

117 lines
6.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="description" content="Manage the global tuning notes that steer every Brain of Reese answer.">
<title>Global Tuning · Brain of Reese</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2064%2064%22%3E%3Cpath%20d=%22M32%204%2055%2018v28L32%2060%209%2046V18Z%22%20fill=%22%23121a2e%22%20stroke=%22%236d78f2%22%20stroke-width=%224%22%20stroke-linejoin=%22round%22/%3E%3Ccircle%20cx=%2232%22%20cy=%2232%22%20r=%226.5%22%20fill=%22%236d78f2%22/%3E%3Cpath%20d=%22M32%2025.5V16M32%2048v-9.5M25.5%2032H16M48%2032h-9.5%22%20stroke=%22%2322d3ee%22%20stroke-width=%223%22%20stroke-linecap=%22round%22/%3E%3C/svg%3E">
<link rel="stylesheet" href="/assets/styles.css">
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="app-header">
<div class="container header-inner">
<span class="brand">
<svg class="brand-mark" aria-hidden="true" viewBox="0 0 64 64"><path d="M32 4 55 18v28L32 60 9 46V18Z" fill="#121a2e" stroke="#6d78f2" stroke-width="4" stroke-linejoin="round"/><circle cx="32" cy="32" r="6.5" fill="#6d78f2"/><path d="M32 25.5V16M32 48v-9.5M25.5 32H16M48 32h-9.5" stroke="#22d3ee" stroke-width="3" stroke-linecap="round"/></svg>
<span class="brand-text">Brain of <strong>Reese</strong></span>
</span>
<nav class="app-nav" aria-label="Primary">
<a href="/" class="nav-link">Chat</a>
<!-- Phase 19: the Sources link is admin-only (owner permission
2026-08-23) — hidden by default, header.js reveals it once
whoami says admin. The soft-gated page itself is unchanged. -->
<a href="/sources.html" class="nav-link" id="nav-sources" hidden>Sources</a>
<!-- Phase 27: this page's own nav link. Admin-only, exactly like
the Sources link: it SHIPS hidden (anonymous-safe default —
the phase-16 "absent, not hidden" spirit) and header.js
reveals it once whoami says admin, so no anonymous user ever
sees it for a frame. -->
<a href="/tuning.html" class="nav-link is-active" id="nav-tuning" aria-current="page" hidden>Tuning</a>
</nav>
<!-- Phase 19: the shared header controls reach the tuning page —
same markup, ids, and aria as the other pages (one consistent
bar on every page). header.js (assets/header.js) reveals
exactly one of Sign in / Sign out after whoami; the New chat
button here means "go to the chat, fresh" (tuning.js). -->
<button type="button" class="new-chat-btn" id="new-chat-btn" aria-label="New chat">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
<span class="new-chat-label">New chat</span>
</button>
<!-- Phase 16: single-admin auth — exactly one of Sign in / Sign out
is visible; /api/whoami decides at load (header.js). Icon-only
below 640px (aria-labels keep the accessible names). -->
<a href="/login.html?next=/tuning.html" class="auth-link" id="sign-in-link" hidden>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M10 4h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-8"/><path d="M4 12h11"/><path d="m12 9 3 3-3 3"/></svg>
<span class="auth-label">Sign in</span>
</a>
<button type="button" class="auth-link" id="sign-out-btn" aria-label="Sign out" hidden>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8"/><path d="M9 12h11"/><path d="m17 9 3 3-3 3"/></svg>
<span class="auth-label">Sign out</span>
</button>
</div>
</header>
<main id="main" class="app-main" tabindex="-1">
<div class="container tuning-shell">
<div class="page-head">
<h1>Global Tuning</h1>
<p class="page-sub">
Every note below is read into the system prompt of
<strong>every</strong> chat turn. Add, edit, or remove them here —
no conversation required.
</p>
</div>
<!-- Phase 27: create a note without a chat. The label is
visually-hidden (the heading + placeholder carry the visible
context); the 1–2000-char contract mirrors the chat-page tune
form — the server re-validates (422). -->
<form id="tune-form">
<label class="visually-hidden" for="tune-note">Add a global tuning note</label>
<textarea
id="tune-note"
name="note"
rows="3"
maxlength="2000"
placeholder="e.g. be more concise — or: assume I'm on NixOS"
required
></textarea>
<button type="submit" id="tune-save">Add note</button>
</form>
<!-- Live announcer for create / edit / delete — tuning.js (phase 27,
task 03) owns the message text. -->
<p class="visually-hidden" id="tune-announcer" role="status" aria-live="polite"></p>
<!-- Phase 27: the note list — the phase-15 steering panel's
language, full column width. tuning.js fills it newest-first;
each row is an <li class="tuning-note"> with a
.tuning-note-text span + an Edit and a Delete button (styles:
styles.css "Global tuning page"). The empty state toggles with
the list. -->
<section class="tuning-panel" aria-labelledby="tuning-panel-title">
<h2 id="tuning-panel-title" class="tuning-panel-title">Tuning notes</h2>
<ul id="tune-list" class="tuning-list" role="list"></ul>
<p id="tune-empty">No tuning notes yet — add one above.</p>
</section>
</div>
</main>
<footer class="app-footer">
<div class="container footer-inner">
<span>Powered by Reese's self-hosted models</span>
</div>
</footer>
<!-- Phase 27: markdown.js (the classic global renderMarkdown) loads
BEFORE the module script; the shared header module loads through
tuning.js's own `import "./header.js"` — a hoisted import that is
evaluated before the page script body calls initSharedHeader() at
boot. No direct header.js <script> tag (single-evaluation design). -->
<script src="assets/markdown.js"></script>
<script type="module" src="/assets/tuning.js"></script>
</body>
</html>