Skip to content

refactor: semantic analyzer cleanup -- shared filtering, concurrency, extraction#908

Merged
Aureliolo merged 6 commits intomainfrom
refactor/semantic-analyzers
Mar 28, 2026
Merged

refactor: semantic analyzer cleanup -- shared filtering, concurrency, extraction#908
Aureliolo merged 6 commits intomainfrom
refactor/semantic-analyzers

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Extract shared filter_files (refactor: extract shared file-filtering logic from semantic analyzers #859): Rename _filter_files to public filter_files in semantic_analyzer.py, replace duplicate inline filtering in semantic_llm.py and git_worktree.py
  • Bounded semaphore + parallel CompositeSemanticAnalyzer (perf: parallelize _get_base_sources git show calls with TaskGroup #857): Add git_concurrency config field (default 10, bounds 1-50) with asyncio.Semaphore in _get_base_sources; replace sequential analyzer loop with asyncio.TaskGroup in CompositeSemanticAnalyzer
  • Extract semantic git ops (review finding): Move _get_merge_base, _get_changed_files, _get_base_sources, and the analysis pipeline to new semantic_git_ops.py module (git_worktree.py 892->699 lines)
  • Split long functions (review finding): Extract _create_worktree_and_branch, _check_workspace_limit, _checkout_and_capture_sha, _remove_worktree_and_branch, _attempt_once, _deduplicate_conflicts helpers
  • Docs: Update docs/design/engine.md for concurrent analyzer execution and git_concurrency config field

Closes #859
Closes #858
Closes #857

Test plan

  • 5 new TestFilterFiles tests (extension filtering, max_files, empty input, multiple extensions, no matches)
  • 2 new TestSemanticAnalysisConfig tests (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 TaskGroup
  • test_cancelled_error_propagates -- verifies CancelledError not swallowed
  • All 10945 tests pass, 0 failures
  • Pre-reviewed by 8 agents, 15 findings addressed

Review 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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fa44b84a-3457-4965-9164-8db9202396b5

📥 Commits

Reviewing files that changed from the base of the PR and between cba8543 and fa0d40d.

📒 Files selected for processing (3)
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.py
📜 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)
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Build Backend
  • GitHub Check: Build Web
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: No from __future__ import annotations -- Python 3.14+ has PEP 649 native lazy annotations. Use except 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/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Every module with business logic must have: from synthorg.observability import get_logger then logger = get_logger(__name__). Use event name constants from synthorg.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), 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).
Use Pydantic v2 models (BaseModel, model_validator, computed_field, ConfigDict). Use @computed_field for derived values instead of storing redundant fields (e.g., TokenUsage.total_tokens). Use NotBlankStr from core.types for all identifier/name fields (including optional NotBlankStr | None and tuple variants) instead of manual whitespace validators.
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.
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 use import logging or logging.getLogger() in application code. Exception: observability/setup.py and observability/sinks.py may use stdlib logging and print(..., file=sys.stderr) for bootst...

Files:

  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.py
src/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Line length: 88 characters (ruff enforces).

Files:

  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.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/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.py
🧠 Learnings (16)
📓 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:

  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • 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/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/semantic_git_ops.py
  • 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.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-15T21:49:53.264Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:49:53.264Z
Learning: Fix everything valid — never skip when review agents find valid issues (including pre-existing issues in surrounding code, suggestions, and findings adjacent to the PR's changes). No deferring, no 'out of scope' skipping.

Applied to files:

  • src/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 : 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:

  • src/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:

  • src/synthorg/engine/workspace/semantic_git_ops.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:

  • 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 : 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-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.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
🔇 Additional comments (21)
src/synthorg/engine/workspace/semantic_llm.py (6)

1-76: LGTM!

Imports, class definition, and initialization are well-structured. The filter_files import from semantic_analyzer supports the shared filtering objective, and the Mapping type is correctly placed in the TYPE_CHECKING block.


77-120: LGTM!

The analyze method correctly accepts merged_sources: Mapping[str, str] per the updated protocol, and the logging follows structured kwargs conventions.


134-143: Order preservation from filter_files() is correctly implemented.

The code now iterates the ordered list returned by filter_files() and indexes into merged_sources, preserving the canonical order for deterministic prompt construction. This addresses the previous review feedback.


215-252: Provider and parse errors are now correctly separated.

The provider call (lines 215-233) and parse step (lines 235-243) are in separate try blocks. Provider exceptions return () (terminal failure, no retry), while parse failures trigger _handle_parse_error which returns None to signal a retry. This addresses the previous review feedback about not retrying provider errors as parse failures.


254-284: LGTM!

The _handle_parse_error method correctly implements retry signaling with appropriate log levels: DEBUG for retryable attempts and WARNING on exhaustion.


287-299: LGTM!

The _build_diff_summary function is a clean helper for generating change-type summaries.

src/synthorg/engine/workspace/semantic_analyzer.py (6)

34-63: LGTM!

The SemanticAnalyzer protocol correctly specifies merged_sources: Mapping[str, str], establishing the read-only contract for all implementations.


66-86: LGTM!

The public filter_files function is well-documented and correctly preserves input order while applying extension filtering and max_files truncation. This consolidates the shared filtering logic per PR objective #859.


89-116: LGTM!

The _run_ast_checks function correctly accepts Mapping[str, str] parameters and aggregates conflicts from all AST checks.


156-170: Both base_sources and merged_sources are now filtered by the same file set.

The code correctly derives filtered_base and relevant from the same py_set, preventing false "deleted file" conflicts from unfiltered base_sources entries. This addresses the previous review feedback.


203-214: LGTM!

The _deduplicate_conflicts function correctly deduplicates by (file_path, description) with O(1) lookup.


266-294: LGTM!

The concurrent analyzer execution using asyncio.TaskGroup correctly:

  • Pre-allocates slots to preserve registration order for deterministic deduplication
  • Catches Exception per-analyzer (allowing CancelledError to propagate via the TaskGroup)
  • Logs failures without aborting sibling analyzers

This aligns with the coding guideline to prefer asyncio.TaskGroup for fan-out/fan-in parallel operations.

src/synthorg/engine/workspace/semantic_git_ops.py (9)

34-46: LGTM!

The _validate_file_path function provides robust path sanitization. While it explicitly checks for Unix absolute paths (/), Windows absolute paths (e.g., C:\...) are implicitly rejected by the regex which doesn't allow : or \ characters.


49-79: LGTM!

The get_merge_base function correctly handles failures by logging at WARNING level and returning an empty string for fallback handling upstream.


114-127: Raw paths are now validated without normalization.

The code correctly uses line directly from stdout.splitlines() without calling .strip(), preserving legitimate filenames with leading/trailing spaces. This addresses the previous review feedback.


172-190: New file detection correctly logs at DEBUG instead of WARNING.

The code now distinguishes between expected missing files (new at base_sha) and unexpected errors. Lines 174-182 check for "does not exist in" or "fatal: Path" in stderr and log at DEBUG level. This addresses the previous review feedback.


198-254: LGTM!

The run_semantic_analysis function provides a clean entry point with proper gating checks and logging for disabled/misconfigured states.


257-280: LGTM!

The _resolve_branch_point helper correctly implements fallback logic with appropriate warning logging.


316-320: Both base_sources and merged_sources are correctly wrapped in MappingProxyType.

This enforces the read-only contract at runtime, preventing accidental mutation by concurrent analyzers. This addresses the previous review feedback. As per coding guidelines, "use MappingProxyType wrapping for read-only enforcement."


334-348: LGTM!

The _gather_filtered_files helper correctly chains get_changed_files and filter_files.


359-383: Single semaphore correctly shared across both source-fetch batches.

Line 359 creates a single asyncio.Semaphore(config.git_concurrency) which is passed to both get_base_sources calls via the semaphore=sem parameter. This ensures total concurrent git show calls honor the configured git_concurrency limit. This addresses the previous review feedback.


Walkthrough

The PR extracts git-backed semantic-analysis operations into a new module semantic_git_ops, adds a git_concurrency integer field to SemanticAnalysisConfig, and promotes file-selection logic to a public filter_files utility. Semantic analyzer signatures and implementations now accept merged_sources: Mapping[str, str] (removing repo-root file reads). The composite analyzer runs configured analyzers concurrently via asyncio.TaskGroup, deduplicates results, and logs per-analyzer failures without aborting. Workspace worktree setup/teardown was refactored into helpers and the SemanticAnalysisError class was removed.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main refactoring effort: extracting shared filtering logic, implementing concurrency improvements, and reorganizing semantic analysis code into separate modules.
Description check ✅ Passed The description comprehensively outlines the key changes, test coverage, and linked issues, directly relating to the actual code modifications in the changeset.
Linked Issues check ✅ Passed All three linked issues (#859, #858, #857) are addressed: shared filter_files exported and used [#859], base_sources changed to Mapping[str, str] [#858], and git_concurrency with TaskGroup concurrency implemented [#857].
Out of Scope Changes check ✅ Passed All changes align with the stated objectives: filter extraction, Mapping type updates, concurrency refactoring, git ops extraction, and helper function splitting. One minor unrelated change (Hypothesis deadline in test_loader_properties.py) is negligible.
Docstring Coverage ✅ Passed Docstring coverage is 65.56% which is sufficient. The required threshold is 40.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 28, 2026 19:38 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 28, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA fa0d40d.
Ensure 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 Files

None

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between a7b9870 and 6e1e2d0.

📒 Files selected for processing (8)
  • docs/design/engine.md
  • src/synthorg/engine/workspace/config.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • tests/unit/engine/test_semantic_analyzer.py
  • tests/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: No from __future__ import annotations -- Python 3.14+ has PEP 649 native lazy annotations. Use except 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.py
  • tests/unit/engine/test_semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • tests/unit/engine/test_workspace_git_worktree.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/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_logger then logger = get_logger(__name__). Use event name constants from synthorg.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), 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).
Use Pydantic v2 models (BaseModel, model_validator, computed_field, ConfigDict). Use @computed_field for derived values instead of storing redundant fields (e.g., TokenUsage.total_tokens). Use NotBlankStr from core.types for all identifier/name fields (including optional NotBlankStr | None and tuple variants) instead of manual whitespace validators.
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.
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 use import logging or logging.getLogger() in application code. Exception: observability/setup.py and observability/sinks.py may use stdlib logging and print(..., file=sys.stderr) for bootst...

Files:

  • src/synthorg/engine/workspace/config.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/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.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/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.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/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. 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.
Use vendor-agnostic names in tests: test-provider, test-small-001, large/medium/small aliases 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.py
  • tests/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 relevant docs/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.md
  • src/synthorg/engine/workspace/semantic_llm.py
  • tests/unit/engine/test_workspace_git_worktree.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/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.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
🔇 Additional comments (19)
src/synthorg/engine/workspace/config.py (1)

67-72: LGTM!

The git_concurrency field 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 TestFilterFiles tests comprehensively cover the shared filtering utility: empty input, single/multiple extension matching, max_files truncation with order preservation, and the no-match case.


384-401: LGTM!

Good validation tests for git_concurrency bounds, verifying both the default value and that out-of-range values raise ValidationError.

docs/design/engine.md (1)

950-954: LGTM!

Documentation accurately reflects the new concurrent asyncio.TaskGroup execution model and failure-isolation semantics in CompositeSemanticAnalyzer.

src/synthorg/engine/workspace/semantic_llm.py (2)

136-136: LGTM!

Good consolidation—delegating to filter_files eliminates duplicate inline filtering logic.


202-262: LGTM!

The _attempt_once extraction cleanly separates per-attempt logic from retry orchestration. The return-value contract (None = retry, () = terminal failure, conflicts = success) is clear, and CancelledError is 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_analysis at the import location in git_worktree.py and verifies the delegation with all expected keyword arguments including the new run_git, config, analyzer, and repo_root parameters.

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 raises WorkspaceLimitError with 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_analysis with 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_files public with a comprehensive docstring. The function maintains input order and applies max_files truncation 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.TaskGroup is well-implemented:

  • Per-analyzer exceptions are caught and logged without blocking other analyzers
  • CancelledError propagates correctly (TaskGroup wraps it in BaseExceptionGroup, which isn't caught by except Exception)
  • Results are deduplicated after all tasks complete
  • The comment at line 295-296 correctly notes that list.extend is safe without locking in single-threaded asyncio

Based on learnings: Prefer asyncio.TaskGroup for 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__). The GitRunner type 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 show implementation:

  • Semaphore bounds concurrency to prevent excessive subprocess fan-out
  • TaskGroup provides structured concurrency with proper cleanup
  • Per-file path validation inside _fetch provides defense in depth
  • Writes to sources dict are safe (each task writes to a unique key)

Based on learnings: Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations.


173-220: LGTM!

Clean orchestration with proper guards:

  • Returns early if analyzer is None, pre_merge_sha is empty, or config.enabled is false
  • Logs WORKSPACE_SEMANTIC_CONFLICT when conflicts are found
  • Delegates to _do_analysis for the actual pipeline

262-277: Verify BaseExceptionGroup propagation from nested TaskGroup.

The analyzer at line 262 may be a CompositeSemanticAnalyzer that uses asyncio.TaskGroup internally. If one of its tasks is cancelled, the resulting BaseExceptionGroup will propagate through the except Exception block (since BaseExceptionGroup is a BaseException, not an Exception).

This is the correct behavior—cancellation signals should propagate. Just confirming this is intentional and aligns with the test at test_cancelled_error_propagates that expects either CancelledError or ExceptionGroup.

#!/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
Copy link
Copy Markdown

codecov bot commented Mar 28, 2026

Codecov Report

❌ Patch coverage is 89.74359% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.16%. Comparing base (ee964c4) to head (fa0d40d).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/synthorg/engine/workspace/git_worktree.py 89.36% 3 Missing and 2 partials ⚠️
src/synthorg/engine/workspace/semantic_git_ops.py 89.65% 2 Missing and 1 partial ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Aureliolo and others added 3 commits March 28, 2026 20:57
…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>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟡 Minor

Preserve 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 makes semantic_conflicts unstable 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

📥 Commits

Reviewing files that changed from the base of the PR and between 6e1e2d0 and 6a14fd4.

📒 Files selected for processing (9)
  • docs/design/engine.md
  • src/synthorg/engine/errors.py
  • src/synthorg/engine/workspace/config.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • tests/unit/engine/test_semantic_analyzer.py
  • tests/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: No from __future__ import annotations -- Python 3.14+ has PEP 649 native lazy annotations. Use except 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.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • tests/unit/engine/test_workspace_git_worktree.py
  • src/synthorg/engine/workspace/git_worktree.py
  • tests/unit/engine/test_semantic_analyzer.py
  • src/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_logger then logger = get_logger(__name__). Use event name constants from synthorg.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), 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).
Use Pydantic v2 models (BaseModel, model_validator, computed_field, ConfigDict). Use @computed_field for derived values instead of storing redundant fields (e.g., TokenUsage.total_tokens). Use NotBlankStr from core.types for all identifier/name fields (including optional NotBlankStr | None and tuple variants) instead of manual whitespace validators.
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.
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 use import logging or logging.getLogger() in application code. Exception: observability/setup.py and observability/sinks.py may use stdlib logging and print(..., file=sys.stderr) for bootst...

Files:

  • src/synthorg/engine/workspace/config.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/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.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/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.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/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 relevant docs/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. 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.
Use vendor-agnostic names in tests: test-provider, test-small-001, large/medium/small aliases 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.py
  • tests/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.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/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.py
  • src/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

Aureliolo and others added 2 commits March 28, 2026 21:43
…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>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6a14fd4 and cba8543.

📒 Files selected for processing (9)
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_checks.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • tests/unit/config/test_loader_properties.py
  • tests/unit/engine/test_semantic_analyzer.py
  • tests/unit/engine/test_semantic_llm.py
  • tests/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: No from __future__ import annotations -- Python 3.14+ has PEP 649 native lazy annotations. Use except 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.py
  • tests/unit/engine/test_semantic_llm.py
  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_checks.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • tests/unit/engine/test_semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • tests/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. 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.
Use vendor-agnostic names in tests: test-provider, test-small-001, large/medium/small aliases 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.py
  • tests/unit/engine/test_semantic_llm.py
  • tests/unit/engine/test_semantic_analyzer.py
  • tests/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_logger then logger = get_logger(__name__). Use event name constants from synthorg.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), 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).
Use Pydantic v2 models (BaseModel, model_validator, computed_field, ConfigDict). Use @computed_field for derived values instead of storing redundant fields (e.g., TokenUsage.total_tokens). Use NotBlankStr from core.types for all identifier/name fields (including optional NotBlankStr | None and tuple variants) instead of manual whitespace validators.
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.
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 use import logging or logging.getLogger() in application code. Exception: observability/setup.py and observability/sinks.py may use stdlib logging and print(..., file=sys.stderr) for bootst...

Files:

  • src/synthorg/engine/workspace/git_worktree.py
  • src/synthorg/engine/workspace/semantic_checks.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/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.py
  • src/synthorg/engine/workspace/semantic_checks.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/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.py
  • src/synthorg/engine/workspace/semantic_checks.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/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.py
  • 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 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.py
  • src/synthorg/engine/workspace/semantic_analyzer.py
  • src/synthorg/engine/workspace/semantic_llm.py
  • src/synthorg/engine/workspace/semantic_git_ops.py
  • 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.py
  • src/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.py
  • tests/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.py
  • 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/**/*.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=None is appropriate for this property-based parser robustness test.

The _yaml_text strategy generates arbitrary input including edge cases, and YAML parser performance legitimately varies across different inputs. Hypothesis explicitly recommends deadline=None for tests with variable performance characteristics like parser complexity variance. The coding guideline about mocking time.monotonic() and asyncio.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>
@Aureliolo Aureliolo merged commit 81372bf into main Mar 28, 2026
33 of 34 checks passed
@Aureliolo Aureliolo deleted the refactor/semantic-analyzers branch March 28, 2026 21:26
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 28, 2026 21:26 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Mar 30, 2026
🤖 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-&gt;3 and @types/node 22-&gt;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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant