From cf83444a9d341ae362e65a9f995100c69176887c Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Thu, 5 Mar 2026 18:51:50 +0000 Subject: Rescue work from claudomator-work: question/answer, ratelimit, start-next-task Merges features developed in /site/doot.terst.org/claudomator-work (a stale clone) into the canonical repo: - executor: QuestionRegistry for human-in-the-loop answers, rate limit detection and exponential backoff retry (ratelimit.go, question.go) - executor/claude.go: process group isolation (SIGKILL orphans on cancel), os.Pipe for reliable stdout drain, backoff retry on rate limits - api/scripts.go: POST /api/scripts/start-next-task handler - api/server.go: startNextTaskScript field, answer-question route, BroadcastQuestion for WebSocket question events - web: Cancel/Restart buttons, question banner UI, log viewer, validate section, WebSocket auto-connect All tests pass. Co-Authored-By: Claude Sonnet 4.6 --- web/style.css | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) (limited to 'web/style.css') diff --git a/web/style.css b/web/style.css index de8ce83..268f80c 100644 --- a/web/style.css +++ b/web/style.css @@ -225,6 +225,40 @@ main { cursor: not-allowed; } +.btn-cancel { + font-size: 0.8rem; + font-weight: 600; + padding: 0.35em 0.85em; + border-radius: 0.375rem; + border: none; + cursor: pointer; + background: var(--state-failed); + color: #fff; + transition: opacity 0.15s; +} + +.btn-cancel:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.btn-restart { + font-size: 0.8rem; + font-weight: 600; + padding: 0.35em 0.85em; + border-radius: 0.375rem; + border: none; + cursor: pointer; + background: var(--text-muted); + color: #0f172a; + transition: opacity 0.15s; +} + +.btn-restart:disabled { + opacity: 0.5; + cursor: not-allowed; +} + .task-error { font-size: 0.78rem; color: var(--state-failed); @@ -704,3 +738,231 @@ dialog label select:focus { .logs-modal-body .meta-grid { row-gap: 0.625rem; } + +/* ── Question banner ───────────────────────────────────────────────────────── */ + +.question-banner { + margin-top: 0.75rem; + padding: 0.75rem; + background: #1e293b; + border: 1px solid #f59e0b; + border-radius: 0.5rem; +} + +.question-item { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.question-text { + font-weight: 600; + color: #f59e0b; + font-size: 0.9rem; +} + +.question-options { + display: flex; + flex-wrap: wrap; + gap: 0.375rem; +} + +.btn-question-option { + padding: 0.375rem 0.75rem; + border: 1px solid #475569; + border-radius: 0.375rem; + background: #334155; + color: #e2e8f0; + cursor: pointer; + font-size: 0.8rem; + transition: background 0.15s, border-color 0.15s; +} + +.btn-question-option:hover:not(:disabled) { + background: #475569; + border-color: #f59e0b; +} + +.btn-question-option:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.question-input-row { + display: flex; + gap: 0.375rem; +} + +.question-input { + flex: 1; + padding: 0.375rem 0.5rem; + border: 1px solid #475569; + border-radius: 0.375rem; + background: #0f172a; + color: #e2e8f0; + font-size: 0.8rem; +} + +.question-input:focus { + outline: none; + border-color: #f59e0b; +} + +.btn-question-send { + padding: 0.375rem 0.75rem; + border: 1px solid #f59e0b; + border-radius: 0.375rem; + background: #f59e0b; + color: #0f172a; + font-weight: 600; + cursor: pointer; + font-size: 0.8rem; +} + +.btn-question-send:hover:not(:disabled) { + background: #fbbf24; +} + +.btn-question-send:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.question-error { + color: #f87171; + font-size: 0.8rem; + margin-top: 0.25rem; +} + +/* ── Log Viewer ──────────────────────────────────────────────────────────── */ + +.log-viewer { + width: 100%; + padding: 0; +} + +.log-back-btn { + font-size: 0.78rem; + font-weight: 600; + padding: 0.3em 0.75em; + border-radius: 0.375rem; + border: 1px solid var(--border); + background: transparent; + color: var(--text-muted); + cursor: pointer; + transition: background 0.15s, color 0.15s; + margin-bottom: 1rem; + display: inline-flex; + align-items: center; +} + +.log-back-btn:hover { + background: var(--border); + color: var(--text); +} + +@keyframes pulse-dot { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.3; } +} + +.log-status-indicator { + display: flex; + align-items: center; + gap: 0.4rem; + font-size: 0.78rem; + color: var(--text-muted); + margin-bottom: 0.75rem; +} + +.log-status-indicator::before { + content: ''; + display: inline-block; + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--state-running); + flex-shrink: 0; + animation: pulse-dot 1.4s ease-in-out infinite; +} + +.log-output { + font-family: monospace; + font-size: 0.8rem; + overflow-y: auto; + max-height: 400px; + background: var(--bg); + padding: 0.625rem 0.75rem; + border-radius: 0.375rem; + border: 1px solid var(--border); +} + +.log-line { + padding: 2px 0; + line-height: 1.5; +} + +.log-text { + color: var(--text); +} + +.log-tool-use { + background: rgba(56, 189, 248, 0.1); + padding: 4px 8px; + border-radius: 3px; + margin: 2px 0; +} + +.tool-name { + color: var(--accent); + font-weight: bold; + margin-right: 6px; +} + +.log-tool-result { + color: var(--text-muted); + opacity: 0.6; +} + +.log-cost { + color: var(--state-running); + font-weight: bold; + margin-top: 8px; +} + +/* ── Validate section ────────────────────────────────────────────────────── */ + +.validate-section { + margin-top: 8px; +} + +#validate-result { + border-left: 3px solid transparent; + padding: 8px 12px; + margin-top: 8px; + font-size: 0.85rem; +} + +#validate-result[data-clarity="clear"] { + border-color: var(--state-completed); +} + +#validate-result[data-clarity="ambiguous"] { + border-color: var(--state-running); +} + +#validate-result[data-clarity="unclear"] { + border-color: var(--state-failed); +} + +.validate-blocking { + color: var(--state-failed); +} + +.validate-minor { + color: var(--state-running); +} + +.validate-suggestion { + color: #94a3b8; +} -- cgit v1.2.3