refactor: semantic analyzer cleanup -- shared filtering, concurrency, extraction#908
refactor: semantic analyzer cleanup -- shared filtering, concurrency, extraction#908
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
🧰 Additional context used📓 Path-based instructions (4)**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/synthorg/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/synthorg/engine/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (16)📓 Common learnings📚 Learning: 2026-03-28T18:10:43.543ZApplied to files:
📚 Learning: 2026-03-28T18:10:43.543ZApplied to files:
📚 Learning: 2026-03-19T07:12:14.508ZApplied to files:
📚 Learning: 2026-03-28T18:10:43.543ZApplied to files:
📚 Learning: 2026-03-20T21:44:04.528ZApplied to files:
📚 Learning: 2026-03-20T21:44:04.528ZApplied to files:
📚 Learning: 2026-03-15T21:49:53.264ZApplied to files:
📚 Learning: 2026-03-17T22:08:13.456ZApplied to files:
📚 Learning: 2026-03-28T18:10:43.543ZApplied to files:
📚 Learning: 2026-03-17T18:52:05.142ZApplied to files:
📚 Learning: 2026-03-20T21:44:04.528ZApplied to files:
📚 Learning: 2026-03-20T11:18:48.128ZApplied to files:
📚 Learning: 2026-03-16T19:13:34.746ZApplied to files:
📚 Learning: 2026-03-17T22:08:13.456ZApplied to files:
📚 Learning: 2026-03-28T18:10:43.543ZApplied to files:
🔇 Additional comments (21)
WalkthroughThe PR extracts git-backed semantic-analysis operations into a new module 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Code Review
This pull request refactors the semantic analysis pipeline by extracting git-related operations into a new semantic_git_ops module and updating the CompositeSemanticAnalyzer to execute analyzers concurrently using asyncio.TaskGroup. It introduces a git_concurrency configuration to cap concurrent git show subprocesses via an asyncio.Semaphore. The changes also include internal refactoring of the PlannerWorktreeStrategy for improved modularity and expanded unit tests covering the new concurrency logic and configuration bounds. I have no feedback to provide.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches. Re-running this action after a short time may resolve the issue. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/unit/engine/test_semantic_analyzer.py`:
- Around line 365-366: Replace the deprecated
asyncio.get_event_loop().create_task(...) call with asyncio.create_task(...)
when creating the task for composite.analyze; update the statement that assigns
to task (currently using get_event_loop().create_task around composite.analyze)
to use asyncio.create_task(composite.analyze(...)) and ensure asyncio is
imported in the test so the new call resolves.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e636cc44-42e9-4159-b0d0-09d6adfffc86
📒 Files selected for processing (8)
docs/design/engine.mdsrc/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_git_ops.pysrc/synthorg/engine/workspace/semantic_llm.pytests/unit/engine/test_semantic_analyzer.pytests/unit/engine/test_workspace_git_worktree.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Sandbox
- GitHub Check: Build Backend
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations-- Python 3.14+ has PEP 649 native lazy annotations. Useexcept A, B:(no parentheses) per PEP 758 except syntax as enforced by ruff.
All public functions and classes require type hints and Google-style docstrings (enforced by ruff D rules). Use mypy strict mode.
Functions must be less than 50 lines, files less than 800 lines. Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Files:
src/synthorg/engine/workspace/config.pytests/unit/engine/test_semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_llm.pytests/unit/engine/test_workspace_git_worktree.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Every module with business logic must have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__). Use event name constants fromsynthorg.observability.events.<domain>modules (e.g.,API_REQUEST_STARTED,TOOL_INVOKE_START). Always use structured kwargs:logger.info(EVENT, key=value). Log all error paths at WARNING or ERROR with context before raising, all state transitions at INFO, and DEBUG for object creation and key function flow. Pure data models, enums, and re-exports do not need logging.
Use immutability patterns: create new objects instead of mutating existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction plusMappingProxyTypewrapping for read-only enforcement. Fordict/listfields in frozen Pydantic models, usecopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization).
Use Pydantic v2 models (BaseModel,model_validator,computed_field,ConfigDict). Use@computed_fieldfor derived values instead of storing redundant fields (e.g.,TokenUsage.total_tokens). UseNotBlankStrfromcore.typesfor all identifier/name fields (including optionalNotBlankStr | Noneand tuple variants) instead of manual whitespace validators.
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations (e.g., multiple tool invocations, parallel agent calls) in new code instead of barecreate_task. Favor structured concurrency.
Separate frozen Pydantic models for config/identity from mutable-via-copy models for runtime state that evolves (e.g., agent execution state, task progress). Never mix static config fields with mutable runtime fields in one model.
Never useimport loggingorlogging.getLogger()in application code. Exception:observability/setup.pyandobservability/sinks.pymay use stdlibloggingandprint(..., file=sys.stderr)for bootst...
Files:
src/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Line length: 88 characters (ruff enforces).
Files:
src/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/synthorg/engine/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
Files:
src/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_git_ops.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Use pytest markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow. Maintain 80% minimum coverage. Useasyncio_mode = 'auto'(no manual@pytest.mark.asyncio). Set 30-second global timeout per test. Run tests with-n autofor parallelism via pytest-xdist; never run sequentially. Use Hypothesis for property-based testing with@givenand@settings,HYPOTHESIS_PROFILEenv var (ci=50 examples, dev=1000 examples). Never skip flaky tests -- fix them fundamentally by mockingtime.monotonic(),asyncio.sleep(), or usingasyncio.Event().wait()for blocking operations.
Use vendor-agnostic names in tests:test-provider,test-small-001,large/medium/smallaliases instead of real vendor names (Anthropic, OpenAI, Claude, GPT, etc.). Vendor names appear only in operations design page,.claude/files, third-party imports, and provider presets.
Files:
tests/unit/engine/test_semantic_analyzer.pytests/unit/engine/test_workspace_git_worktree.py
**/*.{md,mdx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always read the relevant
docs/design/page before implementing any feature or planning any issue. The design spec is the starting point for architecture, data models, and behavior. If implementation deviates from spec, alert the user and explain why -- user decides whether to proceed or update the spec. Never silently diverge. When approved deviations occur, update the relevantdocs/design/page to reflect the new reality.
Files:
docs/design/engine.md
docs/design/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Design spec pages are mandatory reading before implementing features. Design specs pages are the starting point for architecture, data models, and behavior. When implementation deviates from spec, alert the user with reasoning. Update the relevant design page when approved deviations occur.
Files:
docs/design/engine.md
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/engine/**/*.py : Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations (e.g., multiple tool invocations, parallel agent calls) in new code instead of bare `create_task`. Favor structured concurrency.
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to tests/**/*.py : Use pytest markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Maintain 80% minimum coverage. Use `asyncio_mode = 'auto'` (no manual `pytest.mark.asyncio`). Set 30-second global timeout per test. Run tests with `-n auto` for parallelism via pytest-xdist; never run sequentially. Use Hypothesis for property-based testing with `given` and `settings`, `HYPOTHESIS_PROFILE` env var (ci=50 examples, dev=1000 examples). Never skip flaky tests -- fix them fundamentally by mocking `time.monotonic()`, `asyncio.sleep()`, or using `asyncio.Event().wait()` for blocking operations.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to tests/**/*.py : Test markers: pytest.mark.unit, pytest.mark.integration, pytest.mark.e2e, pytest.mark.slow. Coverage: 80% minimum (enforced in CI).
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/engine/**/*.py : Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
Applied to files:
docs/design/engine.mdsrc/synthorg/engine/workspace/semantic_llm.pytests/unit/engine/test_workspace_git_worktree.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Applied to files:
tests/unit/engine/test_workspace_git_worktree.py
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
tests/unit/engine/test_workspace_git_worktree.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/tools/**/*.py : Implement git SSRF prevention and sandbox factory patterns. Use MCP bridge for tool integration. Track tool invocation.
Applied to files:
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
🔇 Additional comments (19)
src/synthorg/engine/workspace/config.py (1)
67-72: LGTM!The
git_concurrencyfield is well-defined with sensible bounds (1–50) and a reasonable default (10). The validation constraints will prevent excessive subprocess fan-out while allowing tuning for different environments.tests/unit/engine/test_semantic_analyzer.py (2)
62-97: LGTM!The
TestFilterFilestests comprehensively cover the shared filtering utility: empty input, single/multiple extension matching,max_filestruncation with order preservation, and the no-match case.
384-401: LGTM!Good validation tests for
git_concurrencybounds, verifying both the default value and that out-of-range values raiseValidationError.docs/design/engine.md (1)
950-954: LGTM!Documentation accurately reflects the new concurrent
asyncio.TaskGroupexecution model and failure-isolation semantics inCompositeSemanticAnalyzer.src/synthorg/engine/workspace/semantic_llm.py (2)
136-136: LGTM!Good consolidation—delegating to
filter_fileseliminates duplicate inline filtering logic.
202-262: LGTM!The
_attempt_onceextraction cleanly separates per-attempt logic from retry orchestration. The return-value contract (None= retry,()= terminal failure, conflicts = success) is clear, andCancelledErroris properly re-raised.tests/unit/engine/test_workspace_git_worktree.py (2)
27-32: LGTM!Import updates correctly reflect the extraction of git operations into
semantic_git_ops.py. The standalone functions are now imported directly for testing.
1036-1055: LGTM!The test correctly patches
run_semantic_analysisat the import location ingit_worktree.pyand verifies the delegation with all expected keyword arguments including the newrun_git,config,analyzer, andrepo_rootparameters.src/synthorg/engine/workspace/git_worktree.py (3)
243-256: LGTM!Clean extraction of workspace limit checking into
_check_workspace_limit. The method properly logs a warning and raisesWorkspaceLimitErrorwith a descriptive message.
258-304: LGTM!Good extraction of worktree/branch creation with proper cleanup semantics: if worktree creation fails, the already-created branch is deleted (lines 287-297). Cleanup failure is logged but doesn't suppress the original error.
686-702: LGTM!Clean delegation to
semantic_git_ops.run_semantic_analysiswith all required parameters. This keeps the worktree module focused on lifecycle management while the semantic analysis pipeline lives in its dedicated module.src/synthorg/engine/workspace/semantic_analyzer.py (3)
66-86: LGTM!Good refactor making
filter_filespublic with a comprehensive docstring. The function maintains input order and appliesmax_filestruncation as documented.
237-248: LGTM!Clean deduplication using
(file_path, description)as the key. This correctly handles the case where multiple analyzers detect the same conflict.
295-322: LGTM!The concurrent execution via
asyncio.TaskGroupis well-implemented:
- Per-analyzer exceptions are caught and logged without blocking other analyzers
CancelledErrorpropagates correctly (TaskGroup wraps it inBaseExceptionGroup, which isn't caught byexcept Exception)- Results are deduplicated after all tasks complete
- The comment at line 295-296 correctly notes that
list.extendis safe without locking in single-threaded asyncioBased on learnings: Prefer
asyncio.TaskGroupfor fan-out/fan-in parallel operations in new code.src/synthorg/engine/workspace/semantic_git_ops.py (5)
1-28: LGTM!Clean module setup with appropriate imports, type hints, and observability integration via
get_logger(__name__). TheGitRunnertype alias clearly documents the expected callback signature.
33-45: LGTM!Conservative path validation that correctly rejects:
- Empty strings and flag-like arguments (
-...)- Directory traversal (checks for
..as a path component, not substring)- Absolute paths
- Characters outside the allowlist
The regex
^[A-Za-z0-9_./ @\-]+$is appropriately restrictive for git path arguments.
120-170: LGTM!Well-structured parallel
git showimplementation:
- Semaphore bounds concurrency to prevent excessive subprocess fan-out
- TaskGroup provides structured concurrency with proper cleanup
- Per-file path validation inside
_fetchprovides defense in depth- Writes to
sourcesdict are safe (each task writes to a unique key)Based on learnings: Prefer
asyncio.TaskGroupfor fan-out/fan-in parallel operations.
173-220: LGTM!Clean orchestration with proper guards:
- Returns early if analyzer is
None,pre_merge_shais empty, orconfig.enabledis false- Logs
WORKSPACE_SEMANTIC_CONFLICTwhen conflicts are found- Delegates to
_do_analysisfor the actual pipeline
262-277: VerifyBaseExceptionGrouppropagation from nestedTaskGroup.The analyzer at line 262 may be a
CompositeSemanticAnalyzerthat usesasyncio.TaskGroupinternally. If one of its tasks is cancelled, the resultingBaseExceptionGroupwill propagate through theexcept Exceptionblock (sinceBaseExceptionGroupis aBaseException, not anException).This is the correct behavior—cancellation signals should propagate. Just confirming this is intentional and aligns with the test at
test_cancelled_error_propagatesthat expects eitherCancelledErrororExceptionGroup.#!/bin/bash # Verify that BaseExceptionGroup propagation is tested # Check the test file for ExceptionGroup handling rg -n "ExceptionGroup|BaseExceptionGroup" tests/unit/engine/test_semantic_analyzer.py
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #908 +/- ##
==========================================
+ Coverage 92.11% 92.16% +0.05%
==========================================
Files 595 596 +1
Lines 31404 31401 -3
Branches 3043 3040 -3
==========================================
+ Hits 28929 28942 +13
+ Misses 1955 1939 -16
Partials 520 520 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…alyzers (#859, #857) - Rename _filter_files to filter_files (public) in semantic_analyzer.py - Replace duplicate inline filtering in semantic_llm.py and git_worktree.py - Add git_concurrency config field with bounded semaphore in _get_base_sources - Parallelize CompositeSemanticAnalyzer with asyncio.TaskGroup - Add TestFilterFiles and TestSemanticAnalysisConfig unit tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cstrings, split long functions - Extract semantic git operations to semantic_git_ops.py (git_worktree.py 892->699 lines) - Split setup_workspace, _merge_under_lock, teardown_workspace, _call_with_retry into smaller helpers - Add Google-style docstrings to filter_files, SemanticAnalysisConfig.git_concurrency - Update CompositeSemanticAnalyzer docstring for concurrent TaskGroup execution - Fix concurrency test: use bare gate.wait() instead of wall-clock timeout - Add tests: CancelledError propagation, all-analyzers-fail, config validation - Update docs/design/engine.md: sequential->concurrent, git_concurrency in YAML example - Extract _deduplicate_conflicts helper from CompositeSemanticAnalyzer.analyze Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logging/error handling (7 items): - Log rev-parse failure in _checkout_and_capture_sha - Upgrade git show failure log from DEBUG to WARNING in get_base_sources - Log merge-base fallback in _resolve_branch_point (extracted helper) - Separate and log empty pre_merge_sha in run_semantic_analysis - Bind exception + include error details in _attempt_once handlers - Log dropped unsafe file paths in get_changed_files Dead code: - Remove unused SemanticAnalysisError from errors.py Timing fix: - Move start = time.monotonic() before _checkout_and_capture_sha to restore full merge cycle timing in duration_seconds Code quality: - Extract _resolve_branch_point to bring _do_analysis under 50 lines - Extract _handle_parse_error to bring _attempt_once under 50 lines - Rename misleading py_files variable to matched in filter_files - Reword "Safe without a lock" comment for precision - Add CancelledError/TaskGroup note to CompositeSemanticAnalyzer docstring - Update get_base_sources docstring re: omitted files Tests: - Replace deprecated asyncio.get_event_loop().create_task() - Parametrize _validate_file_path tests (8 cases incl. Windows path) - Add combined extension+max_files ordering test - Remove duplicate test_returns_empty_when_analyzer_is_none Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6e1e2d0 to
6a14fd4
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/synthorg/engine/workspace/semantic_analyzer.py (1)
297-325:⚠️ Potential issue | 🟡 MinorPreserve analyzer order when collecting conflicts.
Line 310 appends in task-completion order, so the returned tuple and the duplicate winner from
_deduplicate_conflicts()now vary with scheduler timing. That makessemantic_conflictsunstable across runs even when the analyzers return the same data.♻️ Proposed fix
- all_conflicts: list[MergeConflict] = [] + per_analyzer: list[tuple[MergeConflict, ...]] = [()] * len( + self._analyzers + ) - async def _run(analyzer: SemanticAnalyzer) -> None: + async def _run( + index: int, + analyzer: SemanticAnalyzer, + ) -> None: try: conflicts = await analyzer.analyze( workspace=workspace, changed_files=changed_files, repo_root=repo_root, base_sources=base_sources, ) - all_conflicts.extend(conflicts) + per_analyzer[index] = conflicts except Exception as exc: logger.warning( WORKSPACE_SEMANTIC_ANALYSIS_FAILED, workspace_id=workspace.workspace_id, analyzer=type(analyzer).__name__, @@ async with asyncio.TaskGroup() as tg: - for analyzer in self._analyzers: - tg.create_task(_run(analyzer)) + for index, analyzer in enumerate(self._analyzers): + tg.create_task(_run(index, analyzer)) - return _deduplicate_conflicts(all_conflicts) + return _deduplicate_conflicts( + [ + conflict + for conflicts in per_analyzer + for conflict in conflicts + ], + )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workspace/semantic_analyzer.py` around lines 297 - 325, The current implementation collects conflicts into all_conflicts in task completion order (inside _run), causing nondeterministic ordering; change to preserve self._analyzers order by allocating a results list (e.g., results: list[list[MergeConflict]] sized to len(self._analyzers)) and have _run accept an index (or capture i) and assign results[i] = conflicts (or append to results[i]); keep the same exception logging in _run; create tasks for each analyzer as before, await the TaskGroup, then after the TaskGroup completes iterate over results in analyzer order and extend all_conflicts (or build the final list) before calling _deduplicate_conflicts so ordering is stable and independent of scheduling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/synthorg/engine/workspace/git_worktree.py`:
- Around line 701-709: run_semantic_analysis is being passed repo_root and the
analyzers (AstSemanticAnalyzer, LlmSemanticAnalyzer) read the live worktree,
which can change after _merge_under_lock releases the merge lock; update the
flow so analysis uses a stable snapshot: either (A) snapshot merged source
contents under the lock and pass those in (e.g., a mapping of file path ->
content or a temporary locked directory) into _run_semantic_analysis /
run_semantic_analysis instead of repo_root, or (B) modify AstSemanticAnalyzer
and LlmSemanticAnalyzer to load files by merge_sha (using git object access like
git show) rather than reading from disk, and then call them with merge_sha;
ensure changes around merge_workspace/_merge_under_lock/_run_semantic_analysis
remove any dependency on the live checkout after the lock is released.
In `@src/synthorg/engine/workspace/semantic_git_ops.py`:
- Around line 163-177: The warning for a failed git show should be suppressed
when the failure is the expected "file not present at base_sha" case for newly
added files: inside the block that calls run_git("show", f"{base_sha}:{fp}",
...), only add sources[fp] on rc==0; if rc!=0, inspect stderr and if it contains
the git-not-found message (e.g. starts with or includes "fatal: Path" or "does
not exist in") then silently skip adding a warning (treat as new file),
otherwise log WORKSPACE_SEMANTIC_ANALYSIS_FAILED with operation="show",
base_sha=base_sha, file=fp, error=stderr; use the existing symbols run_git,
base_sha, fp, WORKSPACE_SEMANTIC_ANALYSIS_FAILED and sources to implement this
conditional behavior.
- Around line 298-310: The returned plain dict from get_base_sources (assigned
to base_sources) must be wrapped in an immutable Mapping before being passed
into analyzer.analyze to enforce the read-only contract at runtime; import and
use types.MappingProxyType to create a read-only view of base_sources (e.g.,
wrap base_sources with MappingProxyType) right after it's obtained and before
calling analyzer.analyze (this ensures CompositeSemanticAnalyzer and any
concurrent readers cannot mutate the mapping).
In `@src/synthorg/engine/workspace/semantic_llm.py`:
- Around line 218-244: Split the provider call and the parse step so only
parsing failures trigger retries: first await self._provider.complete(...) in a
try/except that re-raises asyncio.CancelledError and treats any other exception
as a provider error (log WORKSPACE_SEMANTIC_ANALYSIS_FAILED with provider_error
and return ()), then after a successful response call
parse_tool_call_response(response) in its own try/except and on ValueError call
self._handle_parse_error(workspace=workspace, attempt=attempt,
max_retries=max_retries, error=exc) so only parse errors are retried; reference
_provider.complete, parse_tool_call_response, and _handle_parse_error to locate
places to change.
In `@tests/unit/engine/test_semantic_analyzer.py`:
- Around line 387-388: The cancellation assertion should expect grouped
cancellations as BaseExceptionGroup instead of ExceptionGroup; update the
pytest.raises tuple used around awaiting task to (asyncio.CancelledError,
BaseExceptionGroup) so grouped cancellations are caught (refer to the existing
pytest.raises usage and the task variable in the test to locate the change).
---
Outside diff comments:
In `@src/synthorg/engine/workspace/semantic_analyzer.py`:
- Around line 297-325: The current implementation collects conflicts into
all_conflicts in task completion order (inside _run), causing nondeterministic
ordering; change to preserve self._analyzers order by allocating a results list
(e.g., results: list[list[MergeConflict]] sized to len(self._analyzers)) and
have _run accept an index (or capture i) and assign results[i] = conflicts (or
append to results[i]); keep the same exception logging in _run; create tasks for
each analyzer as before, await the TaskGroup, then after the TaskGroup completes
iterate over results in analyzer order and extend all_conflicts (or build the
final list) before calling _deduplicate_conflicts so ordering is stable and
independent of scheduling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b0b6db2d-a015-4877-a888-c4a0ff8bd69a
📒 Files selected for processing (9)
docs/design/engine.mdsrc/synthorg/engine/errors.pysrc/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_git_ops.pysrc/synthorg/engine/workspace/semantic_llm.pytests/unit/engine/test_semantic_analyzer.pytests/unit/engine/test_workspace_git_worktree.py
💤 Files with no reviewable changes (1)
- src/synthorg/engine/errors.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Web
- GitHub Check: Build Sandbox
- GitHub Check: Build Backend
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations-- Python 3.14+ has PEP 649 native lazy annotations. Useexcept A, B:(no parentheses) per PEP 758 except syntax as enforced by ruff.
All public functions and classes require type hints and Google-style docstrings (enforced by ruff D rules). Use mypy strict mode.
Functions must be less than 50 lines, files less than 800 lines. Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Files:
src/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_analyzer.pytests/unit/engine/test_workspace_git_worktree.pysrc/synthorg/engine/workspace/git_worktree.pytests/unit/engine/test_semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Every module with business logic must have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__). Use event name constants fromsynthorg.observability.events.<domain>modules (e.g.,API_REQUEST_STARTED,TOOL_INVOKE_START). Always use structured kwargs:logger.info(EVENT, key=value). Log all error paths at WARNING or ERROR with context before raising, all state transitions at INFO, and DEBUG for object creation and key function flow. Pure data models, enums, and re-exports do not need logging.
Use immutability patterns: create new objects instead of mutating existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction plusMappingProxyTypewrapping for read-only enforcement. Fordict/listfields in frozen Pydantic models, usecopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization).
Use Pydantic v2 models (BaseModel,model_validator,computed_field,ConfigDict). Use@computed_fieldfor derived values instead of storing redundant fields (e.g.,TokenUsage.total_tokens). UseNotBlankStrfromcore.typesfor all identifier/name fields (including optionalNotBlankStr | Noneand tuple variants) instead of manual whitespace validators.
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations (e.g., multiple tool invocations, parallel agent calls) in new code instead of barecreate_task. Favor structured concurrency.
Separate frozen Pydantic models for config/identity from mutable-via-copy models for runtime state that evolves (e.g., agent execution state, task progress). Never mix static config fields with mutable runtime fields in one model.
Never useimport loggingorlogging.getLogger()in application code. Exception:observability/setup.pyandobservability/sinks.pymay use stdlibloggingandprint(..., file=sys.stderr)for bootst...
Files:
src/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Line length: 88 characters (ruff enforces).
Files:
src/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/synthorg/engine/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
Files:
src/synthorg/engine/workspace/config.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
**/*.{md,mdx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always read the relevant
docs/design/page before implementing any feature or planning any issue. The design spec is the starting point for architecture, data models, and behavior. If implementation deviates from spec, alert the user and explain why -- user decides whether to proceed or update the spec. Never silently diverge. When approved deviations occur, update the relevantdocs/design/page to reflect the new reality.
Files:
docs/design/engine.md
docs/design/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Design spec pages are mandatory reading before implementing features. Design specs pages are the starting point for architecture, data models, and behavior. When implementation deviates from spec, alert the user with reasoning. Update the relevant design page when approved deviations occur.
Files:
docs/design/engine.md
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Use pytest markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow. Maintain 80% minimum coverage. Useasyncio_mode = 'auto'(no manual@pytest.mark.asyncio). Set 30-second global timeout per test. Run tests with-n autofor parallelism via pytest-xdist; never run sequentially. Use Hypothesis for property-based testing with@givenand@settings,HYPOTHESIS_PROFILEenv var (ci=50 examples, dev=1000 examples). Never skip flaky tests -- fix them fundamentally by mockingtime.monotonic(),asyncio.sleep(), or usingasyncio.Event().wait()for blocking operations.
Use vendor-agnostic names in tests:test-provider,test-small-001,large/medium/smallaliases instead of real vendor names (Anthropic, OpenAI, Claude, GPT, etc.). Vendor names appear only in operations design page,.claude/files, third-party imports, and provider presets.
Files:
tests/unit/engine/test_workspace_git_worktree.pytests/unit/engine/test_semantic_analyzer.py
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/engine/**/*.py : Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/engine/**/*.py : Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
Applied to files:
tests/unit/engine/test_workspace_git_worktree.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Applied to files:
tests/unit/engine/test_workspace_git_worktree.py
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
tests/unit/engine/test_workspace_git_worktree.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/tools/**/*.py : Implement git SSRF prevention and sandbox factory patterns. Use MCP bridge for tool integration. Track tool invocation.
Applied to files:
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations (e.g., multiple tool invocations, parallel agent calls) in new code instead of bare `create_task`. Favor structured concurrency.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-17T18:52:05.142Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T18:52:05.142Z
Learning: Applies to **/*.py : Async concurrency: prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare create_task.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to tests/**/*.py : Use pytest markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Maintain 80% minimum coverage. Use `asyncio_mode = 'auto'` (no manual `pytest.mark.asyncio`). Set 30-second global timeout per test. Run tests with `-n auto` for parallelism via pytest-xdist; never run sequentially. Use Hypothesis for property-based testing with `given` and `settings`, `HYPOTHESIS_PROFILE` env var (ci=50 examples, dev=1000 examples). Never skip flaky tests -- fix them fundamentally by mocking `time.monotonic()`, `asyncio.sleep()`, or using `asyncio.Event().wait()` for blocking operations.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to tests/**/*.py : Test markers: pytest.mark.unit, pytest.mark.integration, pytest.mark.e2e, pytest.mark.slow. Coverage: 80% minimum (enforced in CI).
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
…xyType
Addresses 6 CodeRabbit findings:
Race condition (git_worktree.py):
- Analyzers no longer read from the live worktree checkout; all file
content is fetched via git show {sha}:{path} from immutable git
objects, making semantic analysis safe outside the merge lock
- SemanticAnalyzer protocol: replace repo_root with merged_sources
- Remove _read_sources (semantic_analyzer.py) and _read_file_contents
(semantic_llm.py) -- both are dead code after the protocol change
- _do_analysis fetches base and merged sources concurrently via
_fetch_sources helper using TaskGroup
New-file warning suppression (semantic_git_ops.py):
- git show failures with "does not exist in" or "fatal: Path" in
stderr are logged at DEBUG (expected for newly added files)
MappingProxyType enforcement (semantic_git_ops.py):
- base_sources and merged_sources wrapped in MappingProxyType before
being passed to analyzers, enforcing read-only contract at runtime
Provider/parse split (semantic_llm.py):
- _attempt_once separates the provider.complete() call from
parse_tool_call_response() so only parse ValueError triggers
retries; provider errors are terminal
Deterministic ordering (semantic_analyzer.py):
- CompositeSemanticAnalyzer uses indexed result slots to preserve
analyzer registration order, making deduplication deterministic
BaseExceptionGroup (test_semantic_analyzer.py):
- Cancellation test expects BaseExceptionGroup (not ExceptionGroup)
since CancelledError is a BaseException on Python 3.14
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The test_arbitrary_text_no_unhandled_exception property test checks correctness (no unhandled exceptions), not performance. Cold-start overhead on the first example occasionally exceeds the 200ms default deadline, causing flaky FlakyFailure on Windows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/synthorg/engine/workspace/semantic_analyzer.py`:
- Around line 156-169: py_set is filtered from changed_files but only
merged_sources is restricted to py_set before calling _run_ast_checks, so extra
entries in base_sources are interpreted as deletions and cause false conflicts;
update the code to derive both maps from the same selected file list (i.e.,
produce a filtered_base = {k: v for k, v in base_sources.items() if k in py_set}
alongside relevant = {k: v for k, v in merged_sources.items() if k in py_set})
and pass that filtered_base and relevant into _run_ast_checks (retain existing
early returns using _log_complete when py_set or relevant is empty).
In `@src/synthorg/engine/workspace/semantic_git_ops.py`:
- Around line 356-380: The two concurrent tasks call get_base_sources() which
currently constructs its own Semaphore, allowing up to 2x the configured
concurrency; create a single shared asyncio.Semaphore(concurrency) before the
TaskGroup (e.g., sem = asyncio.Semaphore(concurrency)) and pass that same
semaphore into both calls to get_base_sources() from _get_base and _get_merged
so both batches honor the global git_concurrency cap (update the
get_base_sources() calls to accept the shared semaphore parameter).
- Around line 115-126: The code currently calls line.strip() which silently
normalizes legitimate git-reported paths (e.g., " foo.py"); instead, stop
trimming the line and use the raw value from stdout.splitlines() for validation
and appending: replace usages of stripped with the original line (keep the
empty-line check using the raw line), call _validate_file_path(line) and
safe.append(line) when valid, and pass line into the logger.warning file
argument when rejecting; if filenames with surrounding whitespace should be
invalid, enforce that in _validate_file_path() rather than normalizing here
(leave WORKSPACE_SEMANTIC_ANALYSIS_FAILED and logger.warning semantics
unchanged).
In `@src/synthorg/engine/workspace/semantic_llm.py`:
- Around line 134-143: filter_files()'s ordering is being lost because py_set is
built as a set and merged_contents is reconstructed from merged_sources.items(),
causing nondeterministic prompt order; change the logic to keep the ordered list
returned by filter_files (e.g., rename py_set to something like filtered_files =
filter_files(changed_files, self._config)) and then build merged_contents by
iterating that list and indexing into merged_sources for each filename (checking
existence and len(v.encode("utf-8")) <= self._config.max_file_bytes) so the
prompt respects the canonical, max_files-truncated order; update references to
py_set and max_bytes accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b2a39e9e-ac34-4166-a3be-a90ea25f349e
📒 Files selected for processing (9)
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_checks.pysrc/synthorg/engine/workspace/semantic_git_ops.pysrc/synthorg/engine/workspace/semantic_llm.pytests/unit/config/test_loader_properties.pytests/unit/engine/test_semantic_analyzer.pytests/unit/engine/test_semantic_llm.pytests/unit/engine/test_workspace_git_worktree.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Sandbox
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations-- Python 3.14+ has PEP 649 native lazy annotations. Useexcept A, B:(no parentheses) per PEP 758 except syntax as enforced by ruff.
All public functions and classes require type hints and Google-style docstrings (enforced by ruff D rules). Use mypy strict mode.
Functions must be less than 50 lines, files less than 800 lines. Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Files:
tests/unit/config/test_loader_properties.pytests/unit/engine/test_semantic_llm.pysrc/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_checks.pysrc/synthorg/engine/workspace/semantic_analyzer.pytests/unit/engine/test_semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_git_ops.pytests/unit/engine/test_workspace_git_worktree.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Use pytest markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow. Maintain 80% minimum coverage. Useasyncio_mode = 'auto'(no manual@pytest.mark.asyncio). Set 30-second global timeout per test. Run tests with-n autofor parallelism via pytest-xdist; never run sequentially. Use Hypothesis for property-based testing with@givenand@settings,HYPOTHESIS_PROFILEenv var (ci=50 examples, dev=1000 examples). Never skip flaky tests -- fix them fundamentally by mockingtime.monotonic(),asyncio.sleep(), or usingasyncio.Event().wait()for blocking operations.
Use vendor-agnostic names in tests:test-provider,test-small-001,large/medium/smallaliases instead of real vendor names (Anthropic, OpenAI, Claude, GPT, etc.). Vendor names appear only in operations design page,.claude/files, third-party imports, and provider presets.
Files:
tests/unit/config/test_loader_properties.pytests/unit/engine/test_semantic_llm.pytests/unit/engine/test_semantic_analyzer.pytests/unit/engine/test_workspace_git_worktree.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Every module with business logic must have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__). Use event name constants fromsynthorg.observability.events.<domain>modules (e.g.,API_REQUEST_STARTED,TOOL_INVOKE_START). Always use structured kwargs:logger.info(EVENT, key=value). Log all error paths at WARNING or ERROR with context before raising, all state transitions at INFO, and DEBUG for object creation and key function flow. Pure data models, enums, and re-exports do not need logging.
Use immutability patterns: create new objects instead of mutating existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction plusMappingProxyTypewrapping for read-only enforcement. Fordict/listfields in frozen Pydantic models, usecopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization).
Use Pydantic v2 models (BaseModel,model_validator,computed_field,ConfigDict). Use@computed_fieldfor derived values instead of storing redundant fields (e.g.,TokenUsage.total_tokens). UseNotBlankStrfromcore.typesfor all identifier/name fields (including optionalNotBlankStr | Noneand tuple variants) instead of manual whitespace validators.
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations (e.g., multiple tool invocations, parallel agent calls) in new code instead of barecreate_task. Favor structured concurrency.
Separate frozen Pydantic models for config/identity from mutable-via-copy models for runtime state that evolves (e.g., agent execution state, task progress). Never mix static config fields with mutable runtime fields in one model.
Never useimport loggingorlogging.getLogger()in application code. Exception:observability/setup.pyandobservability/sinks.pymay use stdlibloggingandprint(..., file=sys.stderr)for bootst...
Files:
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_checks.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Line length: 88 characters (ruff enforces).
Files:
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_checks.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_git_ops.py
src/synthorg/engine/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
Files:
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_checks.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_git_ops.py
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/engine/**/*.py : Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to tests/**/*.py : Use pytest markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Maintain 80% minimum coverage. Use `asyncio_mode = 'auto'` (no manual `pytest.mark.asyncio`). Set 30-second global timeout per test. Run tests with `-n auto` for parallelism via pytest-xdist; never run sequentially. Use Hypothesis for property-based testing with `given` and `settings`, `HYPOTHESIS_PROFILE` env var (ci=50 examples, dev=1000 examples). Never skip flaky tests -- fix them fundamentally by mocking `time.monotonic()`, `asyncio.sleep()`, or using `asyncio.Event().wait()` for blocking operations.
Applied to files:
tests/unit/config/test_loader_properties.pytests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_semantic_llm.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/engine/**/*.py : Implement checkpoint recovery, approval/review gates, stagnation detection, context budget management and compaction, hybrid loop execution, and workspace management using git worktree isolation and merge orchestration with semantic conflict detection.
Applied to files:
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_analyzer.pysrc/synthorg/engine/workspace/semantic_llm.pysrc/synthorg/engine/workspace/semantic_git_ops.pytests/unit/engine/test_workspace_git_worktree.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/tools/**/*.py : Implement git SSRF prevention and sandbox factory patterns. Use MCP bridge for tool integration. Track tool invocation.
Applied to files:
src/synthorg/engine/workspace/git_worktree.pysrc/synthorg/engine/workspace/semantic_git_ops.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations (e.g., multiple tool invocations, parallel agent calls) in new code instead of bare `create_task`. Favor structured concurrency.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-17T18:52:05.142Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T18:52:05.142Z
Learning: Applies to **/*.py : Async concurrency: prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare create_task.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.
Applied to files:
tests/unit/engine/test_semantic_analyzer.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to src/synthorg/**/*.py : Never implement retry logic in provider subclasses or calling code — it is handled automatically by `BaseCompletionProvider` with `RetryConfig` and `RateLimiterConfig` per-provider
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-20T11:18:48.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T11:18:48.128Z
Learning: Applies to src/synthorg/**/*.py : Retryable errors (`is_retryable=True`): `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately without retry.
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-16T19:13:34.746Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:13:34.746Z
Learning: Applies to src/synthorg/providers/**/*.py : Retryable errors (is_retryable=True): RateLimitError, ProviderTimeoutError, ProviderConnectionError, ProviderInternalError. Non-retryable errors raise immediately without retry. RetryExhaustedError signals that all retries failed — the engine layer catches this to trigger fallback chains.
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/providers/**/*.py : All provider calls go through `BaseCompletionProvider` which applies retry and rate limiting automatically. Never implement retry logic in driver subclasses or calling code. Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`. Retryable errors (`is_retryable=True`): `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately. `RetryExhaustedError` signals all retries failed -- engine layer catches this for fallback chains. Rate limiter respects `RateLimitError.retry_after` from providers.
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Applied to files:
src/synthorg/engine/workspace/semantic_llm.pytests/unit/engine/test_workspace_git_worktree.py
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to src/synthorg/**/*.py : All provider calls go through `BaseCompletionProvider` which applies retry + rate limiting automatically. Never implement retry logic in driver subclasses or calling code.
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : All provider calls go through `BaseCompletionProvider` which applies retry + rate limiting automatically. Never implement retry logic in driver subclasses or calling code — it's handled by the base class.
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to src/synthorg/**/*.py : `RetryConfig` and `RateLimiterConfig` are set per-provider in `ProviderConfig`. Retryable errors: `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately.
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-17T18:52:05.142Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T18:52:05.142Z
Learning: Applies to src/synthorg/providers/**/*.py : All provider calls go through BaseCompletionProvider which applies retry + rate limiting automatically. Never implement retry logic in driver subclasses or calling code — it's handled by the base class.
Applied to files:
src/synthorg/engine/workspace/semantic_llm.py
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
src/synthorg/engine/workspace/semantic_git_ops.pytests/unit/engine/test_workspace_git_worktree.py
📚 Learning: 2026-03-28T18:10:43.543Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T18:10:43.543Z
Learning: Applies to src/synthorg/**/*.py : Use immutability patterns: create new objects instead of mutating existing ones. For non-Pydantic internal collections (registries, `BaseTool`), use `copy.deepcopy()` at construction plus `MappingProxyType` wrapping for read-only enforcement. For `dict`/`list` fields in frozen Pydantic models, use `copy.deepcopy()` at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization).
Applied to files:
src/synthorg/engine/workspace/semantic_git_ops.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to src/synthorg/**/*.py : For non-Pydantic internal collections (registries, `BaseTool`), use `copy.deepcopy()` at construction and wrap with `MappingProxyType` for read-only enforcement
Applied to files:
src/synthorg/engine/workspace/semantic_git_ops.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to **/*.py : Immutability: create new objects, never mutate existing ones. For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement.
Applied to files:
src/synthorg/engine/workspace/semantic_git_ops.py
📚 Learning: 2026-03-15T19:14:27.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T19:14:27.144Z
Learning: Applies to src/synthorg/**/*.py : For dict/list fields in frozen Pydantic models, rely on frozen=True for field reassignment prevention and copy.deepcopy() at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence).
Applied to files:
src/synthorg/engine/workspace/semantic_git_ops.py
🔇 Additional comments (1)
tests/unit/config/test_loader_properties.py (1)
94-94:deadline=Noneis appropriate for this property-based parser robustness test.The
_yaml_textstrategy generates arbitrary input including edge cases, and YAML parser performance legitimately varies across different inputs. Hypothesis explicitly recommendsdeadline=Nonefor tests with variable performance characteristics like parser complexity variance. The coding guideline about mockingtime.monotonic()andasyncio.sleep()applies specifically to timing-sensitive or async tests, not to synchronous robustness tests where performance variance is inherent to the operation being tested.
- Filter base_sources to py_set in AstSemanticAnalyzer to prevent false "deleted" conflicts from unrelated files in base_sources - Share a single asyncio.Semaphore across base and merged source fetches in _fetch_sources so total concurrency honors the git_concurrency config (was 2x with independent semaphores) - Remove strip() normalization in get_changed_files to preserve legitimate filenames; _validate_file_path handles rejection - Build LLM merged_contents by iterating the ordered list from filter_files instead of dict comprehension over merged_sources, preserving canonical file order in prompts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 I have created a release *beep* *boop* --- #MAJOR CHANGES; We got a somewhat working webui :) ## [0.5.0](v0.4.9...v0.5.0) (2026-03-30) ### Features * add analytics trends and budget forecast API endpoints ([#798](#798)) ([16b61f5](16b61f5)) * add department policies to default templates ([#852](#852)) ([7a41548](7a41548)) * add remaining activity event types (task_started, tool_used, delegation, cost_incurred) ([#832](#832)) ([4252fac](4252fac)) * agent performance, activity, and history API endpoints ([#811](#811)) ([9b75c1d](9b75c1d)) * Agent Profiles and Detail pages (biography, career, performance) ([#874](#874)) ([62d7880](62d7880)) * app shell, Storybook, and CI/CD pipeline ([#819](#819)) ([d4dde90](d4dde90)) * Approvals page with risk grouping, urgency indicators, batch actions ([#889](#889)) ([4e9673d](4e9673d)) * Budget Panel page (P&L dashboard, breakdown charts, forecast) ([#890](#890)) ([b63b0f1](b63b0f1)) * build infrastructure layer (API client, auth, WebSocket) ([#815](#815)) ([9f01d3e](9f01d3e)) * CLI global options infrastructure, UI modes, exit codes, env vars ([#891](#891)) ([fef4fc5](fef4fc5)) * CodeMirror editor and theme preferences toggle ([#905](#905), [#807](#807)) ([#909](#909)) ([41fbedc](41fbedc)) * Company page (department/agent management) ([#888](#888)) ([cfb88b0](cfb88b0)) * comprehensive hint coverage across all CLI commands ([#900](#900)) ([937974e](937974e)) * config system extensions, per-command flags for init/start/stop/status/logs ([#895](#895)) ([32f83fe](32f83fe)) * configurable currency system replacing hardcoded USD ([#854](#854)) ([b372551](b372551)) * Dashboard page (metric cards, activity feed, budget burn) ([#861](#861)) ([7d519d5](7d519d5)) * department health, provider status, and activity feed endpoints ([#818](#818)) ([6d5f196](6d5f196)) * design tokens and core UI components ([#833](#833)) ([ed887f2](ed887f2)) * extend approval, meeting, and budget API responses ([#834](#834)) ([31472bf](31472bf)) * frontend polish -- real-time UX, accessibility, responsive, performance ([#790](#790), [#792](#792), [#791](#791), [#793](#793)) ([#917](#917)) ([f04a537](f04a537)) * implement human roles and access control levels ([#856](#856)) ([d6d8a06](d6d8a06)) * implement semantic conflict detection in workspace merge ([#860](#860)) ([d97283b](d97283b)) * interaction components and animation patterns ([#853](#853)) ([82d4b01](82d4b01)) * Login page + first-run bootstrap + Company page ([#789](#789), [#888](#888)) ([#896](#896)) ([8758e8d](8758e8d)) * Meetings page with timeline viz, token bars, contribution formatting ([#788](#788)) ([#904](#904)) ([b207f46](b207f46)) * Messages page with threading, channel badges, sender indicators ([#787](#787)) ([#903](#903)) ([28293ad](28293ad)) * Org Chart force-directed view and drag-drop reassignment ([#872](#872), [#873](#873)) ([#912](#912)) ([a68a938](a68a938)) * Org Chart page (living nodes, status, CRUD, department health) ([#870](#870)) ([0acbdae](0acbdae)) * per-command flags for remaining commands, auto-behavior wiring, help/discoverability ([#897](#897)) ([3f7afa2](3f7afa2)) * Providers page with backend rework -- health, CRUD, subscription auth ([#893](#893)) ([9f8dd98](9f8dd98)) * scaffold React + Vite + TypeScript + Tailwind project ([#799](#799)) ([bd151aa](bd151aa)) * Settings page with search, dependency indicators, grouped rendering ([#784](#784)) ([#902](#902)) ([a7b9870](a7b9870)) * Setup Wizard rebuild with template comparison, cost estimator, theme customization ([#879](#879)) ([ae8b50b](ae8b50b)) * setup wizard UX -- template filters, card metadata, provider form reuse ([#910](#910)) ([7f04676](7f04676)) * setup wizard UX overhaul -- mode choice, step reorder, provider fixes ([#907](#907)) ([ee964c4](ee964c4)) * structured ModelRequirement in template agent configs ([#795](#795)) ([7433548](7433548)) * Task Board page (rich Kanban, filtering, dependency viz) ([#871](#871)) ([04a19b0](04a19b0)) ### Bug Fixes * align frontend types with backend and debounce WS refetches ([#916](#916)) ([134c11b](134c11b)) * auto-cleanup targets newly pulled images instead of old ones ([#884](#884)) ([50e6591](50e6591)) * correct wipe backup-skip flow and harden error handling ([#808](#808)) ([c05860f](c05860f)) * improve provider setup in wizard, subscription auth, dashboard bugs ([#914](#914)) ([87bf8e6](87bf8e6)) * improve update channel detection and add config get command ([#814](#814)) ([6b137f0](6b137f0)) * resolve all ESLint warnings, add zero-warnings enforcement ([#899](#899)) ([079b46a](079b46a)) * subscription auth uses api_key, base URL optional for cloud providers ([#915](#915)) ([f0098dd](f0098dd)) ### Refactoring * semantic analyzer cleanup -- shared filtering, concurrency, extraction ([#908](#908)) ([81372bf](81372bf)) ### Documentation * brand identity and UX design system from [#765](#765) exploration ([#804](#804)) ([389a9f4](389a9f4)) * page structure and information architecture for v0.5.0 dashboard ([#809](#809)) ([f8d6d4a](f8d6d4a)) * write UX design guidelines with WCAG-verified color system ([#816](#816)) ([4a4594e](4a4594e)) ### Tests * add unit tests for agent hooks and page components ([#875](#875)) ([#901](#901)) ([1d81546](1d81546)) ### CI/CD * bump actions/deploy-pages from 4.0.5 to 5.0.0 in the major group ([#831](#831)) ([01c19de](01c19de)) * bump astral-sh/setup-uv from 7.6.0 to 8.0.0 in /.github/actions/setup-python-uv in the all group ([#920](#920)) ([5f6ba54](5f6ba54)) * bump codecov/codecov-action from 5.5.3 to 6.0.0 in the major group ([#868](#868)) ([f22a181](f22a181)) * bump github/codeql-action from 4.34.1 to 4.35.0 in the all group ([#883](#883)) ([87a4890](87a4890)) * bump sigstore/cosign-installer from 4.1.0 to 4.1.1 in the minor-and-patch group ([#830](#830)) ([7a69050](7a69050)) * bump the all group with 3 updates ([#923](#923)) ([ff27c8e](ff27c8e)) * bump wrangler from 4.76.0 to 4.77.0 in /.github in the minor-and-patch group ([#822](#822)) ([07d43eb](07d43eb)) * bump wrangler from 4.77.0 to 4.78.0 in /.github in the all group ([#882](#882)) ([f84118d](f84118d)) ### Maintenance * add design system enforcement hook and component inventory ([#846](#846)) ([15abc43](15abc43)) * add dev-only auth bypass for frontend testing ([#885](#885)) ([6cdcd8a](6cdcd8a)) * add pre-push rebase check hook ([#855](#855)) ([b637a04](b637a04)) * backend hardening -- eviction/size-caps and model validation ([#911](#911)) ([81253d9](81253d9)) * bump axios from 1.13.6 to 1.14.0 in /web in the all group across 1 directory ([#922](#922)) ([b1b0232](b1b0232)) * bump brace-expansion from 5.0.4 to 5.0.5 in /web ([#862](#862)) ([ba4a565](ba4a565)) * bump eslint-plugin-react-refresh from 0.4.26 to 0.5.2 in /web ([#801](#801)) ([7574bb5](7574bb5)) * bump faker from 40.11.0 to 40.11.1 in the minor-and-patch group ([#803](#803)) ([14d322e](14d322e)) * bump https://github.com/astral-sh/ruff-pre-commit from v0.15.7 to 0.15.8 ([#864](#864)) ([f52901e](f52901e)) * bump nginxinc/nginx-unprivileged from `6582a34` to `f99cc61` in /docker/web in the all group ([#919](#919)) ([df85e4f](df85e4f)) * bump nginxinc/nginx-unprivileged from `ccbac1a` to `6582a34` in /docker/web ([#800](#800)) ([f4e9450](f4e9450)) * bump node from `44bcbf4` to `71be405` in /docker/sandbox ([#827](#827)) ([91bec67](91bec67)) * bump node from `5209bca` to `cf38e1f` in /docker/web ([#863](#863)) ([66d6043](66d6043)) * bump picomatch in /site ([#842](#842)) ([5f20bcc](5f20bcc)) * bump recharts 2->3 and @types/node 22->25 in /web ([#802](#802)) ([a908800](a908800)) * Bump requests from 2.32.5 to 2.33.0 ([#843](#843)) ([41daf69](41daf69)) * bump smol-toml from 1.6.0 to 1.6.1 in /site ([#826](#826)) ([3e5dbe4](3e5dbe4)) * bump the all group with 3 updates ([#921](#921)) ([7bace0b](7bace0b)) * bump the minor-and-patch group across 1 directory with 2 updates ([#829](#829)) ([93e611f](93e611f)) * bump the minor-and-patch group across 1 directory with 3 updates ([#841](#841)) ([7010c8e](7010c8e)) * bump the minor-and-patch group across 1 directory with 3 updates ([#869](#869)) ([548cee5](548cee5)) * bump the minor-and-patch group in /site with 2 updates ([#865](#865)) ([9558101](9558101)) * bump the minor-and-patch group with 2 updates ([#867](#867)) ([4830706](4830706)) * consolidate Dependabot groups to 1 PR per ecosystem ([06d2556](06d2556)) * consolidate Dependabot groups to 1 PR per ecosystem ([#881](#881)) ([06d2556](06d2556)) * improve worktree skill with full dep sync and status enhancements ([#906](#906)) ([772c625](772c625)) * remove Vue remnants and document framework decision ([#851](#851)) ([bf2adf6](bf2adf6)) * update web dependencies and fix brace-expansion CVE ([#880](#880)) ([a7a0ed6](a7a0ed6)) * upgrade to Storybook 10 and TypeScript 6 ([#845](#845)) ([52d95f2](52d95f2)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
filter_files(refactor: extract shared file-filtering logic from semantic analyzers #859): Rename_filter_filesto publicfilter_filesinsemantic_analyzer.py, replace duplicate inline filtering insemantic_llm.pyandgit_worktree.pygit_concurrencyconfig field (default 10, bounds 1-50) withasyncio.Semaphorein_get_base_sources; replace sequential analyzer loop withasyncio.TaskGroupinCompositeSemanticAnalyzer_get_merge_base,_get_changed_files,_get_base_sources, and the analysis pipeline to newsemantic_git_ops.pymodule (git_worktree.py 892->699 lines)_create_worktree_and_branch,_check_workspace_limit,_checkout_and_capture_sha,_remove_worktree_and_branch,_attempt_once,_deduplicate_conflictshelpersdocs/design/engine.mdfor concurrent analyzer execution andgit_concurrencyconfig fieldCloses #859
Closes #858
Closes #857
Test plan
TestFilterFilestests (extension filtering, max_files, empty input, multiple extensions, no matches)TestSemanticAnalysisConfigtests (git_concurrency default and bounds)test_runs_analyzers_concurrently-- proves parallel execution via event gate (deadlocks if sequential)test_all_analyzers_fail_returns_empty-- verifies fault isolation with TaskGrouptest_cancelled_error_propagates-- verifies CancelledError not swallowedReview coverage
8 agents: docs-consistency, code-reviewer, python-reviewer, async-concurrency-reviewer, type-design-analyzer, pr-test-analyzer, conventions-enforcer, issue-resolution-verifier. 15 findings triaged and implemented.
🤖 Generated with Claude Code