summaryrefslogtreecommitdiff
path: root/internal/storage
AgeCommit message (Collapse)Author
12 daysfix: persist VAPID keys in DB instead of config filePeter Stone
The service runs as www-data which cannot write to the root-owned config file. VAPID keys are now stored in the settings table in SQLite (which is writable), loaded on startup, and generated once. Removes saveVAPIDToConfig and the stale warning on every restart. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
12 daysfeat: add web push notifications and file dropPeter Stone
Web Push: - WebPushNotifier with VAPID auth; urgency mapped to event type (BLOCKED=urgent, FAILED=high, COMPLETED=low) - Auto-generates VAPID keys on first serve, persists to config file - push_subscriptions table in SQLite (upsert by endpoint) - GET /api/push/vapid-key, POST/DELETE /api/push/subscribe endpoints - Service worker (sw.js) handles push events and notification clicks - Notification bell button in web UI; subscribes on click File Drop: - GET /api/drops, GET /api/drops/{filename}, POST /api/drops - Persistent ~/.claudomator/drops/ directory - CLAUDOMATOR_DROP_DIR env var passed to agent subprocesses - Drops tab (📁) in web UI with file listing and download links Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
12 daysfeat: add project column to storageClaudomator Agent
Adds project TEXT column to tasks table via additive migration, updates CreateTask INSERT, all SELECT queries, and scanTask to persist and retrieve Task.Project. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
13 daysfeat: add elaboration_input field to tasks for richer subtask placeholderClaudomator Agent
- Add ElaborationInput field to Task struct (task.go) - Add DB migration and update CREATE/SELECT/scan in storage/db.go - Update handleCreateTask to accept elaboration_input from API - Update renderSubtaskRollup in app.js to prefer elaboration_input over description - Capture elaborate prompt in createTask() form submission - Update subtask-placeholder tests to cover elaboration_input priority - Fix missing io import in gemini.go When a task card is waiting for subtasks, it now shows: 1. The raw user prompt from elaboration (if stored) 2. The task description truncated at word boundary (~120 chars) 3. The task name as fallback 4. 'Waiting for subtasks…' only when all fields are empty Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
13 daysfeat: overhaul auto-refresh system with intelligent polling and differential ↵Peter Stone
updates
14 daysfeat: fix task failures via sandbox improvements and display commits in Web UIPeter Stone
- 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.
14 daysfeat: add Changestats struct and storage supportClaudomator Agent
- Add task.Changestats{FilesChanged, LinesAdded, LinesRemoved} - Add changestats_json column to executions via additive migration - Add Changestats field to storage.Execution struct - Add UpdateExecutionChangestats(execID, *task.Changestats) method - Update all SELECT/INSERT/scan paths for executions - Test: TestExecution_StoreAndRetrieveChangestats (was red, now green) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14feat: persist agent assignment before task executionClaudomator Agent
- Add UpdateTaskAgent to Store interface and DB implementation - Call UpdateTaskAgent in Pool.execute to persist assigned agent/model to database before the runner starts - Update runTask in app.js to pass selected agent as query param Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13test: add storage tests for UpdateTaskSummary and AppendTaskInteractionClaudomator Agent
The summary+interactions feature was already fully implemented but lacked storage-layer tests. Added tests covering round-trip persistence of task summaries, accumulation of Q&A interactions, and error handling for nonexistent tasks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13feat: resume support, summary extraction, and task state improvementsPeter Stone
- 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>
2026-03-11fix: clear question_json when restarting a task via ResetTaskForRetryPeter Stone
A BLOCKED task that fails on resume would keep its stale question_json after being restarted. The frontend then showed "waiting for your input" with the old prompt even though the task was running fresh. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11fix: resume BLOCKED tasks in preserved sandbox so Claude finds its sessionPeter Stone
When a task ran in a sandbox (/tmp/claudomator-sandbox-*) and went BLOCKED, Claude stored its session under the sandbox path as the project slug. The resume execution was running in project_dir, causing Claude to look for the session in the wrong project directory and fail with "No conversation found". Fix: carry SandboxDir through BlockedError → Execution → resume execution, and run the resume in that directory so the session lookup succeeds. - BlockedError gains SandboxDir field; claude.go sets it on BLOCKED exit - storage.Execution gains SandboxDir (persisted via new sandbox_dir column) - executor.go stores blockedErr.SandboxDir in the execution record - server.go copies SandboxDir from latest execution to the resume execution - claude.go uses e.SandboxDir as working dir for resume when set Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10fix: ensure tasks are re-classified on manual restartPeter Stone
Updated handleRunTask to use ResetTaskForRetry, which clears the agent type and model. This ensures that manually restarted tasks are always re-classified, allowing the system to switch to a different agent if the previous one is rate-limited. Also improved Claude quota-exhaustion detection.
2026-03-10Remove legacy claude field and working_dir backward compatClaudomator Agent
- Remove Claude field alias from Task struct (already removed in sandbox) - Remove UnmarshalJSON from AgentConfig that silently accepted working_dir - Remove legacy claude fallback in scanTask (db.go) - Remove TestGetTask_BackwardCompatibility test that validated removed behavior Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09storage: fix DeleteTask atomicity and use recursive CTEClaudomator Agent
Replace BFS loop with a single recursive CTE to collect all descendant task IDs in one query, and wrap all DELETE statements in a transaction so a partial failure cannot leave orphaned executions. Add TestDeleteTask_DeepSubtaskCascadeAtomic: creates a 3-level task hierarchy with executions at each level, deletes the root, and verifies all tasks and executions are removed with an explicit orphan-row check. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09storage: add missing indexes and ListRecentExecutions correctness testsClaudomator Agent
Add two schema indexes that were missing: - idx_executions_start_time on executions(start_time): speeds up ListRecentExecutions WHERE start_time >= ? ORDER BY start_time DESC - idx_tasks_parent_task_id on tasks(parent_task_id): speeds up ListSubtasks WHERE parent_task_id = ? Both use CREATE INDEX IF NOT EXISTS so they are safe to apply on existing databases without a migration version bump. Add TestListRecentExecutions_LargeDataset (100 rows, two tasks) covering: - returns all rows in descending start_time order - respects the limit parameter - filters correctly by since time - filters correctly by task_id Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09chore: remove deleted template files from gitPeter Stone
2026-03-09feat: delete templates feature and allow requeueing BUDGET_EXCEEDED tasksPeter Stone
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.
2026-03-08fix: restore task execution broken by add-gemini mergePeter Stone
- handleCreateTask: add legacy "claude" key fallback in input struct so old clients and YAML files sending claude:{...} still work - cli/create: send "agent" key instead of "claude"; add --agent-type flag - storage/db_test: fix ClaudeConfig → AgentConfig after rename Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08merge: pull latest from master and resolve conflictsPeter Stone
- Resolve conflicts in API server, CLI, and executor. - Maintain Gemini classification and assignment logic. - Update UI to use generic agent config and project_dir. - Fix ProjectDir/WorkingDir inconsistencies in Gemini runner. - All tests passing after merge.
2026-03-08storage: enforce valid state transitions in UpdateTaskStatePeter Stone
UpdateTaskState now validates the transition using ValidTransition inside a transaction. Invalid transitions return an error rather than blindly updating. Tests for retry-limit and running-task-rejection test setup are updated to create tasks with the target state directly via CreateTask to bypass the transition guard in setup code. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08refactor: address code review notes (backward compat, Gemini tests, unknown ↵Peter Stone
agent test)
2026-03-08refactor(storage): update templates to use generic agent configPeter Stone
2026-03-08fix(storage): use Agent field instead of Claude in CreateTaskPeter Stone
2026-03-08test(storage): update db_test.go to use AgentConfigPeter Stone
2026-03-06recover: restore untracked work from recovery branch (no Gemini changes)Peter Stone
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>
2026-03-06fix: persist session_id in UpdateExecution so BLOCKED tasks can resumePeter Stone
session_id was set on the Execution struct inside ClaudeRunner.Run but was missing from the UPDATE query, so it was never written to the DB. GetLatestExecution then returned an empty session_id, causing the /answer endpoint to return "no resumable session found". Also patched the existing blocked execution row directly in the DB. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06feat: blocked task state for agent questions via session resumePeter Stone
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>
2026-03-04Add READY state for human-in-the-loop verificationPeter Stone
Top-level tasks now land in READY after successful execution instead of going directly to COMPLETED. Subtasks (with parent_task_id) skip the gate and remain COMPLETED. Users accept or reject via new API endpoints: POST /api/tasks/{id}/accept → READY → COMPLETED POST /api/tasks/{id}/reject → READY → PENDING (with rejection_comment) - task: add StateReady, RejectionComment field, update ValidTransition - storage: migrate rejection_comment column, add RejectTask method - executor: route top-level vs subtask to READY vs COMPLETED - api: /accept and /reject handlers with 409 on invalid state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03Add elaborate, logs-stream, templates, and subtask-list endpointsPeter Stone
- POST /api/tasks/elaborate: calls claude to draft a task config from a natural-language prompt - GET /api/executions/{id}/logs/stream: SSE tail of stdout.log - CRUD /api/templates: create/list/get/update/delete reusable task configs - GET /api/tasks/{id}/subtasks: list child tasks - Server.NewServer accepts claudeBinPath for elaborate; injectable elaborateCmdPath and logStore for test isolation - Valid-transition guard added to POST /api/tasks/{id}/run - CLI passes claude binary path through to the server Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03Add subtask support: parent_task_id, ListSubtasks, UpdateTaskPeter Stone
- Task struct gains ParentTaskID field - DB schema adds parent_task_id column (additive migration) - DB.ListSubtasks fetches children of a parent task - DB.UpdateTask allows partial field updates (name, description, state, etc.) - Templates table added to initial schema Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-08Rename Go module to github.com/thepeterstone/claudomatorPeter Stone
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08Initial project: task model, executor, API server, CLI, storage, reporterPeter Stone
Claudomator automation toolkit for Claude Code with: - Task model with YAML parsing, validation, state machine (49 tests, 0 races) - SQLite storage for tasks and executions - Executor pool with bounded concurrency, timeout, cancellation - REST API + WebSocket for mobile PWA integration - Webhook/multi-notifier system - CLI: init, run, serve, list, status commands - Console, JSON, HTML reporters with cost tracking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>