Enable the orchestrator to assign 1-3 features per coding agent subprocess,
selected via dependency chain extension + same-category fill. This reduces
cold-start overhead and leverages shared context across related features.
Orchestrator (parallel_orchestrator.py):
- Add batch tracking: _batch_features and _feature_to_primary data structures
- Add build_feature_batches() with dependency chain + category fill algorithm
- Add start_feature_batch() and _spawn_coding_agent_batch() methods
- Update _on_agent_complete() for batch cleanup across all features
- Update stop_feature() with _feature_to_primary lookup
- Update get_ready_features() to exclude all batch feature IDs
- Update main loop to build batches then spawn per available slot
CLI and agent layer:
- Add --feature-ids (comma-separated) and --batch-size CLI args
- Add feature_ids parameter to run_autonomous_agent() with batch prompt selection
- Add get_batch_feature_prompt() with sequential workflow instructions
WebSocket layer (server/websocket.py):
- Add BATCH_CODING_AGENT_START_PATTERN and BATCH_FEATURES_COMPLETE_PATTERN
- Add _handle_batch_agent_start() and _handle_batch_agent_complete() methods
- Add featureIds field to all agent_update messages
- Track current_feature_id updates as agent moves through batch
Frontend (React UI):
- Add featureIds to ActiveAgent and WSAgentUpdateMessage types
- Update KanbanColumn and DependencyGraph agent-feature maps for batch
- Update AgentCard to show "Batch: #X, #Y, #Z" with active feature highlight
- Add "Features per Agent" segmented control (1-3) in SettingsModal
Settings integration (full stack):
- Add batch_size to schemas, settings router, agent router, process manager
- Default batch_size=3, user-configurable 1-3 via settings UI
- batch_size=1 is functionally identical to pre-batching behavior
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Redesign ProgressDashboard from tall stacked layout to compact inline:
title/badge left, passing/total right, progress bar with percentage below
- Absorb AgentThought functionality directly into ProgressDashboard,
showing the agent's current thought below the progress bar
- Remove standalone AgentThought usage from App.tsx (component now unused)
- Pass logs/agentStatus to ProgressDashboard in single-agent mode only
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace the PLAYWRIGHT_HEADLESS environment variable with a global
setting toggle in the Settings modal. The setting is persisted in the
registry DB and injected as an env var into agent subprocesses, so
client.py reads it unchanged.
Backend:
- Add playwright_headless field to SettingsResponse/SettingsUpdate schemas
- Read/write the setting in settings router via existing _parse_bool helper
- Pass playwright_headless from agent router through to process manager
- Inject PLAYWRIGHT_HEADLESS env var into subprocess environment
Frontend:
- Add playwright_headless to Settings/SettingsUpdate TypeScript types
- Add "Headless Browser" Switch toggle below YOLO mode in SettingsModal
- Add default value to DEFAULT_SETTINGS in useProjects
Also fix CSS build warning: change @import url("tw-animate-css") to bare
@import "tw-animate-css" so Tailwind v4 inlines it during compilation
instead of leaving it for Vite/Lightning CSS post-processing.
Remove stale summary.md from previous refactoring session.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add centralized path resolution module (autocoder_paths.py) that
consolidates all autocoder-generated file paths behind a dual-path
strategy: check .autocoder/X first, fall back to root-level X for
backward compatibility, default to .autocoder/X for new projects.
Key changes:
- New autocoder_paths.py with dual-path resolution for features.db,
assistant.db, lock files, settings, prompts dir, and progress cache
- migrate_project_layout() safely moves old-layout projects to new
layout with SQLite WAL flush and integrity verification
- Updated 22 files to delegate path construction to autocoder_paths
- Reset/delete logic cleans both old and new file locations
- Orphan lock cleanup checks both locations per project
- Migration called automatically at agent start in autonomous_agent_demo.py
- Updated markdown commands/skills to reference .autocoder/prompts/
- CLAUDE.md documentation updated with new project structure
Files at project root that remain unchanged:
- CLAUDE.md (Claude SDK reads from cwd via setting_sources=["project"])
- app_spec.txt root copy (agent templates reference it via cat)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Narrow `\boverloaded\b` regex to require server/api/system context,
preventing false positives when Claude discusses method/operator
overloading in OOP code (C++, Java, C#, etc.)
- Restore 24-hour cap for absolute reset-time delays instead of 1-hour
clamp, avoiding unnecessary retry loops when rate limits reset hours
in the future
- Add test for Retry-After: 0 returning 0 (regression lock for the
`is not None` fix)
- Add false positive tests for "overloaded" in programming context
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The onComplete handler in the empty Kanban spec creation flow only
logged errors to console.error, leaving users with no feedback when
the agent failed to start. This wires up the SpecCreationChat
component's built-in error UI (spinner, error banner, retry button)
via initializerStatus, initializerError, and onRetryInitializer props.
Changes:
- Add InitializerStatus type and specInitializerStatus/Error state
- Set status to 'starting' before startAgent call (shows spinner)
- On error, keep spec chat open so the error banner is visible
- On success, close chat and refresh queries (same as before)
- Wire up onRetryInitializer to reset state to idle
- Reset initializer status on cancel/exit for clean re-entry
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace ineffective threading.Lock() with atomic SQL operations for
cross-process safety. Key changes:
- Add SQLAlchemy event hooks (do_connect/do_begin) for BEGIN IMMEDIATE
transactions in api/database.py
- Add atomic_transaction() context manager for multi-statement ops
- Convert all feature MCP write operations to atomic UPDATE...WHERE
with compare-and-swap patterns (feature_claim, mark_passing, etc.)
- Add WHERE passes=0 state guard to feature_mark_passing
- Add WAL checkpoint on shutdown and idempotent cleanup() in
parallel_orchestrator.py with async-safe signal handling
- Wrap SQLite connections with contextlib.closing() in progress.py
- Add thread-safe engine cache with double-checked locking in
assistant_database.py
- Migrate to SQLAlchemy 2.0 DeclarativeBase across all modules
Inspired by PR #108 (cabana8471-arch), with fixes for nested
BEGIN EXCLUSIVE bug and missing state guards.
Closes#106
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add explicit session.rollback() in exception handlers for database
context managers in features.py, schedules.py, and database.py get_db()
to prevent SQLAlchemy PendingRollbackError on failed transactions
- Add EXPAND_FEATURE_TOOLS to expand session security settings allow list
so the expand skill can use the MCP tools it references
- Update assistant session prompt to direct the LLM to call MCP tools
directly for feature creation instead of suggesting CLI commands
Cherry-picked fixes from PR #92 (closed) with cleaner implementation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Trim the env var value and fall back to the default model when the
trimmed result is empty. This prevents invalid empty strings from
being appended to VALID_MODELS.
Addresses CodeRabbit review feedback on PR #147.
When ANTHROPIC_DEFAULT_OPUS_MODEL env var is set to a custom model ID,
that model was not present in VALID_MODELS (derived from AVAILABLE_MODELS),
causing potential validation failures in server/schemas.py validators.
This fix dynamically appends the env-provided DEFAULT_MODEL to VALID_MODELS
when set, ensuring validators accept the runtime default. The merge is
idempotent (only adds if missing) and doesn't alter AVAILABLE_MODELS semantics.
Addresses CodeRabbit review feedback on PR #147.
When creating a spec from an empty Kanban board (via "Create Spec" button),
the agent was not automatically starting after clicking "Continue to Project".
Root cause: The SpecCreationChat component in App.tsx had an onComplete handler
that only closed the chat and refreshed queries, but did not call startAgent().
This was different from the NewProjectModal flow which correctly started the agent.
Changes:
- Add startAgent import to App.tsx
- Update onComplete handler to call startAgent() with yoloMode and maxConcurrency
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: NewProjectModal was rendered inside ProjectSelector (in header),
causing the fixed inset-0 container to be constrained by the dropdown DOM tree.
Changes:
- NewProjectModal.tsx: Use createPortal to render chat screen at document.body level
- SpecCreationChat.tsx: Change h-full to h-screen for explicit viewport height
- SpecCreationChat.tsx: Add min-h-0 to messages area for proper flexbox scrolling
This fixes the chat screen not displaying full-screen when creating a new project
with Claude.
Use the shared clamp_retry_delay() function (1-hour cap) for parsed
reset-time delays instead of a separate 24-hour cap. This aligns with
the PR's consistent 1-hour maximum delay objective.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1. agent.py: Reset opposite retry counter when entering rate_limit or error
status to prevent mixed events from inflating delays
2. rate_limit_utils.py: Fix parse_retry_after() regex to reject minute/hour
units - patterns now require explicit "seconds"/"s" unit or end of string
3. test_rate_limit_utils.py: Add tests for "retry after 5 minutes" and other
minute/hour variants to ensure they return None
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename compute_mode -> convert_model_for_vertex for clarity
- Move `import re` to module top-level (stdlib convention)
- Use greedy regex quantifier for more readable pattern matching
- Restore PEP 8 double blank line between top-level definitions
- Add test_client.py with 10 unit tests covering:
- Vertex disabled (env unset, "0", empty)
- Standard conversions (Opus, Sonnet, Haiku)
- Edge cases (already-converted, non-Claude, no date suffix, empty)
Follow-up improvements from PR #129 review.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add comment on running_coding_agents explaining why feature_id keying
is safe (start_feature checks for duplicates before spawning), since
the sister dict running_testing_agents required PID keying to avoid
overwrites from concurrent same-feature testing
- Clear running_testing_agents dict in stop_all() after killing
processes so get_status() doesn't report stale agent counts while
_on_agent_complete callbacks are still in flight
Follow-up to PR #130 (runaway testing agent spawn fix).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
running_testing_agents was keyed by feature_id, so when multiple agents
tested the same feature, each spawn overwrote the previous dict entry.
The count stayed at 1 regardless of how many processes were actually
running, causing the maintain loop to spawn agents indefinitely (~130+).
Re-key the dict by PID so each agent gets a unique entry and the
existing max-agent guards work correctly. Also check the return value
of _spawn_testing_agent() to break the loop on failure.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update the documented test count in CLAUDE.md to reflect the current
state after merging PR #100 which added diagnostic warnings for config
loading failures. The test suite now includes additional tests for:
- Empty command name validation in project configs
- Config loading diagnostic warnings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Follow-up to PR #89 - apply the same popen_kwargs pattern with
stdin=DEVNULL and CREATE_NO_WINDOW to _spawn_testing_agent() and
_run_initializer() for consistent Windows behavior.
Also fixes typo: _kill_process_tree -> kill_process_tree
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the ability to reset a project to its initial state with two options:
- Quick Reset: Clears features.db, assistant.db, and settings files while
preserving app spec and prompts
- Full Reset: Deletes everything including prompts directory, triggering
the setup wizard for project reconfiguration
Backend changes:
- Add POST /{name}/reset endpoint to projects router with full_reset query param
- Validate agent lock file to prevent reset while agent is running (409 Conflict)
- Dispose database engines before deleting files to release Windows file locks
- Add engine caching to api/database.py for better connection management
- Add dispose_engine() functions to both database modules
- Delete WAL mode journal files (*.db-wal, *.db-shm) during reset
Frontend changes:
- Add ResetProjectModal component with toggle between Quick/Full reset modes
- Add ProjectSetupRequired component shown when has_spec is false
- Add resetProject API function and useResetProject React Query hook
- Integrate reset button in header (disabled when agent running)
- Add 'R' keyboard shortcut to open reset modal
- Show ProjectSetupRequired when project needs setup after full reset
This implements the feature from PR #4 directly on master to avoid merge
conflicts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a test case to verify that empty command names are rejected
in project-level allowed_commands.yaml, matching the behavior already
tested for org-level config. Updates test count to 163.
Addresses review feedback from leonvanzyl.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Per CodeRabbit feedback, add logger.warning calls when pkill_processes
validation fails in both load_org_config and load_project_commands.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When config files have errors, users had no way to know why their
settings weren't being applied. Added logging.warning() calls to
diagnose:
- Empty config files
- Missing 'version' field
- Invalid structure (not a dict)
- Invalid command entries
- Exceeding 100 command limit
- YAML parse errors
- File read errors
Also added .resolve() to project path to handle symlinks correctly.
Fixes: leonvanzyl/autocoder#91
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add debug logging when shlex fallback extraction is used, capturing
both successful extractions and failures for security auditing
- Add test case for docker nested quotes that trigger fallback parser
- Remove redundant comment about re import (already at module level)
Follow-up improvements from PR #127 code review:
- Enables tracking of malformed command patterns in production logs
- Verifies fallback parser handles the exact docker exec case reported
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `default_concurrency` column to the projects table in the registry
database, allowing each project to remember its preferred concurrency
setting (1-5 agents). The value persists across page refreshes and
app restarts.
Backend changes:
- Add `default_concurrency` column to Project model in registry.py
- Add database migration for existing databases (ALTER TABLE)
- Add get/set_project_concurrency() CRUD functions
- Add ProjectSettingsUpdate schema with validation
- Add PATCH /{name}/settings endpoint in projects router
- Include default_concurrency in ProjectSummary/ProjectDetail responses
Frontend changes:
- Add default_concurrency to ProjectSummary TypeScript interface
- Add ProjectSettingsUpdate type and updateProjectSettings API function
- Add useUpdateProjectSettings React Query mutation hook
- Update AgentControl to accept defaultConcurrency prop
- Sync local state when project changes via useEffect
- Debounce slider changes (500ms) before saving to backend
- Pass defaultConcurrency from selectedProjectData in App.tsx
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create shared `isSubmitEnter()` utility in `ui/src/lib/keyboard.ts`
for IME-aware Enter key handling across all input components
- Extract magic number 48 to named constant `COLLAPSED_DEBUG_PANEL_CLEARANCE`
with explanatory comment (40px panel header + 8px margin)
- Update 5 components to use the new utility:
- AssistantChat.tsx
- ExpandProjectChat.tsx
- SpecCreationChat.tsx
- FolderBrowser.tsx
- TerminalTabs.tsx
This follows up on PR #121 which added IME composition checks. The
refactoring centralizes the logic for easier maintenance and documents
the padding value that prevents Kanban cards from being cut off when
the debug panel is collapsed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add sticky positioning and glassmorphism effect to the top navigation:
- sticky top-0 z-50 for fixed positioning above content
- bg-card/80 for 80% opacity background
- backdrop-blur-md for frosted glass effect
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change CSS import from bare module specifier to url() syntax to fix
Vite/Tailwind CSS resolution issues on some systems.
- Changed `@import "tw-animate-css"` to `@import url("tw-animate-css")`
- The url() wrapper ensures proper package resolution across platforms
- Fixes "Can't resolve 'tw-animate-css'" build error
The bare import syntax failed because Vite's CSS processing didn't
properly resolve the package exports. Using url() bypasses this issue
while still correctly resolving the npm package from node_modules.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>