| Age | Commit message (Collapse) | Author |
|
Merges 12 commits from github/main (formerly master) that were developed
independently. Key additions:
- LocalRunner: OpenAI-compatible local LLM execution (Ollama, LM Studio)
- Real GeminiRunner with full sandbox parity to ClaudeRunner
- llm.Client for enriching CI failures and elaboration via local model
- retry.ParseRetryAfter moved to shared package
- tokens_in/tokens_out columns in executions table
Conflict resolutions:
- Kept local main's VAPID/push, stories, projects, agent events schema
- Merged both sets of Config fields (local + LocalModel from github/main)
- Unified activePerAgent accounting (decActiveAgent helper)
- Removed duplicate helpers from claude.go (now in helpers.go)
- Fixed double-decrement bug in handleRunResult vs decActiveAgent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Phase 2 of "local OSS models as agents" plan. Adds a third elaboration
path that calls the local OpenAI-compatible LLM via the internal/llm
client, and reorders dispatch so the cheap path is tried first:
local → claude → gemini, with each next attempt only on hard failure
of the prior.
Wiring is opt-out, not opt-in: when [local_model].endpoint is set,
elaboration prefers local by default. Users with a slow or low-quality
local model can disable just elaboration via:
[local_model]
endpoint = "..."
prefer_for_elaborate = false
without giving up the runner or the classifier path.
Implementation:
- Server gains an optional *llm.Client field via SetLLM (matches the
existing SetNotifier/SetWorkspaceRoot setter pattern, no NewServer
signature break).
- elaborateWithLocal() reuses buildElaboratePrompt verbatim and asks
for response_format=json_object so we skip markdown-fence cleanup.
- handleElaborateTask reorders try chain; existing Claude-first
behavior is preserved exactly when SetLLM is not called.
- LocalModel.UseForElaborate() encapsulates the default-true gating
with a *bool so explicit-false survives TOML parse.
Tests:
- elaborateWithLocal: parses valid response, errors on nil client,
errors on bad JSON.
- handler: local preferred when wired; falls back to claude when
local fails; unchanged behavior when no LLM is configured.
- config: UseForElaborate gating across empty/default/explicit-true/
explicit-false cases.
Pre-existing test failures noted in docs/plans/local-oss-runner.md
(post-epic cleanup): TestGeminiLogs_ParsedCorrectly returns 404 for
gemini execution log fetch — predates this change.
Plan: docs/plans/local-oss-runner.md.
https://claude.ai/code/session_017Edeq947TpSm1vQTxMhi1J
|
|
Add AcceptanceCriteria field to elaboratedStoryTask struct, update
buildStoryElaboratePrompt schema and rules, pass the value through
handleApproveStory into task.Task, and add a test verifying the
field is persisted on approved story tasks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
scripts
- handleApproveStory: set Project = input.ProjectID on tasks and subtasks so
the executor can resolve RepositoryURL from the project registry (was causing
"task has no repository_url" on every story task)
- elaborate.go: read .agent/worklog.md instead of SESSION_STATE.md for project
context injected into elaboration prompts
- deploy: explicitly chmod +x all scripts before restart (same root cause as
the binary execute-bit loss — chown -R was stripping it)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- POST /api/stories/elaborate: runs Claude/Gemini against project LocalPath
to produce a structured story plan (name, branch_name, tasks, validation)
- POST /api/stories/approve: creates story + sequentially-wired tasks/subtasks
from the elaborate output and pushes the story branch to origin
- createStoryBranch helper: git checkout -b + push -u origin
- Tests: TestBuildStoryElaboratePrompt, TestHandleStoryApprove_WiresDepends
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- task.Project type + storage CRUD + UpsertProject + SeedProjects
- Remove AgentConfig.ProjectDir, RepositoryURL, SkipPlanning
- Remove ContainerRunner fallback git init logic
- Project API endpoints: GET/POST /api/projects, GET/PUT /api/projects/{id}
- processResult no longer extracts changestats (pool-side only)
- claude_config_dir config field; default to credentials/claude/
- New scripts: sync-credentials, fix-permissions, check-token
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
elaboration fallback
|
|
Previously appendRawNarrative was called with the server's default workDir
(os.Getwd()) when no project_dir was in the request, causing test runs and
any elaboration without a project to pollute the repo's own RAW_NARRATIVE.md.
The narrative is per-project human input — only write it when the caller
explicitly specifies which project they're working in.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
practices
Add sanitizeElaboratedTask() called after every elaboration response:
- Infers missing allowed_tools from instruction keywords (Write/Edit/Read/Bash/Grep/Glob)
- Auto-adds Read when Edit is present
- Appends Acceptance Criteria section if none present
- Appends TDD reminder for coding tasks without test mention
Also tighten buildElaboratePrompt to require acceptance criteria and
list concrete tool examples, reducing how often the model omits tools.
Fixes class of failures where agents couldn't create files because
the elaborator omitted Write from allowed_tools.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
The elaborator now logs every user prompt to docs/RAW_NARRATIVE.md within the project directory. This is done in a background goroutine to ensure it doesn't delay the response.
|
|
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.
|
|
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).
|
|
- 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.
|
|
- 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>
|
|
- 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>
|
|
|
|
The elaborate call now sends working_dir from the Project dropdown.
The backend uses it (falling back to server workDir) when building
the system prompt, so AI-drafted tasks are contextualised to the
selected project.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
executor/claude.go: stat working_dir before cmd.Start() so a missing
or inaccessible directory surfaces as a clear error
("working_dir \"/bad/path\": no such file or directory") rather than
an opaque chdir failure wrapped in "starting claude".
api/elaborate.go: replace the hardcoded /root/workspace/claudomator
path with buildElaboratePrompt(workDir) which injects the server's
actual working directory (from os.Getwd() at startup). Empty workDir
tells the model to leave working_dir blank.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- 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>
|