The Claude CLI sends `rate_limit_event` messages that the SDK's
`parse_message()` doesn't recognize, raising `MessageParseError` and
crashing all three chat session types (spec, assistant, expand).
Changes:
- Bump claude-agent-sdk minimum from 0.1.0 to 0.1.39
- Add `check_rate_limit_error()` helper in chat_constants.py that
detects rate limits from both MessageParseError data payloads and
error message text patterns
- Wrap `receive_response()` loops in all three `_query_claude()` methods
with retry-on-rate-limit logic (up to 3 retries with backoff)
- Gracefully log and skip non-rate-limit MessageParseError instead of
crashing the session
- Add `rate_limited` message type to frontend TypeScript types and
handle it in useSpecChat, useAssistantChat, useExpandChat hooks to
show "Rate limited. Retrying in Xs..." system messages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Follow-up fixes after merging PR #183 (graceful pause/drain mode):
- process_manager: _stream_output finally block now transitions from
pausing/paused_graceful to crashed/stopped (not just running), and
cleans up the drain signal file on process exit
- App.tsx: block Reset button and R shortcut during pausing/paused_graceful
- AgentThought/ProgressDashboard: keep thought bubble visible while pausing
- OrchestratorAvatar: add draining/paused cases to animation, glow, and
description switch statements
- AgentMissionControl: show Draining/Paused badge text for new states
- registry.py: remove redundant type annotation to fix mypy no-redef
- process_manager.py: add type:ignore for SQLAlchemy Column assignment
- websocket.py: reclassify test-pass lines as 'testing' not 'success'
- review-pr.md: add post-review recommended action guidance
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major changes across 21 files (755 additions, 196 deletions):
Browser Automation Migration:
- Add versioned project migration system (prompts.py) with content-based
detection and section-level regex replacement for coding/testing prompts
- Migrate STEP 5 (browser verification) and BROWSER AUTOMATION sections
in coding prompt template to use playwright-cli commands
- Migrate STEP 2 and AVAILABLE TOOLS sections in testing prompt template
- Migration auto-runs at agent startup (autonomous_agent_demo.py), copies
playwright-cli skill, scaffolds .playwright/cli.config.json, updates
.gitignore, and stamps .migration_version file
- Add playwright-cli command validation to security allowlist (security.py)
with tests for allowed subcommands and blocked eval/run-code
Headless Browser Setting Fix:
- Add _apply_playwright_headless() to process_manager.py that reads/updates
.playwright/cli.config.json before agent subprocess launch
- Remove dead PLAYWRIGHT_HEADLESS env var that was never consumed
- Settings UI toggle now correctly controls visible browser window
Playwright CLI Auto-Install:
- Add ensurePlaywrightCli() to lib/cli.js for npm global entry point
- Add playwright-cli detection + npm install to start.bat, start.sh,
start_ui.bat, start_ui.sh for all startup paths
Other Improvements:
- Add project folder path tooltip to ProjectSelector.tsx dropdown items
- Remove legacy Playwright MCP server configuration from client.py
- Update CLAUDE.md with playwright-cli skill documentation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address three issues reported after overnight AutoForge runs:
1. ~193GB of .node files in %TEMP% from V8 compile caching
2. Stale npm artifact folders on drive root when %TEMP% fills up
3. PNG screenshot files left in project root by Playwright
Changes:
- Widen .node cleanup glob from ".78912*.node" to ".[0-9a-f]*.node"
to match all V8 compile cache hex prefixes
- Add "node-compile-cache" directory to temp cleanup patterns
- Set NODE_COMPILE_CACHE="" in all subprocess environments (client.py,
parallel_orchestrator.py, process_manager.py) to disable V8 compile
caching at the source
- Add cleanup_project_screenshots() to remove stale .png files from
project directories (feature*-*.png, screenshot-*.png, step-*.png)
- Run cleanup_stale_temp() at server startup in lifespan()
- Add _run_inter_session_cleanup() to orchestrator, called after each
agent completes (both coding and testing paths)
- Update coding and testing prompt templates to instruct agents to use
inline (base64) screenshots only, never saving files to disk
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agents can now request structured human input when they encounter
genuine blockers (API keys, design choices, external configs). The
request is displayed in the UI with a dynamic form, and the human's
response is stored and made available when the agent resumes.
Changes span 21 files + 1 new component:
- Database: 3 new columns (needs_human_input, human_input_request,
human_input_response) with migration
- MCP: new feature_request_human_input tool + guards on existing tools
- API: new resolve-human-input endpoint, 4th feature bucket
- Orchestrator: skip needs_human_input features in scheduling
- Progress: 4-tuple return from count_passing_tests
- WebSocket: needs_human_input count in progress messages
- UI: conditional 4th Kanban column, HumanInputForm component,
amber status indicators, dependency graph support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
File-based signal (.pause_drain) lets the orchestrator finish current
work before pausing instead of hard-freezing the process tree. New
status states pausing/paused_graceful flow through WebSocket to the UI
where a Pause button, draining indicator, and Resume button are shown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add interactive multiple-choice question support to the project assistant,
allowing it to present clickable options when clarification is needed.
Backend changes:
- Add ask_user MCP tool to feature_mcp.py with input validation
- Add mcp__features__ask_user to assistant allowed tools list
- Intercept ask_user tool calls in _query_claude() to yield question messages
- Add answer WebSocket message handler in assistant_chat router
- Document ask_user tool in assistant system prompt
Frontend changes:
- Add AssistantChatQuestionMessage type and update server message union
- Add currentQuestions state and sendAnswer() to useAssistantChat hook
- Handle question WebSocket messages by attaching to last assistant message
- Render QuestionOptions component between messages and input area
- Disable text input while structured questions are active
Flow: Claude calls ask_user → backend intercepts → WebSocket question message →
frontend renders QuestionOptions → user clicks options → answer sent back →
Claude receives formatted answer and continues conversation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When users configured GLM/Ollama/Kimi via the Settings UI, agents still
used Claude because conflicting env vars leaked through subprocess env.
Root cause: get_effective_sdk_env() set ANTHROPIC_AUTH_TOKEN for GLM but
didn't clear ANTHROPIC_API_KEY, which leaked from os.environ. The CLI
prioritized the wrong credential.
Changes:
- registry.py: Clear conflicting auth vars (API_KEY vs AUTH_TOKEN) and
Vertex AI vars when building env for alternative providers
- client.py: Replace manual os.getenv() loop with get_effective_sdk_env()
so agent SDK reads provider settings from the database
- autonomous_agent_demo.py: Apply UI-configured provider settings to
process env so CLI-launched agents also respect Settings UI config
- start.py: Pass --model from settings when launching agent subprocess
- server/schemas.py: Allow non-Claude model names when an alternative
provider is configured (prevents 422 errors for glm-4.7, etc.)
- .env.example: Document env vars for GLM, Ollama, and Kimi providers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove legacy env-var-based provider/mode detection that caused misleading
UI badges (e.g., GLM badge showing when Settings was set to Claude).
Key changes:
- Remove _is_glm_mode() and _is_ollama_mode() env-var sniffing functions
from server/routers/settings.py; derive glm_mode/ollama_mode purely from
the api_provider setting
- Remove `import os` from settings router (no longer needed)
- Update schema comments to reflect settings-based derivation
- Remove "(configured via .env)" from badge tooltips in App.tsx
- Remove Kimi/GLM/Ollama/Playwright-headless sections from .env.example;
add note pointing to Settings UI
- Update CLAUDE.md and README.md documentation to reference Settings UI
for alternative provider configuration
- Update model IDs from claude-opus-4-5-20251101 to claude-opus-4-6
across registry, client, chat sessions, tests, and UI defaults
- Add LEGACY_MODEL_MAP with auto-migration in get_all_settings()
- Show model ID subtitle in SettingsModal model selector
- Add Vertex passthrough test for claude-opus-4-6 (no date suffix)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix model selection regression: _get_settings_defaults() now checks
api_model (set by new provider UI) before falling back to legacy
model setting, ensuring Claude model selection works end-to-end
- Add input validation for provider settings: api_base_url must start
with http:// or https:// (max 500 chars), api_auth_token max 500
chars, api_model max 200 chars
- Fix terminal.py misleading import alias: replace
is_valid_project_name aliased as validate_project_name with direct
is_valid_project_name import across all 5 call sites
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
assistant_chat.py and spec_creation.py imported is_valid_project_name
(returns bool) aliased as validate_project_name. When used as
`project_name = validate_project_name(project_name)`, the project name
was replaced with True, causing "Project not found in registry" errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensures features stuck from a previous crash are reset before
launching a new agent, not just on stop/crash going forward.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The provider refactor moved env building to get_effective_sdk_env(),
making these imports unused. Fixes ruff F401 lint errors in CI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
API Provider Selection:
- Add provider switcher in Settings modal (Claude, Kimi, GLM, Ollama, Custom)
- Auth tokens stored locally only (registry.db), never returned by API
- get_effective_sdk_env() builds provider-specific env vars for agent subprocess
- All chat sessions (spec, expand, assistant) use provider settings
- Backward compatible: defaults to Claude, env vars still work as override
Fix Stuck Features:
- Add _cleanup_stale_features() to process_manager.py
- Reset in_progress features when agent stops, crashes, or fails healthcheck
- Prevents features from being permanently stuck after rate limit crashes
- Uses separate SQLAlchemy engine to avoid session conflicts with subprocess
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All WebSocket endpoints now call websocket.accept() before any
validation checks. Previously, closing the connection before accepting
caused Starlette to return an opaque HTTP 403 instead of a meaningful
error message.
Changes:
- Server: Accept WebSocket first, then send JSON error + close with
4xxx code if validation fails (expand, spec, assistant, terminal,
main project WS)
- Server: ConnectionManager.connect() no longer calls accept() to
avoid double-accept
- UI: Gate expand button and keyboard shortcut on hasSpec
- UI: Skip WebSocket reconnection on application error codes (4000-4999)
- UI: Update keyboard shortcuts help text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 5 WebSocket endpoints (expand, spec, assistant, terminal, project)
were closing the connection before calling accept() when validation
failed. Starlette converts pre-accept close into an HTTP 403, giving
clients no meaningful error information.
Server changes:
- Move websocket.accept() before all validation checks in every WS handler
- Send JSON error message before closing so clients get actionable errors
- Fix validate_project_name usage (raises HTTPException, not returns bool)
- ConnectionManager.connect() no longer calls accept() (caller's job)
Client changes:
- All 3 WS hooks (useWebSocket, useExpandChat, useSpecChat) skip
reconnection on 4xxx close codes (application errors won't self-resolve)
- Gate expand button, keyboard shortcut, and modal on hasSpec
- Add hasSpec to useEffect dependency array to prevent stale closure
- Update keyboard shortcuts help text for E key context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address security gaps and improve validation in the dev server command
execution path introduced by PR #153:
Security fixes (critical):
- Add missing shell metacharacters to dangerous_ops blocklist: single &
(Windows cmd.exe command separator), >, <, ^, %, \n, \r
- The single & gap was a confirmed RCE bypass on Windows where .cmd
files are always executed via cmd.exe even with shell=False (CPython
limitation documented in issue #77696)
- Apply validate_custom_command_strict at /start endpoint for
defense-in-depth against config file tampering
Validation improvements:
- Fix uvicorn --flag=value syntax (split on = before comparing)
- Expand Python support: Django (manage.py), Flask, custom .py scripts
- Add runners: flask, poetry, cargo, go, npx
- Expand npm script allowlist: serve, develop, server, preview
- Reorder PATCH /config validation to run strict check first (fail fast)
- Extract constants: ALLOWED_NPM_SCRIPTS, ALLOWED_PYTHON_MODULES,
BLOCKED_SHELLS for reuse and testability
Cleanup:
- Remove unused security.py imports from dev_server_manager.py
- Fix deprecated datetime.utcnow() -> datetime.now(timezone.utc)
- Remove unnecessary _remove_lock() in exception handlers where lock
was never created (Popen failure path)
Tests:
- Add test_devserver_security.py with 78 tests covering valid commands,
blocked shells, blocked commands, injection attempts, dangerous_ops
blocking, and constant verification
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete project rebrand from AutoCoder to AutoForge, touching 62 files
across Python backend, FastAPI server, React UI, documentation, config,
and CI/CD.
Key changes:
- Rename autocoder_paths.py -> autoforge_paths.py with backward-compat
migration from .autocoder/ -> .autoforge/ directories
- Update registry.py to migrate ~/.autocoder/ -> ~/.autoforge/ global
config directory with fallback support
- Update security.py with fallback reads from legacy .autocoder/ paths
- Rename .claude/commands and skills from gsd-to-autocoder-spec to
gsd-to-autoforge-spec
- Update all Python modules: client, prompts, progress, agent,
orchestrator, server routers and services
- Update React UI: package.json name, index.html title, localStorage
keys, all documentation sections, component references
- Update start scripts (bat/sh/py), examples, and .env.example
- Update CLAUDE.md and README.md with new branding and paths
- Update test files for new .autoforge/ directory structure
- Transfer git remote from leonvanzyl/autocoder to
AutoForgeAI/autoforge
Backward compatibility preserved: legacy .autocoder/ directories are
auto-detected and migrated on next agent start. Config fallback chain
checks both new and old paths.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
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>
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>
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>
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>
Replace direct-DB feature creation with MCP tool path. The expand
session now configures the feature MCP server and allows
feature_create_bulk tool calls, matching how AssistantChatSession
already works. Removes duplicated _create_features_bulk() method
and <features_to_create> regex parsing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address CodeRabbit feedback - use consistent conditional pattern:
`(max_priority.priority + 1) if max_priority else 1`
This matches the pattern used in create_feature and create_features_bulk.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Users can now access the WebUI remotely (e.g., via VS Code tunnels,
remote servers) by specifying a host address:
python start_ui.py --host 0.0.0.0
python start_ui.py --host 0.0.0.0 --port 8888
Changes:
- Added --host and --port CLI arguments to start_ui.py
- Security warning displayed when remote access is enabled
- AUTOCODER_ALLOW_REMOTE env var passed to server
- server/main.py conditionally disables localhost middleware
- CORS updated to allow all origins when remote access is enabled
- Browser auto-open disabled for remote hosts
Security considerations documented in warning:
- File system access to project directories
- API can start/stop agents and modify files
- Recommend firewall or VPN for protection
Fixes: leonvanzyl/autocoder#81
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When running multiple projects simultaneously, UI would show mixed data
because the manager registry used only project_name as key. Projects with
the same name but different paths shared the same manager instance.
Changed manager registries to use composite key (project_name, resolved_path):
- server/services/process_manager.py: AgentProcessManager registry
- server/services/dev_server_manager.py: DevServerProcessManager registry
This ensures that:
- /old/my-app and /new/my-app get separate managers
- Multiple browser tabs viewing different projects stay isolated
- Project renames don't cause callback contamination
Fixes: leonvanzyl/autocoder#71
Also fixes: leonvanzyl/autocoder#62 (progress bar sync)
Also fixes: leonvanzyl/autocoder#61 (features missing in kanban)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The REST API skip endpoint was using max_priority + 1000, while the
MCP server used max_priority + 1. This caused priority inflation where
values could reach 10,000+ after multiple skips.
Changed to use + 1 for consistency with mcp_server/feature_mcp.py:345.
Fixes: leonvanzyl/autocoder#65
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem:
Several API endpoints return 500 Internal Server Error because datetime
objects are not serializable by Pydantic. The error occurs when:
- GET /agent/{project}/status
- GET /devserver/{project}/status
- GET /schedules/{project}/next
Root cause:
Pydantic models expect strings for Optional datetime fields, but the code
was passing raw datetime objects.
Solution:
Convert datetime objects to ISO 8601 strings using .isoformat() before
returning in Pydantic response models.
Changes:
- server/routers/agent.py: Fix started_at serialization
- server/routers/devserver.py: Fix started_at serialization
- server/routers/schedules.py: Fix next_start/next_end serialization
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolved conflicts by combining:
- stdin=DEVNULL and CREATE_NO_WINDOW (blocking fix)
- PYTHONUNBUFFERED env var (output buffering fix)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add stdin=subprocess.DEVNULL to prevent blocking on stdin reads
- Add CREATE_NO_WINDOW flag on Windows to prevent console pop-ups
- Remove trailing pause from start_ui.bat
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove the testing_in_progress claim/release mechanism from the testing
agent architecture. Multiple testing agents can now test the same feature
concurrently, simplifying the system and eliminating potential stale lock
issues.
Changes:
- parallel_orchestrator.py:
- Remove claim_feature_for_testing() and release_testing_claim() methods
- Remove _cleanup_stale_testing_locks() periodic cleanup
- Replace with simple _get_random_passing_feature() selection
- Remove startup stale lock cleanup code
- Remove STALE_TESTING_LOCK_MINUTES constant
- Remove unused imports (timedelta, text)
- api/database.py:
- Remove testing_in_progress and last_tested_at columns from Feature model
- Update to_dict() to exclude these fields
- Convert _migrate_add_testing_columns() to no-op for backwards compat
- mcp_server/feature_mcp.py:
- Remove feature_release_testing tool entirely
- Remove unused datetime import
- prompts.py:
- Update testing prompt to remove feature_release_testing instruction
- Testing agents now just verify and exit (no cleanup needed)
- server/websocket.py:
- Update AgentTracker to use composite keys (feature_id, agent_type)
- Prevents ghost agent creation from ambiguous [Feature #X] messages
- Proper separation of coding vs testing agent tracking
Benefits:
- Eliminates artificial bottleneck from claim coordination
- No stale locks to clean up after crashes
- Simpler crash recovery (no testing state to restore)
- Reduced database writes (no claim/release transactions)
- Matches intended design: random, concurrent regression testing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>