| Age | Commit message (Collapse) | Author |
|
CSS cascade fix: .task-log-tail.running-log combinator overrides
.task-log-tail's 90px max-height for RUNNING/BLOCKED cards, restoring
the intended 300px prominent log panel. Closes EventSource streams in
taskLogStreams when cards are removed from the board.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Change .tasks-column width from 300px to 220px (spec literal value)
- Change .tasks-column-list max-height from 60vh to 70vh (spec literal value)
- Add missing .task-log-tail and .task-log-tail-placeholder rules after .tasks-column-list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Add <button data-tab="tasks"> to the nav bar (between Stories and Stats)
- Add <div data-panel="tasks" hidden><div class="tasks-board"></div></div>
to main as the panel container for the Tasks board
- Add .tasks-board, .tasks-column, .tasks-column-header, .tasks-column-count,
.tasks-column-list CSS rules (mirrors .stories-* layout; 300px columns to
accommodate task card content)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
redesign (Phase 9b)
Two new tabs, matching Phase 9a's conventions: Budget (per-provider spend
meters, escalation funnel, spend-over-time) and Roles (version history,
draft activation, readable escalation-ladder view) -- the human-facing
surface for the token-husbanding value proposition and the Phase 5/8
versioned role-config system.
New backend (minimal, additive, matching existing endpoint conventions --
unauthenticated like /api/budget and /api/roles/*):
- internal/storage/dashboard.go: QueryEscalationFunnel (executions grouped
by escalation_rung + agent, count + cost) and QuerySpendTimeseries (cost
per provider bucketed hourly/daily, mirroring QueryDashboardStats'
existing bucketing expressions). Documented honestly: rung 0 is not
exclusively "resolved locally" -- escalation_rung defaults to 0
uniformly, so non-role-typed executions (which never climb a ladder)
land there too, alongside role-typed tasks genuinely resolved at tier 0.
A role-only variant would need a join against tasks.config_json with no
queryable role column on executions -- intentionally out of scope.
- internal/api/dashboard.go: GET /api/escalation-funnel, GET
/api/spend-timeseries (both ?window=5h|24h|7d|<duration>, default 24h).
- internal/storage.ListRoleNames + GET /api/roles: the "which roles exist"
gap -- there was no way to discover role names before this, only to list
versions for a role you already knew the name of.
Chart-form decisions (dataviz skill, invoked before writing chart code):
horizontal stacked bar for the escalation funnel (rung order already
encodes the funnel shape positionally; color only needed for per-provider
segments within each rung); multi-line for spend-over-time; a fixed-order
categorical palette from the skill's validated palette.md slots for
provider identity (re-validated against this app's dark surface, passing);
a separate status (good/warning/critical) palette for budget meters,
deliberately distinct from both --state-* and the provider palette. Caught
and fixed a real bug during visual QA: converging near-zero end-labels on
the spend chart were overlapping (an anti-pattern the skill explicitly
flags) -- fixed with a 14px minimum-gap check before direct-labeling an
endpoint, leaning on the legend/tooltip otherwise.
Verified with a real running server, real seeded data (65 executions across
rungs 0-2 with a realistic provider mix, 2 roles with active/draft/retired
role_configs versions written directly via internal/storage), and a real
headless-browser session (reusing Phase 9a's Chromium/proxy scaffinding):
confirmed correct rung totals/percentages, provider legends, a 3-line spend
chart, live window-selector re-render, correct active-version highlighting
on the role panel, and a real Activate click on a draft version -- verified
via both DOM re-render and a direct backend GET that it truly persisted.
go build/vet/test -race -count=1 all pass, full suite. node --test
web/test/*.mjs: 291/291 passing (16 new).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1moSNCJRcP6kykA4tyUSs
|
|
(Phase 9a)
First UI work on top of the harness's 8 backend phases -- pure web/*
frontend, no backend changes, keeping the existing embedded vanilla-JS
convention (no build step, no framework).
- Kanban board: columns spanning the full story lifecycle (DISCOVERY/FRAMING
-> BACKLOG -> PRIORITIZED -> IN_PROGRESS -> VALIDATING/REVIEW_READY -> DONE),
cards showing priority/acceptance-criteria count/eval-verdict progress.
Drag-and-drop reorders priority within a column (persisted via a partial
PUT /api/stories/{id}); cross-column drag is disabled outright (a
dragover handler only preventDefault()s when the dragged card's own status
already maps to that column) rather than allowed-then-snapped-back, since
the latter would visibly misplace a card for several seconds until the
next poll -- reads as a bug, not a feature.
- Epic swimlanes: stories grouped client-side by epic_id (incl. an
"Unassigned" lane) with a DONE/total progress meter per epic, built from
data the board already fetches (avoids N+1 GET /api/epics/{id}/stories
calls for a result that's a strict subset of the already-loaded list).
- Story detail modal: metadata/spec/acceptance criteria, a BFS-layered plain-
SVG DAG of the story's task-tree (rows = BFS depth from root_task_id over
both parent_task_id and depends_on edges, solid vs. dashed strokes
distinguishing the two edge kinds), an event timeline rendering
eval_verdict/arbitration_decided/human_accepted/retro_captured/
epic_proposed with human-readable text, and an Accept button wired to
POST /api/stories/{id}/accept when status is REVIEW_READY.
- DAG node coloring reuses the app's existing --state-* CSS custom
properties (the dataviz skill's "reserved status palette" pattern,
already used elsewhere in the app) rather than introducing a new palette.
Running the skill's own palette validator against that pre-existing
9-color set fails its CVD/lightness checks (a pre-existing condition, out
of scope to fix here since those colors are used elsewhere in the app) --
mitigated per the skill's documented remedy for a failing palette: every
node always carries a text label (name + role + state) and a full legend,
so identity never depends on color alone; edge kind is encoded by stroke
style, not color.
Verified with a real running server and a real headless-browser session
(Chromium via playwright-core, offline-cached), not just code review:
seeded real data (an epic, 11 stories across every lifecycle status, a
6-node Builder->4-Evaluator->Arbitration task tree, 4 story events) via the
live REST API plus two throwaway fixture scripts for the two write paths
the API doesn't expose (task depends_on, direct event writes), then
confirmed via screenshots/DOM assertions: correct column placement for every
status, working swimlane grouping/progress meter, correct 6-node/8-edge DAG
render, working event timeline, a real Accept-button API call flipping
REVIEW_READY->DONE, real drag-and-drop priority persistence (re-fetched to
confirm), and a genuine cross-column-drag no-op. Caught and fixed a real bug
during this process: DAG node-label truncation now measures
getComputedTextLength() and binary-searches the longest fit, instead of a
fixed character-count budget that collapsed every "Eval: evaluator_X" label
to "Eval:..." (only one space in the string).
go build ./... clean; node --test web/test/*.mjs -- 275 tests pass (19 new).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1moSNCJRcP6kykA4tyUSs
|
|
Replace the per-row "View Logs" button with a click handler on the entire
execution row. Clicking opens the logs-modal showing a metadata grid (id,
status, agent, exit code, cost, times, error, log paths) followed by an
inline streaming log viewer. The EventSource is torn down on modal close.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Adds GET /api/budget returning per-provider rolling-window headroom (empty when
budget gating is unconfigured), wired from serve.go via SetBudget. The web UI
polls it and renders a chip per limited provider in the header, flagging any
under 20% remaining. New pure JS helpers formatBudgetHeadroom/
renderBudgetHeadroom are unit-tested; the endpoint is covered by Go handler
tests (empty/reports/500). UI render not browser-verified in this environment.
Completes Phase 6: spend accounting + dispatcher gating + observability surface.
https://claude.ai/code/session_01SESwn7kQ7oP62trWw6pc39
|
|
Adds GET /api/tasks/{id}/events (seq-ordered, ?since_seq for incremental
polling) as the timeline data source, and a per-task Timeline section in the
web UI that fetches and renders the observability event stream. New pure,
unit-tested JS helpers: formatEventText, renderEventTimeline, fetchTaskEvents.
The timeline load is async and guarded on a global fetch so the synchronous
renderTaskPanel path (and its DOM-mock unit tests) is unaffected. Verified via
Go endpoint tests and node --test (272 JS tests pass). Note: the live in-browser
panel render was not exercised in this environment — only unit-level coverage.
https://claude.ai/code/session_01SESwn7kQ7oP62trWw6pc39
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Remove the standalone "All" tab; completed tasks (last 24h) now appear
at the bottom of the Ready tab under a "Completed (24h)" section header
- Move Stories tab to the first position in the nav bar
- Drop 'all' from badge count computation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Uses time-bucketed picsum seed (5-min intervals) so all sites
show the same image simultaneously. Sets --bg-url CSS custom
property on body, consumed by .bg-body background-image rule.
|
|
Story detail modal now fetches /api/stories/{id}/tasks and renders
top-level tasks as a numbered list with subtasks nested beneath, using
the same state emoji as the blocked/task views.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
AgentStatusInfo was missing drained field so UI couldn't show drain lock.
AgentEvent had no JSON tags so ev.agent/event/timestamp were undefined in
the stats timeline. UI now shows "Drain locked" card state with undrain CTA.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Stories tab (📖) with story card list, status badges, project/branch meta
- New Story modal: project picker + goal textarea + AI elaboration → plan review → approve & queue
- Story detail modal: status, project, branch, created date
- Export storyStatusLabel() and renderStoryCard() with 16 unit tests
- CSS for story cards, status badges, and modals
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
- GET /api/stats?window=7d: pre-aggregated SQL queries for errors, throughput, billing
- Errors section: category summary (quota/rate_limit/timeout/git/failed) + failure table
- Throughput section: stacked hourly bar chart (completed/failed/other) over 7d
- Billing section: KPIs (7d total, avg/day, cost/run) + daily cost bar chart
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
detection
- Detect Gemini TerminalQuotaError (daily quota) as BUDGET_EXCEEDED, not generic FAILED
- Surface container stderr tail in error so quota/rate-limit classifiers can match it
- Add agent_events table to persist rate-limit start/recovery events across restarts
- Add GET /api/agents/status endpoint returning live agent state + 24h event history
- Stats dashboard: agent status cards, 24h availability timeline, per-run execution table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Show task.project as a badge in task card meta row and as a field
in the task detail overview grid. Both display conditionally only
when project is non-empty.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Add deployment_status field to task list/get API responses for READY
tasks. The field includes deployed_commit, fix_commits, and includes_fix
so the UI can show whether the deployed server includes each fix.
- internal/api/task_view.go: taskView struct + enrichTask() helper
- handleListTasks/handleGetTask: return enriched taskView responses
- web/app.js: export renderDeploymentBadge(); add badge to READY cards
- web/test/deployment-badge.test.mjs: 8 tests for renderDeploymentBadge
- web/style.css: .deployment-badge--deployed / --pending styles
- server_test.go: 3 new tests (red→green) for enriched task responses
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Fix ephemeral sandbox deletion issue by passing $CLAUDOMATOR_PROJECT_DIR to agents and using it for subtask project_dir.
- Implement sandbox autocommit in teardown to prevent task failures from uncommitted work.
- Track git commits created during executions and persist them in the DB.
- Display git commits and changestats badges in the Web UI execution history.
- Add badge counts to Web UI tabs for Interrupted, Ready, and Running states.
- Improve scripts/next-task to handle QUEUED tasks and configurable DB path.
|
|
When a task is BLOCKED due to spawned subtasks (no question), the card
footer now fetches and renders a list of subtask names with their state
emoji instead of showing the question/answer input UI. The Cancel button
remains in both cases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
All, Stats, Settings)
- Replace Tasks/Active tabs with Queue (QUEUED+PENDING), Interrupted, Ready top-level tabs
- Add All tab (COMPLETED, TIMED_OUT, BUDGET_EXCEEDED within last 24h) and Settings placeholder
- Export filterQueueTasks, filterReadyTasks, filterAllDoneTasks from app.js
- Refactor poll() to dispatch to active tab's render function instead of always rendering all panels
- Add renderQueuePanel, renderInterruptedPanel, renderReadyPanel, renderAllPanel helpers
- Add tests in web/test/tab-filters.test.mjs covering all new filter functions (16 tests)
- All 165 JS tests and all Go tests pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
Keep file-based summary approach (CLAUDOMATOR_SUMMARY_FILE) from HEAD.
Combine Q&A History and Stats tab CSS from both branches.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Extend Resume to CANCELLED, FAILED, and BUDGET_EXCEEDED tasks
- Add summary extraction from agent stdout stream-json output
- Fix storage: persist stdout/stderr/artifact_dir paths in UpdateExecution
- Clear question_json on ResetTaskForRetry
- Resume BLOCKED tasks in preserved sandbox so Claude finds its session
- Add planning preamble: CLAUDOMATOR_SUMMARY_FILE env var + summary step
- Update ADR-002 with new state transitions
- UI style improvements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Export computeTaskStats and computeExecutionStats from app.js
- Add renderStatsPanel with state count grid, KPI row (total/success-rate/cost/avg-duration), and outcome bar chart
- Wire stats tab into switchTab and poll for live refresh
- Add Stats tab button and panel to index.html
- Add CSS for .stats-counts, .stats-kpis, .stats-bar-chart using existing state color variables
- Add docs/stats-tab-plan.md with component structure and data flow
- 14 new unit tests in web/test/stats.test.mjs (140 total, all passing)
No backend changes — derives all metrics from existing /api/tasks and /api/executions endpoints.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Removed all template-related code from frontend (tabs, modals, logic) and backend (routes, files, DB table). Updated BUDGET_EXCEEDED tasks to be requeueable with a Restart button. Fixed ReferenceError in isUserEditing for Node.js tests.
|
|
- Running tab in nav with live SSE log streams per running task
- Execution history table (last 24h) with duration, cost, exit code, view logs
- Poll loop refreshes running view when tab is active
- Smart diff: only full re-render when task set changes; elapsed updated in place
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Recovered files with no Claude→Agent contamination:
- docs/adr/002-task-state-machine.md
- internal/api/logs.go/logs_test.go: task-level log streaming endpoint
- internal/api/validate.go/validate_test.go: POST /api/tasks/validate
- internal/api/server_test.go, storage/db_test.go: expanded test coverage
- scripts/reset-failed-tasks, reset-running-tasks
- web/app.js, index.html, style.css: frontend improvements
- web/test/: active-tasks-tab, delete-button, filter-tabs, sort-tasks tests
Manually applied from server.go diff (skipping Claude→Agent rename):
- taskLogStore field + validateCmdPath field
- DELETE /api/tasks/{id} route + handleDeleteTask
- GET /api/tasks/{id}/logs/stream route
- POST /api/tasks/{id}/resume route + handleResumeTimedOutTask
- handleCancelTask: allow cancelling PENDING/QUEUED tasks directly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
When an agent needs user input it writes a question to
$CLAUDOMATOR_QUESTION_FILE and exits. The runner detects the file and
returns BlockedError; the pool transitions the task to BLOCKED and
stores the question JSON on the task record.
The user answers via POST /api/tasks/{id}/answer. The server looks up
the claude session_id from the most recent execution and submits a
resume execution (claude --resume <session-id> "<answer>"), freeing the
executor slot entirely while waiting.
Changes:
- task: add StateBlocked, transitions RUNNING→BLOCKED, BLOCKED→QUEUED
- storage: add session_id to executions, question_json to tasks;
add GetLatestExecution and UpdateTaskQuestion methods
- executor: BlockedError type; ClaudeRunner pre-assigns --session-id,
sets CLAUDOMATOR_QUESTION_FILE env var, detects question file on exit;
buildArgs handles --resume mode; Pool.SubmitResume for resume path
- api: handleAnswerQuestion rewritten to create resume execution
- preamble: add question protocol instructions for agents
- web: BLOCKED state badge (indigo), question text + option buttons or
free-text input with Submit on the task card footer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- READY state task cards show Accept + Reject buttons
- Accept POSTs to /api/tasks/{id}/accept (→ COMPLETED)
- Reject POSTs to /api/tasks/{id}/reject (→ PENDING)
- "Start Next" button in toolbar POSTs to /api/scripts/start-next-task
- CSS for .btn-accept and .btn-reject
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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 <noreply@anthropic.com>
|
|
Replace the static "N hidden tasks" label with a toggle button that
expands an inline fold showing the hidden task cards dimmed at 0.6
opacity. Fold state is module-level so it survives poll cycles within
a session but resets on reload.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Serves a lightweight dashboard (HTML/CSS/JS) from an embedded FS at
GET /. The JS polls the REST API to display tasks and stream logs
via WebSocket. Static files are embedded at build time via web/embed.go.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|