| Age | Commit message (Collapse) | Author |
|
The elaborator now reads CLAUDE.md and SESSION_STATE.md from the project directory (if they exist) and prepends their content to the user prompt. This allows the AI to generate tasks that are more context-aware.
|
|
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.
|
|
The --config flag was registered but silently ignored. Now:
- config.LoadFile loads a TOML file on top of defaults
- PersistentPreRunE applies the file when --config is set
- Explicit CLI flags (--data-dir, --claude-bin) take precedence over the file
Tests: TestLoadFile_OverridesDefaults, TestLoadFile_MissingFile_ReturnsError,
TestRootCmd_ConfigFile_Loaded, TestRootCmd_ConfigFile_CLIFlagOverrides,
TestRootCmd_ConfigFile_Missing_ReturnsError
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Both execute() and executeResume() shared ~80% identical post-run logic:
error classification (BLOCKED, TIMED_OUT, CANCELLED, BUDGET_EXCEEDED, FAILED),
state transitions, result emission, and UpdateExecution. Extract this into
handleRunResult(ctx, t, exec, err, agentType) on *Pool. Both functions now
call it after runner.Run() returns.
Also adds TestHandleRunResult_SharedPath which directly exercises the new
function via a minimalMockStore, covering FAILED, READY, COMPLETED, and
TIMED_OUT classification paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- 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>
|
|
Add maybeUnblockParent helper that transitions a BLOCKED parent task to
READY once every subtask is in the COMPLETED state. Called in both
execute() and executeResume() immediately after a subtask is marked
COMPLETED. Any non-COMPLETED sibling (RUNNING, FAILED, etc.) keeps the
parent BLOCKED.
Tests added:
- TestPool_Submit_LastSubtask_UnblocksParent
- TestPool_Submit_NotLastSubtask_ParentStaysBlocked
- TestPool_Submit_ParentNotBlocked_NoTransition
|
|
When a top-level task (ParentTaskID == "") finishes successfully,
check for subtasks before deciding the next state:
- subtasks exist → BLOCKED (waiting for subtasks to complete)
- no subtasks → READY (existing behavior, unchanged)
This applies to both execute() and executeResume().
Adds ListSubtasks to the Store interface.
Tests:
- TestPool_Submit_TopLevel_WithSubtasks_GoesBlocked
- TestPool_Submit_TopLevel_NoSubtasks_GoesReady
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
All previously ignored errors from p.store.UpdateTaskState() and
p.store.UpdateTaskQuestion() in execute() and executeResume() now log
with structured context (taskID, state, error).
Introduces a Store interface so tests can inject a failing mock store.
Adds TestPool_UpdateTaskState_DBError_IsLoggedAndResultDelivered to
verify that a DB write failure is logged and the result is still
delivered to resultCh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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>
|
|
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>
|
|
response shapes
- handleListTasks: validate ?state= against known states, return 400 with clear
error for unrecognized values (e.g. ?state=BOGUS)
- handleCancelTask: replace {"status":"cancelling"|"cancelled"} with
{"message":"...","task_id":"..."} to match run/resume shape
- handleAnswerQuestion: replace {"status":"queued"} with
{"message":"task queued for resume","task_id":"..."}
- Tests: add TestListTasks_InvalidState_Returns400, TestListTasks_ValidState_Returns200,
TestCancelTask_ResponseShape, TestAnswerQuestion_ResponseShape,
TestRunTask_ResponseShape, TestResumeTimedOut_ResponseShape
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace the no-op mockRunner in server_test.go with a configurable
version that supports err and sleep fields. Add testServerWithRunner
helper and a pollState utility for async assertions.
Add three new tests that exercise the pool's error paths end-to-end:
- TestRunTask_AgentFails_TaskSetToFailed
- TestRunTask_AgentTimesOut_TaskSetToTimedOut
- TestRunTask_AgentCancelled_TaskSetToCancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
The pgid-kill goroutine in execOnce() uses a select with both ctx.Done()
and the killDone channel. Add a detailed comment explaining why the goroutine
cannot block indefinitely: the killDone arm fires unconditionally when
cmd.Wait() returns (whether the process exited naturally or was killed),
so the goroutine always exits before execOnce() returns.
Add TestExecOnce_NoGoroutineLeak_OnNaturalExit to verify this: it samples
runtime.NumGoroutine() before and after execOnce() with a no-op binary
("true") and a background context (never cancelled), asserting no net
goroutine growth.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
Updated isQuotaExhausted to detect more Claude quota messages. Added 'rate limit reached (rejected)' to quota exhausted checks. Strengthened classifier prompt to explicitly forbid selecting rate-limited agents. Improved Pool to set 5h rate limit on quota exhaustion.
|
|
concurrent rejection
- Remove git pull into project_dir: working copy is the developer workspace
and should be pulled manually; www-data can't write to root-owned .git/objects
- On non-fast-forward push rejection (concurrent task pushed first), fetch and
rebase then retry once instead of failing the entire task
|
|
activePerAgent: delete zero-count entries after decrement so the map
doesn't accumulate stale keys for agent types that are no longer active.
rateLimited: delete entries whose deadline has passed when reading them
(in both the classifier block and the execute() pre-flight), so stale
entries are cleaned up on the next check rather than accumulating forever.
Both fixes are covered by new regression tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Add workspaceRoot field (default "/workspace") to Server struct
- Add SetWorkspaceRoot method on Server
- Update handleListWorkspaces to use s.workspaceRoot
- Add WorkspaceRoot field to Config with default "/workspace"
- Wire cfg.WorkspaceRoot into server in serve.go
- Expose --workspace-root flag on the serve command
- Add TestListWorkspaces_UsesConfiguredRoot integration test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
On restart, any tasks in RUNNING state have no active goroutine.
RecoverStaleRunning() marks them FAILED (retryable) and closes
their open execution records with an appropriate error message.
Called once from serve.go after the pool is created.
|
|
|
|
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.
|
|
Permitted BUDGET_EXCEEDED -> QUEUED transition in ValidTransition. Updated frontend to show 'Restart' button for BUDGET_EXCEEDED tasks, allowing them to be requeued after failure.
|
|
Updated parseStream to detect 'rate_limit_event' and 'assistant' error:rate_limit messages from the Claude CLI. Updated Classifier to strongly prefer non-rate-limited agents. Added logging to Pool to track rate-limit status during classification.
|
|
Update the default Gemini model and classification prompt to use gemini-2.5-flash-lite, which is the current available model. Improved the classifier's parsing logic to correctly handle the JSON envelope returned by the gemini CLI (stripping 'response' wrapper and 'Loaded cached credentials' noise).
|
|
Instead of git fetch/merge INTO the working copy (which fails with
mixed-owner .git/objects), clone FROM a bare repo, push BACK to it,
then pull into the working copy:
sandbox clone ← bare repo (local remote or origin)
agent commits in sandbox
git push sandbox → bare repo
git pull bare repo → working copy
sandboxCloneSource() prefers a remote named "local" (local bare repo),
then "origin", then falls back to the working copy path.
Set up: git remote add local /site/git.terst.org/repos/claudomator.git
The bare repo was created with: git clone --bare /workspace/claudomator
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Fix: use file:// prefix in git fetch during sandbox teardown to force
pack-protocol transfer. The local optimization uses hard links which
fail across devices and with mixed-owner object stores.
Feature: before running a task, query prior failed/timed-out executions
and prepend their error messages to the agent's --append-system-prompt.
This tells the agent what went wrong in previous attempts so it doesn't
repeat the same mistakes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
Agents running in a sandbox must commit all changes before exiting.
The teardown rejects any dirty working tree. Add an explicit section
to the planning preamble making this requirement clear.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
git clone --local fails with "Invalid cross-device link" when /workspace
and /tmp are on different filesystems. --no-hardlinks forces object
copying instead, which works across devices.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Remove the MaxAttempts check from POST /api/tasks/{id}/run. A user
explicitly triggering a run is a manual action and should not be gated
by the retry limit. Retry limits will be enforced in the (future)
automatic retry path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- 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>
|
|
Restore the script registry in internal/cli/serve.go which was lost
during the gemini merge. This fixes the 'Start Next Task' button in the
web UI which relies on the /api/scripts/start-next-task endpoint.
|
|
- 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.
|
|
- Add Classifier using gemini-2.0-flash-lite to automatically select agent/model.
- Update Pool to track per-agent active tasks and rate limit status.
- Enable classification for all tasks (top-level and subtasks).
- Refine SystemStatus to be dynamic across all supported agents.
- Add unit tests for the classifier and updated pool logic.
- Minor UI improvements for project selection and 'Start Next' action.
|
|
- Extract newLogger() to remove duplication across run/serve/start
- Add defaultServerURL const ("http://localhost:8484") used by all client commands
- Move http.Client into internal/cli/http.go with 30s timeout
- Add 'report' command for printing execution summaries
- Add test coverage for create and serve commands
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Default() now returns (*Config, error) so callers can detect TOML parse
failures rather than silently falling back to zero values.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- handleListRecentExecutions: add since/limit/task_id query params
- handleStreamLogs: tighten SSE framing and cleanup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Extract questionStore interface for testability of handleAnswerQuestion
- Add SetAPIToken/SetNotifier methods for post-construction wiring
- Extract processResult() from forwardResults() for direct testability
- Add ipRateLimiter with token-bucket per IP; applied to /elaborate and /validate
- Fix tests for running-task deletion and retry-limit that relied on
invalid state transitions in setup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace hardcoded handleStartNextTask/handleDeploy with a single
handleScript handler keyed by name from a ScriptRegistry map.
Scripts are now configured via Server.SetScripts() rather than
individual setter fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Require bearer token on WebSocket connections when apiToken is set
- Cap concurrent WebSocket clients at maxWsClients (1000, overridable)
- Send periodic pings every 30s; close dead connections after 10s write deadline
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace the at-capacity error return from Submit/SubmitResume with an
internal workCh/doneCh channel pair. A dispatch() goroutine blocks
waiting for a free slot and launches the worker goroutine, so tasks are
buffered up to 10x pool capacity instead of being rejected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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>
|
|
- ClaudeConfig.WorkingDir → ProjectDir (json: project_dir)
- UnmarshalJSON fallback reads legacy working_dir from DB records
- New executions with project_dir clone into a temp sandbox via git clone --local
- Non-git project_dirs get git init + initial commit before clone
- After success: verify clean working tree, merge --ff-only back to project_dir, remove sandbox
- On failure/BLOCKED: sandbox preserved, path included in error message
- Resume executions run directly in project_dir (no re-clone)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
agent test)
|
|
|
|
|
|
|
|
When claude hits the 5-hour usage limit it exits 1. execOnce was
returning the generic "exit status 1" error, hiding the real cause from
the retry loop and the task state machine.
Fix:
- execOnce now surfaces streamErr when it indicates rate limiting or
quota exhaustion, so callers see the actual message.
- New isQuotaExhausted() detects "hit your limit" messages — these are
not retried (retrying a depleted 5h bucket wastes nothing but is
pointless), and map to BUDGET_EXCEEDED in both execute/executeResume.
- isRateLimitError() remains for transient throttling (429/overloaded),
which continues to trigger exponential backoff retries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|