feat(tools): wire RootConfig.git_clone to GitCloneTool instantiation#519
feat(tools): wire RootConfig.git_clone to GitCloneTool instantiation#519
Conversation
…Tool Create build_default_tools() factory that instantiates all 11 built-in workspace tools with config-driven parameters. The factory connects RootConfig.git_clone (GitCloneNetworkPolicy) to GitCloneTool's network_policy parameter, making YAML-configured hostname_allowlist functional. A convenience wrapper build_default_tools_from_config() extracts the policy from RootConfig automatically.
Pre-reviewed by 11 agents, 10 findings addressed: - Add TOOL_FACTORY_BUILT to CLAUDE.md logging event catalogue - Add factory.py to CLAUDE.md Package Structure tools/ line - Use public .workspace property instead of ._workspace in tests - Add sandbox passthrough test for build_default_tools_from_config - Add block_private_ips=False edge case test - Replace magic number 11 with _EXPECTED_TOOL_COUNT constant - Assert literal values instead of comparing against fresh instance - Rename yaml var to yaml_str to avoid stdlib shadowing - Fix "End-to-end" -> "Integration:" in docstring - Move deferred RootConfig imports to module level - Simplify intermediate variable and normalize separator width
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 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). (4)
🧰 Additional context used📓 Path-based instructions (2)**/*.md📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{md,py,ts,tsx,vue,go,yml,yaml,json,toml}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (18)📓 Common learnings📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
📚 Learning: 2026-03-15T11:48:14.867ZApplied to files:
📚 Learning: 2026-03-17T07:15:40.520ZApplied to files:
🪛 LanguageToolCLAUDE.md[style] ~199-~199: Since ownership is already implied, this phrasing may be redundant. (PRP_OWN) 🔇 Additional comments (2)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a new tools factory module with two public APIs to build built-in file-system and git tools (wiring RootConfig.git_clone and sandbox), exports those APIs, introduces three factory observability events, and adds unit and integration tests validating the wiring and composition. Changes
Sequence DiagramsequenceDiagram
participant Caller
participant Factory as build_default_tools_from_config()
participant Config as RootConfig
participant FileBuilder as _build_file_system_tools
participant GitBuilder as _build_git_tools
participant Logger as Event Logger
Caller->>Factory: call(workspace, config, sandbox)
Factory->>Config: read git_clone policy
Factory->>FileBuilder: instantiate file-system tools
FileBuilder-->>Factory: return file tools
Factory->>GitBuilder: instantiate git tools (network_policy, sandbox)
GitBuilder-->>Factory: return git tools
Factory->>Factory: combine & sort tools
Factory->>Logger: emit TOOL_FACTORY_CONFIG_ENTRY and TOOL_FACTORY_BUILT
Factory-->>Caller: return sorted tuple of tools
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
📝 Coding Plan
Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the configurability and robustness of tool instantiation by introducing a dedicated factory for built-in workspace tools. It allows for the dynamic creation of tools, particularly the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a well-designed factory for instantiating the built-in tools, which is a great improvement for configurability. The new build_default_tools and build_default_tools_from_config functions are clear, and the core goal of wiring the RootConfig.git_clone settings to the GitCloneTool is achieved effectively. The accompanying unit and integration tests are comprehensive and provide excellent coverage for the new functionality. The code quality is high. I have one minor suggestion for improving the maintainability of the documentation.
CLAUDE.md
Outdated
| - **Never** use `import logging` / `logging.getLogger()` / `print()` in application code | ||
| - **Variable name**: always `logger` (not `_logger`, not `log`) | ||
| - **Event names**: always use constants from the domain-specific module under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`, `BUDGET_RECORD_ADDED` from `events.budget`, `CFO_ANOMALY_DETECTED` from `events.cfo`, `CONFLICT_DETECTED` from `events.conflict`, `MEETING_STARTED` from `events.meeting`, `MEETING_SCHEDULER_STARTED` from `events.meeting`, `MEETING_SCHEDULER_ERROR` from `events.meeting`, `MEETING_SCHEDULER_STOPPED` from `events.meeting`, `MEETING_PERIODIC_TRIGGERED` from `events.meeting`, `MEETING_EVENT_TRIGGERED` from `events.meeting`, `MEETING_PARTICIPANTS_RESOLVED` from `events.meeting`, `MEETING_NO_PARTICIPANTS` from `events.meeting`, `MEETING_NOT_FOUND` from `events.meeting`, `CLASSIFICATION_START` from `events.classification`, `CONSOLIDATION_START` from `events.consolidation`, `ORG_MEMORY_QUERY_START` from `events.org_memory`, `API_REQUEST_STARTED` from `events.api`, `API_REQUEST_COMPLETED` from `events.api`, `API_REQUEST_ERROR` from `events.api`, `API_ROUTE_NOT_FOUND` from `events.api`, `API_HEALTH_CHECK` from `events.api`, `API_COORDINATION_STARTED` from `events.api`, `API_COORDINATION_COMPLETED` from `events.api`, `API_COORDINATION_FAILED` from `events.api`, `API_COORDINATION_AGENT_RESOLVE_FAILED` from `events.api`, `API_CONTENT_NEGOTIATED` from `events.api`, `API_CORRELATION_FALLBACK` from `events.api`, `API_ACCEPT_PARSE_FAILED` from `events.api`, `API_WS_TICKET_ISSUED` from `events.api`, `API_WS_TICKET_CONSUMED` from `events.api`, `API_WS_TICKET_EXPIRED` from `events.api`, `API_WS_TICKET_INVALID` from `events.api`, `API_WS_TICKET_CLEANUP` from `events.api`, `CODE_RUNNER_EXECUTE_START` from `events.code_runner`, `DOCKER_EXECUTE_START` from `events.docker`, `MCP_INVOKE_START` from `events.mcp`, `SECURITY_EVALUATE_START` from `events.security`, `HR_HIRING_REQUEST_CREATED` from `events.hr`, `PERF_METRIC_RECORDED` from `events.performance`, `PERF_LLM_SAMPLE_STARTED` from `events.performance`, `PERF_LLM_SAMPLE_COMPLETED` from `events.performance`, `PERF_LLM_SAMPLE_FAILED` from `events.performance`, `PERF_OVERRIDE_SET` from `events.performance`, `PERF_OVERRIDE_CLEARED` from `events.performance`, `PERF_OVERRIDE_APPLIED` from `events.performance`, `PERF_OVERRIDE_EXPIRED` from `events.performance`, `TRUST_EVALUATE_START` from `events.trust`, `PROMOTION_EVALUATE_START` from `events.promotion`, `PROMPT_BUILD_START` from `events.prompt`, `MEMORY_RETRIEVAL_START` from `events.memory`, `MEMORY_BACKEND_CONNECTED` from `events.memory`, `MEMORY_ENTRY_STORED` from `events.memory`, `MEMORY_BACKEND_SYSTEM_ERROR` from `events.memory`, `MEMORY_RRF_FUSION_COMPLETE` from `events.memory`, `MEMORY_RRF_VALIDATION_FAILED` from `events.memory`, `AUTONOMY_ACTION_AUTO_APPROVED` from `events.autonomy`, `TIMEOUT_POLICY_EVALUATED` from `events.timeout`, `PERSISTENCE_AUDIT_ENTRY_SAVED` from `events.persistence`, `TASK_ENGINE_STARTED` from `events.task_engine`, `COORDINATION_STARTED` from `events.coordination`, `COORDINATION_FACTORY_BUILT` from `events.coordination`, `COMMUNICATION_DISPATCH_START` from `events.communication`, `COMPANY_STARTED` from `events.company`, `CONFIG_LOADED` from `events.config`, `CORRELATION_ID_CREATED` from `events.correlation`, `DECOMPOSITION_STARTED` from `events.decomposition`, `DELEGATION_STARTED` from `events.delegation`, `EXECUTION_LOOP_START` from `events.execution`, `CHECKPOINT_SAVED` from `events.checkpoint`, `PERSISTENCE_CHECKPOINT_SAVED` from `events.persistence`, `GIT_COMMAND_START` from `events.git`, `GIT_CLONE_URL_REJECTED` from `events.git`, `GIT_CLONE_SSRF_BLOCKED` from `events.git`, `GIT_CLONE_DNS_FAILED` from `events.git`, `GIT_CLONE_SSRF_DISABLED` from `events.git`, `PARALLEL_GROUP_START` from `events.parallel`, `PERSONALITY_LOADED` from `events.personality`, `QUOTA_CHECKED` from `events.quota`, `ROLE_ASSIGNED` from `events.role`, `ROUTING_STARTED` from `events.routing`, `SANDBOX_EXECUTE_START` from `events.sandbox`, `TASK_CREATED` from `events.task`, `TASK_ASSIGNMENT_STARTED` from `events.task_assignment`, `TASK_ROUTING_STARTED` from `events.task_routing`, `TEMPLATE_LOADED` from `events.template`, `TOOL_INVOKE_START` from `events.tool`, `TOOL_OUTPUT_WITHHELD` from `events.tool`, `WORKSPACE_CREATED` from `events.workspace`, `APPROVAL_GATE_ESCALATION_DETECTED` from `events.approval_gate`, `APPROVAL_GATE_ESCALATION_FAILED` from `events.approval_gate`, `APPROVAL_GATE_INITIALIZED` from `events.approval_gate`, `APPROVAL_GATE_RISK_CLASSIFIED` from `events.approval_gate`, `APPROVAL_GATE_RISK_CLASSIFY_FAILED` from `events.approval_gate`, `APPROVAL_GATE_CONTEXT_PARKED` from `events.approval_gate`, `APPROVAL_GATE_CONTEXT_PARK_FAILED` from `events.approval_gate`, `APPROVAL_GATE_PARK_TASKLESS` from `events.approval_gate`, `APPROVAL_GATE_RESUME_STARTED` from `events.approval_gate`, `APPROVAL_GATE_CONTEXT_RESUMED` from `events.approval_gate`, `APPROVAL_GATE_RESUME_FAILED` from `events.approval_gate`, `APPROVAL_GATE_RESUME_DELETE_FAILED` from `events.approval_gate`, `APPROVAL_GATE_RESUME_TRIGGERED` from `events.approval_gate`, `APPROVAL_GATE_NO_PARKED_CONTEXT` from `events.approval_gate`, `APPROVAL_GATE_LOOP_WIRING_WARNING` from `events.approval_gate`, `STAGNATION_CHECK_PERFORMED` from `events.stagnation`, `STAGNATION_DETECTED` from `events.stagnation`, `STAGNATION_CORRECTION_INJECTED` from `events.stagnation`, `STAGNATION_TERMINATED` from `events.stagnation`, `PERSISTENCE_AGENT_STATE_SAVED` from `events.persistence`, `PERSISTENCE_AGENT_STATE_FETCHED` from `events.persistence`, `PERSISTENCE_AGENT_STATE_ACTIVE_QUERIED` from `events.persistence`, `PERSISTENCE_AGENT_STATE_DELETED` from `events.persistence`, `SETTINGS_VALUE_SET` from `events.settings`, `SETTINGS_VALUE_DELETED` from `events.settings`, `SETTINGS_VALUE_RESOLVED` from `events.settings`, `SETTINGS_CACHE_INVALIDATED` from `events.settings`, `SETTINGS_ENCRYPTION_ERROR` from `events.settings`, `SETTINGS_VALIDATION_FAILED` from `events.settings`, `SETTINGS_NOTIFICATION_PUBLISHED` from `events.settings`, `SETTINGS_NOTIFICATION_FAILED` from `events.settings`, `SETTINGS_FETCH_FAILED` from `events.settings`, `SETTINGS_SET_FAILED` from `events.settings`, `SETTINGS_DELETE_FAILED` from `events.settings`, `SETTINGS_NOT_FOUND` from `events.settings`, `SETTINGS_REGISTRY_DUPLICATE` from `events.settings`, `SETTINGS_CONFIG_PATH_MISS` from `events.settings`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT` | ||
| - **Event names**: always use constants from the domain-specific module under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`, `BUDGET_RECORD_ADDED` from `events.budget`, `CFO_ANOMALY_DETECTED` from `events.cfo`, `CONFLICT_DETECTED` from `events.conflict`, `MEETING_STARTED` from `events.meeting`, `MEETING_SCHEDULER_STARTED` from `events.meeting`, `MEETING_SCHEDULER_ERROR` from `events.meeting`, `MEETING_SCHEDULER_STOPPED` from `events.meeting`, `MEETING_PERIODIC_TRIGGERED` from `events.meeting`, `MEETING_EVENT_TRIGGERED` from `events.meeting`, `MEETING_PARTICIPANTS_RESOLVED` from `events.meeting`, `MEETING_NO_PARTICIPANTS` from `events.meeting`, `MEETING_NOT_FOUND` from `events.meeting`, `CLASSIFICATION_START` from `events.classification`, `CONSOLIDATION_START` from `events.consolidation`, `ORG_MEMORY_QUERY_START` from `events.org_memory`, `API_REQUEST_STARTED` from `events.api`, `API_REQUEST_COMPLETED` from `events.api`, `API_REQUEST_ERROR` from `events.api`, `API_ROUTE_NOT_FOUND` from `events.api`, `API_HEALTH_CHECK` from `events.api`, `API_COORDINATION_STARTED` from `events.api`, `API_COORDINATION_COMPLETED` from `events.api`, `API_COORDINATION_FAILED` from `events.api`, `API_COORDINATION_AGENT_RESOLVE_FAILED` from `events.api`, `API_CONTENT_NEGOTIATED` from `events.api`, `API_CORRELATION_FALLBACK` from `events.api`, `API_ACCEPT_PARSE_FAILED` from `events.api`, `API_WS_TICKET_ISSUED` from `events.api`, `API_WS_TICKET_CONSUMED` from `events.api`, `API_WS_TICKET_EXPIRED` from `events.api`, `API_WS_TICKET_INVALID` from `events.api`, `API_WS_TICKET_CLEANUP` from `events.api`, `CODE_RUNNER_EXECUTE_START` from `events.code_runner`, `DOCKER_EXECUTE_START` from `events.docker`, `MCP_INVOKE_START` from `events.mcp`, `SECURITY_EVALUATE_START` from `events.security`, `HR_HIRING_REQUEST_CREATED` from `events.hr`, `PERF_METRIC_RECORDED` from `events.performance`, `PERF_LLM_SAMPLE_STARTED` from `events.performance`, `PERF_LLM_SAMPLE_COMPLETED` from `events.performance`, `PERF_LLM_SAMPLE_FAILED` from `events.performance`, `PERF_OVERRIDE_SET` from `events.performance`, `PERF_OVERRIDE_CLEARED` from `events.performance`, `PERF_OVERRIDE_APPLIED` from `events.performance`, `PERF_OVERRIDE_EXPIRED` from `events.performance`, `TRUST_EVALUATE_START` from `events.trust`, `PROMOTION_EVALUATE_START` from `events.promotion`, `PROMPT_BUILD_START` from `events.prompt`, `MEMORY_RETRIEVAL_START` from `events.memory`, `MEMORY_BACKEND_CONNECTED` from `events.memory`, `MEMORY_ENTRY_STORED` from `events.memory`, `MEMORY_BACKEND_SYSTEM_ERROR` from `events.memory`, `MEMORY_RRF_FUSION_COMPLETE` from `events.memory`, `MEMORY_RRF_VALIDATION_FAILED` from `events.memory`, `AUTONOMY_ACTION_AUTO_APPROVED` from `events.autonomy`, `TIMEOUT_POLICY_EVALUATED` from `events.timeout`, `PERSISTENCE_AUDIT_ENTRY_SAVED` from `events.persistence`, `TASK_ENGINE_STARTED` from `events.task_engine`, `COORDINATION_STARTED` from `events.coordination`, `COORDINATION_FACTORY_BUILT` from `events.coordination`, `COMMUNICATION_DISPATCH_START` from `events.communication`, `COMPANY_STARTED` from `events.company`, `CONFIG_LOADED` from `events.config`, `CORRELATION_ID_CREATED` from `events.correlation`, `DECOMPOSITION_STARTED` from `events.decomposition`, `DELEGATION_STARTED` from `events.delegation`, `EXECUTION_LOOP_START` from `events.execution`, `CHECKPOINT_SAVED` from `events.checkpoint`, `PERSISTENCE_CHECKPOINT_SAVED` from `events.persistence`, `GIT_COMMAND_START` from `events.git`, `GIT_CLONE_URL_REJECTED` from `events.git`, `GIT_CLONE_SSRF_BLOCKED` from `events.git`, `GIT_CLONE_DNS_FAILED` from `events.git`, `GIT_CLONE_SSRF_DISABLED` from `events.git`, `PARALLEL_GROUP_START` from `events.parallel`, `PERSONALITY_LOADED` from `events.personality`, `QUOTA_CHECKED` from `events.quota`, `ROLE_ASSIGNED` from `events.role`, `ROUTING_STARTED` from `events.routing`, `SANDBOX_EXECUTE_START` from `events.sandbox`, `TASK_CREATED` from `events.task`, `TASK_ASSIGNMENT_STARTED` from `events.task_assignment`, `TASK_ROUTING_STARTED` from `events.task_routing`, `TEMPLATE_LOADED` from `events.template`, `TOOL_INVOKE_START` from `events.tool`, `TOOL_OUTPUT_WITHHELD` from `events.tool`, `TOOL_FACTORY_BUILT` from `events.tool`, `WORKSPACE_CREATED` from `events.workspace`, `APPROVAL_GATE_ESCALATION_DETECTED` from `events.approval_gate`, `APPROVAL_GATE_ESCALATION_FAILED` from `events.approval_gate`, `APPROVAL_GATE_INITIALIZED` from `events.approval_gate`, `APPROVAL_GATE_RISK_CLASSIFIED` from `events.approval_gate`, `APPROVAL_GATE_RISK_CLASSIFY_FAILED` from `events.approval_gate`, `APPROVAL_GATE_CONTEXT_PARKED` from `events.approval_gate`, `APPROVAL_GATE_CONTEXT_PARK_FAILED` from `events.approval_gate`, `APPROVAL_GATE_PARK_TASKLESS` from `events.approval_gate`, `APPROVAL_GATE_RESUME_STARTED` from `events.approval_gate`, `APPROVAL_GATE_CONTEXT_RESUMED` from `events.approval_gate`, `APPROVAL_GATE_RESUME_FAILED` from `events.approval_gate`, `APPROVAL_GATE_RESUME_DELETE_FAILED` from `events.approval_gate`, `APPROVAL_GATE_RESUME_TRIGGERED` from `events.approval_gate`, `APPROVAL_GATE_NO_PARKED_CONTEXT` from `events.approval_gate`, `APPROVAL_GATE_LOOP_WIRING_WARNING` from `events.approval_gate`, `STAGNATION_CHECK_PERFORMED` from `events.stagnation`, `STAGNATION_DETECTED` from `events.stagnation`, `STAGNATION_CORRECTION_INJECTED` from `events.stagnation`, `STAGNATION_TERMINATED` from `events.stagnation`, `PERSISTENCE_AGENT_STATE_SAVED` from `events.persistence`, `PERSISTENCE_AGENT_STATE_FETCHED` from `events.persistence`, `PERSISTENCE_AGENT_STATE_ACTIVE_QUERIED` from `events.persistence`, `PERSISTENCE_AGENT_STATE_DELETED` from `events.persistence`, `SETTINGS_VALUE_SET` from `events.settings`, `SETTINGS_VALUE_DELETED` from `events.settings`, `SETTINGS_VALUE_RESOLVED` from `events.settings`, `SETTINGS_CACHE_INVALIDATED` from `events.settings`, `SETTINGS_ENCRYPTION_ERROR` from `events.settings`, `SETTINGS_VALIDATION_FAILED` from `events.settings`, `SETTINGS_NOTIFICATION_PUBLISHED` from `events.settings`, `SETTINGS_NOTIFICATION_FAILED` from `events.settings`, `SETTINGS_FETCH_FAILED` from `events.settings`, `SETTINGS_SET_FAILED` from `events.settings`, `SETTINGS_DELETE_FAILED` from `events.settings`, `SETTINGS_NOT_FOUND` from `events.settings`, `SETTINGS_REGISTRY_DUPLICATE` from `events.settings`, `SETTINGS_CONFIG_PATH_MISS` from `events.settings`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT` |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #519 +/- ##
=======================================
Coverage 93.15% 93.16%
=======================================
Files 505 506 +1
Lines 24480 24490 +10
Branches 2333 2333
=======================================
+ Hits 22805 22815 +10
Misses 1328 1328
Partials 347 347 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@CLAUDE.md`:
- Line 199: Replace the huge inline mega-list of event constants with a concise
example and a pointer to the events package: show one or two example imports
(e.g., "from synthorg.observability.events.api import API_REQUEST_STARTED") and
then add a short sentence directing readers to the events directory for the full
list (referencing the module path src/synthorg/observability/events/). Keep the
wording in the current CLAUDE.md sentence but remove the long comma-separated
list and ensure the example uses the generic symbol EVENT_CONSTANT or a real
constant like API_REQUEST_STARTED to demonstrate the pattern.
In `@src/synthorg/tools/factory.py`:
- Around line 41-92: build_default_tools is over the 50-line limit; split it
into two small private helper builders to reduce size. Create
_build_filesystem_tools(workspace: Path) -> list[BaseTool] that returns the
fs_tools list (ReadFileTool, WriteFileTool, EditFileTool, ListDirectoryTool,
DeleteFileTool) and _build_git_tools(workspace: Path, sandbox: SandboxBackend |
None, git_clone_policy: GitCloneNetworkPolicy | None) -> list[BaseTool] that
returns the git_tools list (GitStatusTool, GitLogTool, GitDiffTool,
GitBranchTool, GitCommitTool, GitCloneTool), then update build_default_tools to
call these helpers, sort the combined list into result, log with
TOOL_FACTORY_BUILT and return result; keep names (fs_tools, git_tools, result,
TOOL_FACTORY_BUILT) so callers and logging remain unchanged.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 02262b24-a764-46a3-bcb8-a96874bde3ad
📒 Files selected for processing (6)
CLAUDE.mdsrc/synthorg/observability/events/tool.pysrc/synthorg/tools/__init__.pysrc/synthorg/tools/factory.pytests/integration/tools/test_factory_integration.pytests/unit/tools/test_factory.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: Deploy Preview
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Sandbox
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Do not usefrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations.
Useexcept A, B:syntax (no parentheses) — PEP 758 except syntax enforced by ruff on Python 3.14.
Add type hints to all public functions; enforce mypy strict mode compliance.
Use Google-style docstrings on all public classes and functions; enforce via ruff D rules.
Keep functions under 50 lines and files under 800 lines.
Handle errors explicitly and never silently swallow exceptions.
Validate at system boundaries (user input, external APIs, config files).
Set line length to 88 characters (ruff enforces).
Useuvfor Python dependency management. Install withuv sync, run tests with-n autofor parallelism, lint withruff check, format withruff format, type-check withmypy.
Scripts inscripts/have relaxed ruff rules:
Files:
src/synthorg/observability/events/tool.pytests/unit/tools/test_factory.pysrc/synthorg/tools/factory.pysrc/synthorg/tools/__init__.pytests/integration/tools/test_factory_integration.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Create new objects instead of mutating existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping. Fordict/listfields in frozen Pydantic models, rely onfrozen=Trueandcopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization).
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (withmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Adopt Pydantic v2 conventions: use@computed_fieldfor derived values instead of storing redundant fields; useNotBlankStrfromcore.typesfor all identifier/name fields (including optional and tuple variants) instead of manual whitespace validators.
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Every module with business logic must have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__). Never useimport logging,logging.getLogger(), orprint()in application code.
Always useloggeras the variable name (not_logger, notlog). Use event name constants from domain-specific modules undersynthorg.observability.events(e.g.,PROVIDER_CALL_STARTfromevents.provider). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT.
Always use structured kwargs for logging:logger.info(EVENT, key=value)— never use string interpolation likelogger.info('msg %s', val).
Log all error paths at WARNING or ERROR with context before raising. Log all state transitions at INFO. Log object creation, internal flow, and entry/exit of key functions at DEBUG.
Do NOT useimport loggingorlogging.getLogger(). Pure data models, ...
Files:
src/synthorg/observability/events/tool.pysrc/synthorg/tools/factory.pysrc/synthorg/tools/__init__.py
**/*.{md,py,ts,tsx,vue,go,yml,yaml,json,toml}
📄 CodeRabbit inference engine (CLAUDE.md)
Use conventional commits:
<type>: <description>where types are feat, fix, refactor, docs, test, chore, perf, ci. Commits must be GPG/SSH signed on main branch.
Files:
src/synthorg/observability/events/tool.pytests/unit/tools/test_factory.pysrc/synthorg/tools/factory.pyCLAUDE.mdsrc/synthorg/tools/__init__.pytests/integration/tools/test_factory_integration.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Mark tests with@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e, or@pytest.mark.slow. Maintain 80% minimum code coverage.
Useasyncio_mode = 'auto'for async tests — no manual@pytest.mark.asyncioneeded. Set test timeout to 30 seconds per test. Always include-n autofor parallelism via pytest-xdist.
Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned test code, docstrings, or config examples. Use generic names:example-provider,example-large-001,example-medium-001,example-small-001,test-provider,test-small-001, etc. Vendor names may only appear in Operations design page, .claude/ files, or third-party import paths.
Use Hypothesis for property-based testing with@given+@settings. Profiles:ci(200 examples, default) anddev(1000 examples) viaHYPOTHESIS_PROFILEenv var. Never skip, dismiss, or ignore flaky tests — fix them fully. Mocktime.monotonic()andasyncio.sleep()for deterministic timing-sensitive tests instead of widening margins.
Files:
tests/unit/tools/test_factory.pytests/integration/tools/test_factory_integration.py
src/synthorg/tools/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Tool registry with built-in tools: file_system/, git (SSRF prevention via git_url_validator), sandbox/, code_runner. MCP bridge (mcp/). Role-based access. Approval tool (request_human_approval).
Files:
src/synthorg/tools/factory.pysrc/synthorg/tools/__init__.py
**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Read relevant
docs/design/page before implementing features or planning issues. Design spec is the starting point for architecture, data models, and behavior.
Files:
CLAUDE.md
🧠 Learnings (17)
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under synthorg.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
src/synthorg/observability/events/tool.pyCLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/tools/**/*.py : Tool registry with built-in tools: file_system/, git (SSRF prevention via git_url_validator), sandbox/, code_runner. MCP bridge (mcp/). Role-based access. Approval tool (request_human_approval).
Applied to files:
tests/unit/tools/test_factory.pysrc/synthorg/tools/factory.pyCLAUDE.mdsrc/synthorg/tools/__init__.pytests/integration/tools/test_factory_integration.py
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Create new objects instead of mutating existing ones. For non-Pydantic internal collections (registries, `BaseTool`), use `copy.deepcopy()` at construction + `MappingProxyType` wrapping. For `dict`/`list` fields in frozen Pydantic models, rely on `frozen=True` and `copy.deepcopy()` at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization).
Applied to files:
src/synthorg/tools/factory.py
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Always use `logger` as the variable name (not `_logger`, not `log`). Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/security/**/*.py : SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to web/**/*.{ts,tsx,vue} : TypeScript Vue 3 dashboard with PrimeVue UI components, Tailwind CSS styling, Pinia state management, VueFlow for org charts, ECharts for charts, Axios for API calls. Structure: `components/` (feature-organized), `composables/` (reusable logic), `stores/` (Pinia), `router/` (Vue Router), `views/` (pages), `__tests__/` (Vitest), `utils/` (helpers), `api/` (endpoints).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to docs/**/*.md : Documentation in Markdown built with Zensical. Design spec: 7 pages under `docs/design/` (index, agents, organization, communication, engine, memory, operations). Architecture: `docs/architecture/`. Roadmap: `docs/roadmap/`. Security: `docs/security.md`. Licensing: `docs/licensing.md`. Reference: `docs/reference/`. REST API: `docs/rest-api.md` with generated Scalar UI. Library reference: `docs/api/` (auto-generated from docstrings via mkdocstrings + Griffe).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging` / `logging.getLogger()` / `print()` in application code. Variable name: always `logger` (not `_logger`, not `log`).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : Structured kwargs in logging: always `logger.info(EVENT, key=value)` — never `logger.info('msg %s', val)`.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Always use structured kwargs for logging: `logger.info(EVENT, key=value)` — never use string interpolation like `logger.info('msg %s', val)`.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic must have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging`, `logging.getLogger()`, or `print()` in application code.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : All error paths must log at WARNING or ERROR with context before raising.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Log all error paths at WARNING or ERROR with context before raising. Log all state transitions at INFO. Log object creation, internal flow, and entry/exit of key functions at DEBUG.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : All state transitions must log at INFO.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Do NOT use `import logging` or `logging.getLogger()`. Pure data models, enums, and re-exports do NOT need logging setup.
Applied to files:
CLAUDE.md
🧬 Code graph analysis (4)
tests/unit/tools/test_factory.py (2)
src/synthorg/config/schema.py (1)
RootConfig(387-651)src/synthorg/tools/git_url_validator.py (1)
GitCloneNetworkPolicy(82-127)
src/synthorg/tools/factory.py (3)
src/synthorg/tools/git_tools.py (1)
GitCloneTool(596-720)src/synthorg/config/schema.py (1)
RootConfig(387-651)src/synthorg/tools/git_url_validator.py (1)
GitCloneNetworkPolicy(82-127)
src/synthorg/tools/__init__.py (1)
src/synthorg/tools/factory.py (2)
build_default_tools(41-92)build_default_tools_from_config(95-119)
tests/integration/tools/test_factory_integration.py (3)
src/synthorg/config/loader.py (1)
load_config_from_string(495-524)src/synthorg/tools/factory.py (2)
build_default_tools(41-92)build_default_tools_from_config(95-119)src/synthorg/tools/git_tools.py (1)
GitCloneTool(596-720)
🔇 Additional comments (7)
src/synthorg/observability/events/tool.py (1)
26-27: Looks good: new factory event constant is consistent with existing event taxonomy.src/synthorg/tools/factory.py (1)
95-119: Nice wrapper design: config policy passthrough is clear and correct.src/synthorg/tools/__init__.py (1)
14-14: Public exports are correctly wired for the new factory APIs.Also applies to: 90-91
CLAUDE.md (1)
135-135: Package-structure docs update is aligned with the new tool factory surface.tests/unit/tools/test_factory.py (2)
34-160: Strong unit coverage for factory construction, ordering, and policy/sandbox wiring.
163-216: Wrapper-focused unit tests are solid and directly validateRootConfig.git_clonepassthrough.tests/integration/tools/test_factory_integration.py (1)
18-68: Great integration coverage for the YAML→config→factory→GitCloneToolpipeline and registry wrapping path.
…t, and Gemini - Split build_default_tools into private helpers (_build_file_system_tools, _build_git_tools) to satisfy the 50-line function limit - Add workspace absoluteness guard for fail-fast validation before partial tool construction - Add Raises section to both factory function docstrings - Log git_clone_block_private_ips and git_clone_allowlist_size in TOOL_FACTORY_BUILT event for security audit visibility - Add DEBUG-level entry log to build_default_tools_from_config - Add TOOL_FACTORY_ERROR event constant for validation failures - Parametrize three policy-variant unit tests per CLAUDE.md convention - Add workspace validation unit test for new guard - Add integration tests for YAML block_private_ips:false and absent git_clone key - Condense CLAUDE.md event constant mega-list to example + pointer
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/synthorg/tools/factory.py`:
- Around line 152-155: The DEBUG entry log currently reuses the
TOOL_FACTORY_BUILT event constant (logger.debug(..., source="config")) which
conflicts with the INFO completion log in build_default_tools; update the entry
logging in factory.py to either remove the event constant and log a plain debug
message via logger.debug("Entering tool factory configuration", source="config")
or introduce and use a new constant TOOL_FACTORY_CONFIG_ENTRY for this entry
point and reference that constant in the logger.debug call, ensuring
build_default_tools still uses TOOL_FACTORY_BUILT for completion logging.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6dc684e9-cc9f-40ea-ae79-5bc68d9a33fc
📒 Files selected for processing (5)
CLAUDE.mdsrc/synthorg/observability/events/tool.pysrc/synthorg/tools/factory.pytests/integration/tools/test_factory_integration.pytests/unit/tools/test_factory.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: Deploy Preview
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Sandbox
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Read relevant
docs/design/page before implementing features or planning issues. Design spec is the starting point for architecture, data models, and behavior.
Files:
CLAUDE.md
**/*.{md,py,ts,tsx,vue,go,yml,yaml,json,toml}
📄 CodeRabbit inference engine (CLAUDE.md)
Use conventional commits:
<type>: <description>where types are feat, fix, refactor, docs, test, chore, perf, ci. Commits must be GPG/SSH signed on main branch.
Files:
CLAUDE.mdsrc/synthorg/tools/factory.pysrc/synthorg/observability/events/tool.pytests/integration/tools/test_factory_integration.pytests/unit/tools/test_factory.py
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Do not usefrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations.
Useexcept A, B:syntax (no parentheses) — PEP 758 except syntax enforced by ruff on Python 3.14.
Add type hints to all public functions; enforce mypy strict mode compliance.
Use Google-style docstrings on all public classes and functions; enforce via ruff D rules.
Keep functions under 50 lines and files under 800 lines.
Handle errors explicitly and never silently swallow exceptions.
Validate at system boundaries (user input, external APIs, config files).
Set line length to 88 characters (ruff enforces).
Useuvfor Python dependency management. Install withuv sync, run tests with-n autofor parallelism, lint withruff check, format withruff format, type-check withmypy.
Scripts inscripts/have relaxed ruff rules:
Files:
src/synthorg/tools/factory.pysrc/synthorg/observability/events/tool.pytests/integration/tools/test_factory_integration.pytests/unit/tools/test_factory.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Create new objects instead of mutating existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping. Fordict/listfields in frozen Pydantic models, rely onfrozen=Trueandcopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, persistence serialization).
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (withmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Adopt Pydantic v2 conventions: use@computed_fieldfor derived values instead of storing redundant fields; useNotBlankStrfromcore.typesfor all identifier/name fields (including optional and tuple variants) instead of manual whitespace validators.
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Every module with business logic must have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__). Never useimport logging,logging.getLogger(), orprint()in application code.
Always useloggeras the variable name (not_logger, notlog). Use event name constants from domain-specific modules undersynthorg.observability.events(e.g.,PROVIDER_CALL_STARTfromevents.provider). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT.
Always use structured kwargs for logging:logger.info(EVENT, key=value)— never use string interpolation likelogger.info('msg %s', val).
Log all error paths at WARNING or ERROR with context before raising. Log all state transitions at INFO. Log object creation, internal flow, and entry/exit of key functions at DEBUG.
Do NOT useimport loggingorlogging.getLogger(). Pure data models, ...
Files:
src/synthorg/tools/factory.pysrc/synthorg/observability/events/tool.py
src/synthorg/tools/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Tool registry with built-in tools: file_system/, git (SSRF prevention via git_url_validator), sandbox/, code_runner. MCP bridge (mcp/). Role-based access. Approval tool (request_human_approval).
Files:
src/synthorg/tools/factory.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Mark tests with@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e, or@pytest.mark.slow. Maintain 80% minimum code coverage.
Useasyncio_mode = 'auto'for async tests — no manual@pytest.mark.asyncioneeded. Set test timeout to 30 seconds per test. Always include-n autofor parallelism via pytest-xdist.
Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned test code, docstrings, or config examples. Use generic names:example-provider,example-large-001,example-medium-001,example-small-001,test-provider,test-small-001, etc. Vendor names may only appear in Operations design page, .claude/ files, or third-party import paths.
Use Hypothesis for property-based testing with@given+@settings. Profiles:ci(200 examples, default) anddev(1000 examples) viaHYPOTHESIS_PROFILEenv var. Never skip, dismiss, or ignore flaky tests — fix them fully. Mocktime.monotonic()andasyncio.sleep()for deterministic timing-sensitive tests instead of widening margins.
Files:
tests/integration/tools/test_factory_integration.pytests/unit/tools/test_factory.py
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/tools/**/*.py : Tool registry with built-in tools: file_system/, git (SSRF prevention via git_url_validator), sandbox/, code_runner. MCP bridge (mcp/). Role-based access. Approval tool (request_human_approval).
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under synthorg.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
CLAUDE.mdsrc/synthorg/observability/events/tool.py
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Always use `logger` as the variable name (not `_logger`, not `log`). Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/tools/**/*.py : Tool registry with built-in tools: file_system/, git (SSRF prevention via git_url_validator), sandbox/, code_runner. MCP bridge (mcp/). Role-based access. Approval tool (request_human_approval).
Applied to files:
CLAUDE.mdsrc/synthorg/tools/factory.pytests/integration/tools/test_factory_integration.pytests/unit/tools/test_factory.py
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/security/**/*.py : SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to web/**/*.{ts,tsx,vue} : TypeScript Vue 3 dashboard with PrimeVue UI components, Tailwind CSS styling, Pinia state management, VueFlow for org charts, ECharts for charts, Axios for API calls. Structure: `components/` (feature-organized), `composables/` (reusable logic), `stores/` (Pinia), `router/` (Vue Router), `views/` (pages), `__tests__/` (Vitest), `utils/` (helpers), `api/` (endpoints).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to docs/**/*.md : Documentation in Markdown built with Zensical. Design spec: 7 pages under `docs/design/` (index, agents, organization, communication, engine, memory, operations). Architecture: `docs/architecture/`. Roadmap: `docs/roadmap/`. Security: `docs/security.md`. Licensing: `docs/licensing.md`. Reference: `docs/reference/`. REST API: `docs/rest-api.md` with generated Scalar UI. Library reference: `docs/api/` (auto-generated from docstrings via mkdocstrings + Griffe).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging` / `logging.getLogger()` / `print()` in application code. Variable name: always `logger` (not `_logger`, not `log`).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic must have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging`, `logging.getLogger()`, or `print()` in application code.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : Structured kwargs in logging: always `logger.info(EVENT, key=value)` — never `logger.info('msg %s', val)`.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Always use structured kwargs for logging: `logger.info(EVENT, key=value)` — never use string interpolation like `logger.info('msg %s', val)`.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : All error paths must log at WARNING or ERROR with context before raising.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Log all error paths at WARNING or ERROR with context before raising. Log all state transitions at INFO. Log object creation, internal flow, and entry/exit of key functions at DEBUG.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to src/synthorg/**/*.py : All state transitions must log at INFO.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to src/synthorg/**/*.py : Do NOT use `import logging` or `logging.getLogger()`. Pure data models, enums, and re-exports do NOT need logging setup.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T07:15:40.520Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T07:15:40.520Z
Learning: Applies to **/*.py : Keep functions under 50 lines and files under 800 lines.
Applied to files:
src/synthorg/tools/factory.py
🧬 Code graph analysis (2)
src/synthorg/tools/factory.py (2)
src/synthorg/config/schema.py (1)
RootConfig(387-651)src/synthorg/tools/git_url_validator.py (1)
GitCloneNetworkPolicy(82-127)
tests/unit/tools/test_factory.py (3)
src/synthorg/config/schema.py (1)
RootConfig(387-651)src/synthorg/tools/git_tools.py (1)
GitCloneTool(596-720)src/synthorg/tools/git_url_validator.py (1)
GitCloneNetworkPolicy(82-127)
🪛 LanguageTool
CLAUDE.md
[style] ~199-~199: Since ownership is already implied, this phrasing may be redundant.
Context: ...RTfromevents.git). Each domain has its own module — see src/synthorg/observabilit...
(PRP_OWN)
🔇 Additional comments (13)
src/synthorg/observability/events/tool.py (1)
26-29: LGTM!The new
TOOL_FACTORY_BUILTandTOOL_FACTORY_ERRORevent constants follow the established naming convention and are properly organized with a section comment. TheFinal[str]type annotation is consistent with existing constants in this module.CLAUDE.md (2)
135-135: LGTM!The tools package structure documentation is correctly updated to include the new factory functions
build_default_toolsandbuild_default_tools_from_config.
199-199: LGTM!The event names guidance is improved with concrete examples (
API_REQUEST_STARTED,TOOL_INVOKE_START,GIT_COMMAND_START) and a reference to the events directory for the full inventory. This addresses the prior feedback to make the documentation more maintainable.src/synthorg/tools/factory.py (3)
1-42: LGTM!The module structure is well-organized:
- Proper observability setup with
get_logger(__name__)- Event constants imported from the domain-specific module
TYPE_CHECKINGblock correctly used for type-only imports- Clear module docstring explaining both public APIs
44-76: LGTM!The private helper functions are well-designed:
_build_file_system_toolsand_build_git_toolseach return a tuple of tools- Clear docstrings describe the purpose
git_clone_policyis correctly wired toGitCloneTool.network_policy
79-126: LGTM!The
build_default_toolsfunction is well-implemented:
- Validates workspace absoluteness with proper error logging before raising
- Combines and sorts tools by name for deterministic ordering
- Logs
TOOL_FACTORY_BUILTwith comprehensive metrics (tool count, names, policy details)- Correctly handles
Nonepolicy by defaulting to restrictive values in the log outputtests/unit/tools/test_factory.py (4)
1-31: LGTM!The test module setup is clean with proper imports and a well-defined
_EXPECTED_TOOL_NAMESconstant that documents the expected 11 built-in tools in sorted order. This makes test maintenance easier when tools are added or renamed.
34-92: LGTM!The
TestBuildDefaultToolsclass has excellent coverage:
- Verifies tool count and sorted order
- Uses
@pytest.mark.parametrizefor policy wiring variants (custom allowlist, default whenNone, permissive policy)- Tests workspace validation with relative path rejection
94-166: LGTM!Good coverage of workspace and sandbox propagation:
- File system tools receive correct
workspace_root- Git tools receive correct
workspace- Sandbox backend is forwarded to all git tools
- Return type verification (tuple) and
BaseToolisinstance checks
169-222: LGTM!The
TestBuildDefaultToolsFromConfigtests properly verify the config wrapper:
- Policy extraction from
RootConfig.git_clone- Default config yields default policy
- Sandbox forwarding through the config wrapper
tests/integration/tools/test_factory_integration.py (3)
1-16: LGTM!The integration test module is well-structured with proper imports and the
_EXPECTED_TOOL_COUNTconstant. Usingload_config_from_stringenables testing the full YAML → RootConfig → factory pipeline without filesystem dependencies.
18-96: LGTM!Excellent integration test coverage for the config-driven tool factory pipeline:
- Tests all key YAML configurations: allowlist, empty section,
block_private_ips: false, and absent key- Each test verifies policy propagation through to
GitCloneTool._network_policy- Uses realistic YAML syntax with proper indentation
These tests directly validate the PR's objective of wiring
RootConfig.git_clonetoGitCloneTool.
98-105: LGTM!The
test_factory_tools_form_valid_registrytest is a valuable integration check that verifies factory output can be wrapped in aToolRegistrywithout errors, confirming compatibility with the existing tool infrastructure.
…try log Avoid reusing TOOL_FACTORY_BUILT for both the DEBUG entry log in build_default_tools_from_config and the INFO completion log in build_default_tools — distinct event constants prevent confusion in log aggregation and metrics.
🤖 I have created a release *beep* *boop* --- ## [0.3.1](v0.3.0...v0.3.1) (2026-03-17) ### Features * **api:** RFC 9457 Phase 2 — ProblemDetail and content negotiation ([#496](#496)) ([30f7c49](30f7c49)) * **cli:** verify container image signatures and SLSA provenance on pull ([#492](#492)) ([bef272d](bef272d)), closes [#491](#491) * **engine:** implement context budget management in execution loops ([#520](#520)) ([181eb8a](181eb8a)), closes [#416](#416) * implement settings persistence layer (DB-backed config) ([#495](#495)) ([4bd99f7](4bd99f7)), closes [#450](#450) * **memory:** implement dual-mode archival in memory consolidation ([#524](#524)) ([4603c9e](4603c9e)), closes [#418](#418) * migrate config consumers to read through SettingsService ([#510](#510)) ([32f553d](32f553d)) * **settings:** implement settings change subscriptions for service hot-reload ([#526](#526)) ([53f908e](53f908e)), closes [#503](#503) * **settings:** register API config in SettingsService with 2-phase init ([#518](#518)) ([29f7481](29f7481)) * **tools:** add SSRF prevention for git clone URLs ([#505](#505)) ([492dd0d](492dd0d)) * **tools:** wire RootConfig.git_clone to GitCloneTool instantiation ([#519](#519)) ([b7d8172](b7d8172)) ### Bug Fixes * **api:** replace JWT query parameter with one-time ticket for WebSocket auth ([#493](#493)) ([22a25f6](22a25f6)), closes [#343](#343) ### Documentation * add uv cache lock contention handling to worktree skill ([#500](#500)) ([bd85a8d](bd85a8d)) * document RFC 9457 dual response formats in OpenAPI schema ([#506](#506)) ([8dd2524](8dd2524)) ### Maintenance * upgrade jsdom from 28 to 29 ([#499](#499)) ([1ea2249](1ea2249)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
build_default_tools()factory that instantiates all 11 built-in workspace tools with config-driven parametersbuild_default_tools_from_config()convenience wrapper that extractsRootConfig.git_cloneand wires it toGitCloneTool(network_policy=)hostname_allowlistfunctional by connecting config to tool instantiationTOOL_FACTORY_BUILTevent constant andfactory.pyin package structureCloses #507
Test plan
Review coverage
Pre-reviewed by 11 agents (docs-consistency, code-reviewer, python-reviewer, pr-test-analyzer, comment-analyzer, logging-audit, resilience-audit, conventions-enforcer, security-reviewer, test-quality-reviewer, issue-resolution-verifier). 10 findings addressed in a dedicated review-fix commit.