feat: token-based personality trimming via PromptProfile.max_personality_tokens#1059
feat: token-based personality trimming via PromptProfile.max_personality_tokens#1059
Conversation
WalkthroughImplements token-based personality trimming in the prompt pipeline: adds a frozen Pydantic Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches. Re-running this action after a short time may resolve the issue. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
There was a problem hiding this comment.
Code Review
This pull request implements a three-tier progressive personality trimming system to manage token budgets for system prompts, including new settings and observability metadata. Feedback identifies a logic error where personality trimming is reverted during iterative section-level trimming, a bug in the description truncation function that adds unnecessary ellipses, and an inconsistency caused by hardcoding the token estimator.
src/synthorg/engine/prompt.py
Outdated
| context_budget=context_budget, | ||
| currency=currency, | ||
| profile=profile, | ||
| trimming_enabled=False, |
There was a problem hiding this comment.
In _trim_sections, trimming_enabled=False is passed to _render_and_estimate. Since _render_and_estimate builds a fresh template context from the original agent identity, this causes any personality trimming applied in the initial render to be lost.
As a result, the personality section reverts to its full size during iterative section trimming. This can lead to the prompt exceeding the total token budget even after all optional sections are removed, or cause the engine to aggressively trim other critical sections (like the task or policies) because it incorrectly perceives the personality section as taking up its full original budget. _trim_sections should respect the personality trimming decisions made in the first pass.
| budget = max_chars - len(ellipsis) | ||
| truncated = description[:budget] | ||
| # Find last space to avoid splitting mid-word. | ||
| last_space = truncated.rfind(" ") | ||
| if last_space > 0: | ||
| truncated = truncated[:last_space] | ||
| return truncated.rstrip() + ellipsis |
There was a problem hiding this comment.
The _truncate_description function always appends an ellipsis, even if the input string already fits within the max_chars limit. This results in unnecessary truncation markers and slightly increased token counts for descriptions that don't actually need trimming. Additionally, it causes an empty description to be returned as "...", which is likely unintended.
Note that the unit test test_empty_input in tests/unit/engine/test_personality_trimming.py currently asserts this buggy behavior and should be updated accordingly.
if len(description) <= max_chars:
return description
budget = max_chars - len(ellipsis)
truncated = description[:budget]
# Find last space to avoid splitting mid-word.
last_space = truncated.rfind(" ")
if last_space > 0:
truncated = truncated[:last_space]
return truncated.rstrip() + ellipsis| :class:`PersonalityTrimInfo` when trimming was applied, or | ||
| ``None`` when the section was already within budget. | ||
| """ | ||
| estimator = DefaultTokenEstimator() |
There was a problem hiding this comment.
_trim_personality instantiates a DefaultTokenEstimator internally, which ignores any custom token_estimator (such as a more accurate Tiktoken-based implementation) that may have been passed to build_system_prompt. This leads to inconsistent token counting where the personality section is trimmed based on a character-count heuristic while the rest of the prompt might be measured using actual model-specific encoding. The estimator should be passed down through the call chain from build_system_prompt.
There was a problem hiding this comment.
Pull request overview
Implements enforcement of PromptProfile.max_personality_tokens by introducing progressive, token-estimate-based trimming of the personality section, and exposes trimming metadata through the prompt-building API and observability hooks.
Changes:
- Added a 3-tier personality trimming pipeline (condense → truncate description → minimal fallback) with
PersonalityTrimInfometadata. - Integrated trimming metadata into
SystemPrompt, added prompt-builder controls for enabling trimming and overriding the token cap, and prevented redundant trimming during section re-renders. - Introduced
ENGINEsettings namespace + definitions, new observability constant, and a WS event type; added comprehensive unit tests and updated docs.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/settings/test_engine_settings.py | Validates ENGINE namespace settings registration and constraints. |
| tests/unit/engine/test_prompt.py | Updates expectations for build_core_context() now returning (ctx, trim_info). |
| tests/unit/engine/test_personality_trimming.py | Adds unit + integration tests for token estimation, tiered trimming, logging, overrides, and WS enum. |
| src/synthorg/settings/enums.py | Adds SettingNamespace.ENGINE. |
| src/synthorg/settings/definitions/engine.py | Registers 3 engine settings for personality trimming behavior. |
| src/synthorg/settings/definitions/init.py | Ensures engine definitions module is imported/registered. |
| src/synthorg/observability/events/prompt.py | Adds PROMPT_PERSONALITY_TRIMMED event constant. |
| src/synthorg/engine/prompt.py | Plumbs trimming controls/metadata through prompt rendering and result model. |
| src/synthorg/engine/prompt_profiles.py | Updates max_personality_tokens docstring to reflect active enforcement. |
| src/synthorg/engine/agent_engine.py | Logs trimming occurrence at engine level with agent context. |
| src/synthorg/engine/_prompt_helpers.py | Implements token estimation + progressive trimming + PersonalityTrimInfo; refactors autonomy formatting; changes build_core_context return type. |
| src/synthorg/api/ws_models.py | Adds WsEventType.PERSONALITY_TRIMMED. |
| docs/design/engine.md | Documents profile token caps, trimming tiers, and new invariants/logging. |
| CLAUDE.md | Updates package structure notes to mention personality trimming. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| estimator = DefaultTokenEstimator() | ||
| max_tokens = profile.max_personality_tokens | ||
| mode: PersonalityMode = ctx["personality_mode"] | ||
| before = _estimate_personality_tokens(ctx, mode, estimator) |
There was a problem hiding this comment.
Personality trimming always instantiates and uses DefaultTokenEstimator here. If a caller supplies a custom token_estimator to build_system_prompt (e.g., a tokenizer-backed estimator), the personality “hard cap” can become inconsistent with the estimator used for the overall prompt, and trimming may under/over-trim. Consider threading a PromptTokenEstimator into build_core_context/_trim_personality/_estimate_personality_tokens and using the same estimator instance that prompt.py uses for estimation.
| ``"..."`` as a suffix. Returns an empty string when *max_chars* | ||
| is too small to hold any meaningful content. | ||
|
|
||
| Args: | ||
| description: Original description text. | ||
| max_chars: Maximum character count for the result. | ||
|
|
||
| Returns: | ||
| Truncated description or empty string. |
There was a problem hiding this comment.
_truncate_description() returns "..." when the input description is empty (as implemented/tested), but the docstring implies the function returns either a truncated description or an empty string. Either adjust the implementation to return "" for empty input, or update the docstring to document the empty-input behavior explicitly so callers don’t accidentally render an ellipsis-only description.
| ``"..."`` as a suffix. Returns an empty string when *max_chars* | |
| is too small to hold any meaningful content. | |
| Args: | |
| description: Original description text. | |
| max_chars: Maximum character count for the result. | |
| Returns: | |
| Truncated description or empty string. | |
| ``"..."`` as a suffix. Returns an empty string only when | |
| *max_chars* is too small to hold at least one character plus the | |
| ellipsis. If *description* is empty and there is sufficient room, | |
| the result is ``"..."``. | |
| Args: | |
| description: Original description text. | |
| max_chars: Maximum character count for the result. | |
| Returns: | |
| Truncated description with an ellipsis suffix, ``"..."`` for an | |
| empty description when space permits, or an empty string when | |
| *max_chars* is too small. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1059 +/- ##
==========================================
+ Coverage 90.74% 90.76% +0.01%
==========================================
Files 710 711 +1
Lines 40396 40521 +125
Branches 4035 4056 +21
==========================================
+ Hits 36659 36780 +121
- Misses 3038 3040 +2
- Partials 699 701 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
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/agent_engine.py (1)
862-872:⚠️ Potential issue | 🟠 MajorRuntime trimming controls are still not applied in engine execution path.
At Line 865,
build_system_prompt(...)is called withoutpersonality_trimming_enabled/max_personality_tokens_override, and Lines 862-864 leave this as TODO. That makes the new ENGINE settings ineffective for normalAgentEngine.run()prompt builds.Suggested fix direction
- system_prompt = build_system_prompt( + system_prompt = build_system_prompt( agent=identity, task=task, available_tools=tool_defs, effective_autonomy=effective_autonomy, currency=cur_code, model_tier=identity.model.model_tier, + personality_trimming_enabled=resolved_engine_settings.personality_trimming_enabled, + max_personality_tokens_override=resolved_engine_settings.personality_max_tokens_override, )Pass values resolved from
ConfigResolver(or equivalent injected settings source) before merge.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/agent_engine.py` around lines 862 - 872, The system prompt is built without applying runtime trimming settings so personality_trimming_enabled and personality_max_tokens_override are ignored; update the AgentEngine.run path to fetch the resolved settings (e.g., via ConfigResolver or injected settings object) and pass them into build_system_prompt by adding the personality_trimming_enabled and personality_max_tokens_override arguments (use the resolved boolean and token limit variables) when calling build_system_prompt with agent=identity, task=task, available_tools=tool_defs, effective_autonomy=effective_autonomy, currency=cur_code, model_tier=identity.model.model_tier so the engine honors the runtime trimming controls.
🤖 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/_prompt_helpers.py`:
- Around line 196-221: The function _truncate_description currently appends an
ellipsis even when the input description is empty; add an early check at the top
of _truncate_description to return an empty string for empty or whitespace-only
description (e.g., if not description.strip(): return "") before computing
ellipsis, budget, truncated, etc., so that ellipsis is only added when there is
actual content to truncate.
In `@src/synthorg/engine/prompt_profiles.py`:
- Around line 41-44: The docstring for the max_personality_tokens field is
inconsistent (it calls the value a "Hard cap" earlier but still says "Soft
limit" around the current text); update the wording so all occurrences
consistently state that max_personality_tokens is a hard cap enforced by
build_core_context via progressive trimming (drop enums, truncate description,
fallback to minimal mode). Search for max_personality_tokens and the surrounding
lines (around the current 58-61 region) in the class docstring and replace any
"Soft limit" phrasing with a clear "Hard cap" description and mention
build_core_context as the enforcing function.
---
Outside diff comments:
In `@src/synthorg/engine/agent_engine.py`:
- Around line 862-872: The system prompt is built without applying runtime
trimming settings so personality_trimming_enabled and
personality_max_tokens_override are ignored; update the AgentEngine.run path to
fetch the resolved settings (e.g., via ConfigResolver or injected settings
object) and pass them into build_system_prompt by adding the
personality_trimming_enabled and personality_max_tokens_override arguments (use
the resolved boolean and token limit variables) when calling build_system_prompt
with agent=identity, task=task, available_tools=tool_defs,
effective_autonomy=effective_autonomy, currency=cur_code,
model_tier=identity.model.model_tier so the engine honors the runtime trimming
controls.
🪄 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: 664bc135-819d-4028-be15-645c0526956f
📒 Files selected for processing (14)
CLAUDE.mddocs/design/engine.mdsrc/synthorg/api/ws_models.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/settings/enums.pytests/unit/engine/test_personality_trimming.pytests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.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: Agent
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations— Python 3.14 has PEP 649
PEP 758 except syntax: useexcept A, B:(no parentheses) — ruff enforces this on Python 3.14
Type hints: all public functions, mypy strict mode
Docstrings: Google style, required on public classes/functions (enforced by ruff D rules)
Files:
src/synthorg/settings/enums.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/api/ws_models.pytests/unit/settings/test_engine_settings.pysrc/synthorg/engine/prompt_profiles.pytests/unit/engine/test_prompt.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pytests/unit/engine/test_personality_trimming.pysrc/synthorg/engine/_prompt_helpers.py
src/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.py: Immutability: create new objects, never mutate existing ones. For non-Pydantic internal collections (registries, BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
Async concurrency: preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (e.g., multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Line length: 88 characters (ruff)
Files:
src/synthorg/settings/enums.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/api/ws_models.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.py
⚙️ CodeRabbit configuration file
This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.
Files:
src/synthorg/settings/enums.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/api/ws_models.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Config vs runtime state: frozen Pydantic models for config/identity; separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Models: Pydantic v2 (BaseModel,model_validator,computed_field,ConfigDict). Useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields at validation time.
Models: use@computed_fieldfor derived values instead of storing + validating redundant fields (e.g.,TokenUsage.total_tokens)
Models: useNotBlankStr(fromcore.types) for all identifier/name fields — including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants — instead of manual whitespace validators
Functions: < 50 lines, files < 800 lines
Errors: handle explicitly, never silently swallow
Validate: at system boundaries (user input, external APIs, config files)
Every module with business logic MUST have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__)
Never useimport logging/logging.getLogger()/print()in application code (exception:observability/setup.py,observability/sinks.py,observability/syslog_handler.py, andobservability/http_handler.pymay use stdlibloggingandprint(..., file=sys.stderr)for handler construction, bootstrap, and error reporting code)
Variable name: alwayslogger(not_logger, notlog)
Event names: always use constants from the domain-specific module undersynthorg.observability.events(e.g., API_REQUEST_STARTED from events.api, TOOL_INVOKE_START from events.tool). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
Structured kwargs: alwayslogger.info(EVENT, key=value)— neverlogger.info("msg %s", val)
All error paths must log at WARNING or ERROR with context before raising
All state transitions must log at INFO
DEBUG for object crea...
Files:
src/synthorg/settings/enums.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/api/ws_models.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Test markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow
Async:asyncio_mode = "auto"— no manual@pytest.mark.asyncioneeded
Timeout: 30 seconds per test (global inpyproject.toml— do not add per-filepytest.mark.timeout(30)markers; non-default overrides liketimeout(60)are allowed)
Parametrize: Prefer@pytest.mark.parametrizefor testing similar cases
Tests must usetest-provider,test-small-001, etc. (vendor-agnostic naming)
Property-based testing: Python uses Hypothesis (@given+@settings). Hypothesis profiles configured intests/conftest.py:ci(deterministic,max_examples=10+derandomize=True),dev(1000 examples),fuzz(10,000 examples, no deadline),extreme(500,000 examples, no deadline).
Flaky tests: NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep()to make them deterministic instead of widening timing margins.
For tasks that must block indefinitely until cancelled (e.g. simulating a slow provider or stubborn coroutine), useasyncio.Event().wait()instead ofasyncio.sleep(large_number)— it is cancellation-safe and carries no timing assumptions.
Files:
tests/unit/settings/test_engine_settings.pytests/unit/engine/test_prompt.pytests/unit/engine/test_personality_trimming.py
⚙️ CodeRabbit configuration file
Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare
@settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which@given() honors automatically.
Files:
tests/unit/settings/test_engine_settings.pytests/unit/engine/test_prompt.pytests/unit/engine/test_personality_trimming.py
🧠 Learnings (30)
📚 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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)
Applied to files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pytests/unit/settings/test_engine_settings.pysrc/synthorg/settings/definitions/engine.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/settings/**/*.py : Settings use runtime-editable persistence with precedence: DB > env > YAML > code defaults. 8 namespaces with Fernet encryption for sensitive values.
Applied to files:
src/synthorg/settings/enums.pytests/unit/settings/test_engine_settings.pysrc/synthorg/settings/definitions/engine.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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)
Applied to files:
src/synthorg/settings/definitions/__init__.pyCLAUDE.mdsrc/synthorg/engine/agent_engine.pysrc/synthorg/settings/definitions/engine.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/settings/definitions/__init__.pyCLAUDE.md
📚 Learning: 2026-04-02T07:18:02.381Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T07:18:02.381Z
Learning: Applies to {pyproject.toml,src/synthorg/__init__.py} : Update version in `pyproject.toml` (`[tool.commitizen].version`) and `src/synthorg/__init__.py` (`__version__`)
Applied to files:
src/synthorg/settings/definitions/__init__.py
📚 Learning: 2026-04-02T07:18:02.381Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T07:18:02.381Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`, `TOOL_INVOKE_START` from `events.tool`); import directly from the domain module
Applied to files:
src/synthorg/settings/definitions/__init__.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: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...
Applied to files:
src/synthorg/settings/definitions/__init__.pyCLAUDE.mdsrc/synthorg/engine/agent_engine.pydocs/design/engine.md
📚 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/observability/**/*.py : Observability package (observability/): structured logging, correlation tracking, log sinks; event constants organized by domain under observability/events/ (e.g., events.api, events.tool, events.git, events.context_budget, events.backup)
Applied to files:
src/synthorg/settings/definitions/__init__.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget tracking includes pre-flight/in-flight checks, auto-downgrade, billing periods, cost tiers, quota/subscription. CFO includes anomaly detection, efficiency analysis, downgrade recommendations.
Applied to files:
src/synthorg/settings/definitions/__init__.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: Budget: Cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError).
Applied to files:
src/synthorg/settings/definitions/__init__.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/communication/**/*.py : Communication package (communication/): message bus, dispatcher, messenger, channels, delegation, loop prevention, conflict resolution; meeting/ subpackage for meeting protocol (round-robin, position papers, structured phases), scheduler (frequency, participant resolver), orchestrator
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/hr/**/*.py : HR engine must provide: hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, trend detection), promotion/demotion
Applied to files:
CLAUDE.md
📚 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: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.
Applied to files:
CLAUDE.md
📚 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 docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/hr/**/*.py : HR package (hr/): hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, LLM calibration, collaboration overrides, trend detection), promotion/demotion (criteria evaluation, approval strategies, model mapping)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/engine/coordination/**/*.py : Task coordination uses multi-agent pipeline with 4 dispatchers (SAS/centralized/decentralized/context-dependent), wave execution, and workspace lifecycle integration.
Applied to files:
CLAUDE.md
📚 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 : Use Pydantic v2 BaseModel, model_validator, computed_field, ConfigDict.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-15T18:42:17.990Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:42:17.990Z
Learning: Applies to src/synthorg/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.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 : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. For derived values use `computed_field` instead of storing + validating redundant fields. Use `NotBlankStr` (from `core.types`) for all identifier/name fields — including optional (`NotBlankStr | None`) and tuple (`tuple[NotBlankStr, ...]`) variants — instead of manual whitespace validators.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget package (budget/): cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError)
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-03T21:18:15.006Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-03T21:18:15.006Z
Learning: Applies to src/synthorg/**/*.py : Models: Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields at validation time.
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-02T11:49:21.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T11:49:21.202Z
Learning: Applies to **/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`) with `allow_inf_nan=False` in all `ConfigDict` declarations
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-01T15:36:39.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T15:36:39.993Z
Learning: Applies to src/**/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields at validation time
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. Use `computed_field` for derived values instead of storing redundant fields. Use `NotBlankStr` for all identifier/name fields.
Applied to files:
src/synthorg/engine/prompt.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 : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.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: Settings: Runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge, ConfigResolver (typed composed reads for controllers), validation, registry, change notifications via message bus. Per-namespace setting definitions in definitions/ submodule (api, company, providers, memory, budget, security, coordination, observability, backup).
Applied to files:
src/synthorg/settings/definitions/engine.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/_prompt_helpers.py
📚 Learning: 2026-04-01T09:09:43.948Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T09:09:43.948Z
Learning: Applies to **/*.py : Use `copy.deepcopy()` at construction and `MappingProxyType` wrapping for read-only enforcement in non-Pydantic internal collections (registries, BaseTool)
Applied to files:
src/synthorg/engine/_prompt_helpers.py
🔇 Additional comments (27)
src/synthorg/settings/enums.py (1)
22-22: ENGINE namespace enum addition is correct.This aligns with the new settings namespace wiring and follows existing enum conventions.
CLAUDE.md (1)
99-99: Documentation update is aligned with the feature.The engine package summary now accurately mentions personality trimming support.
src/synthorg/observability/events/prompt.py (1)
17-17: New prompt event constant looks good.
PROMPT_PERSONALITY_TRIMMEDmatches the existing observability event convention.src/synthorg/api/ws_models.py (1)
63-64: WebSocket event type addition is clean.
PERSONALITY_TRIMMEDfits the existing event taxonomy and enum structure.src/synthorg/settings/definitions/__init__.py (1)
13-13: Engine settings definitions are wired correctly at package level.Adding both the import and
__all__export keeps registration and public module exposure consistent.Also applies to: 26-26
tests/unit/engine/test_prompt.py (1)
1221-1224: Test update correctly validates the new return contract.Unpacking
(ctx, trim_info)plus assertingtrim_info is Noneis the right non-trimming baseline check.Also applies to: 1229-1229
tests/unit/settings/test_engine_settings.py (1)
1-53: LGTM!Clean and comprehensive test coverage for the ENGINE namespace settings. Tests properly verify namespace registration, individual setting types/defaults/constraints, and total setting count. Appropriate use of
@pytest.mark.unitmarker.src/synthorg/settings/definitions/engine.py (1)
1-47: LGTM!Settings definitions follow established patterns with appropriate types, defaults, and constraints. The descriptions clearly explain behavior (especially the
0 = use profile defaultssemantic for the override setting).src/synthorg/engine/prompt.py (4)
85-118: LGTM!
SystemPromptmodel correctly adds thepersonality_trim_infofield with appropriate docstring update. The model maintains frozen semantics andallow_inf_nan=Falseas required.
183-189: LGTM!Override logic correctly guards against non-positive values before applying
model_copy(update=...), ensuring0and negative values fall back to profile defaults as documented.
490-542: LGTM!
_trim_sectionscorrectly passestrimming_enabled=Falseon section-level re-renders to avoid redundant personality trimming work. This is a good optimization since personality trimming already ran on the initial render.
573-636: LGTM!
_render_with_trimmingcorrectly threads thetrimming_enabledflag through to_render_and_estimateand properly captures and propagatestrim_infoto the finalSystemPromptvia_build_prompt_result.docs/design/engine.md (2)
711-715: LGTM!Updated profile table correctly documents the
max_personality_tokensbudget for each tier, aligning with the implementation values.
717-759: LGTM!The new "Personality Trimming" section accurately documents the three-tier progressive trimming strategy, the
PersonalityTrimInfometadata fields, the ENGINE namespace runtime controls, and the observability event. This aligns well with the implementation in_prompt_helpers.py.tests/unit/engine/test_personality_trimming.py (8)
1-103: LGTM!Well-structured test fixtures with clear helper functions. The
_verbose_agent()factory correctly creates an agent at the 500-char description limit to test trimming behavior, and_build_ctx()properly disables trimming for manual trimming tests.
108-165: LGTM!Token estimation tests correctly verify the relative ordering of token counts across modes (
full > condensed > minimal) and that empty descriptions reduce estimates. Good coverage of the estimation logic.
170-292: LGTM!Comprehensive trimming tests covering all tiers, edge cases (empty description, already minimal), and validation of
PersonalityTrimInfofields. The tier transition logic tests are particularly well-designed.
297-329: LGTM!Good use of
structlog.testing.capture_logs()to verify logging behavior. Tests correctly assert thatPROMPT_PERSONALITY_TRIMMEDis logged exactly once when trimming occurs and not at all when within budget.
393-488: LGTM!Excellent integration tests via
build_system_promptcovering the full flow includingpersonality_trimming_enabled,max_personality_tokens_overridesemantics (including zero and negative values), andpersonality_trim_infopropagation toSystemPrompt.
541-603: LGTM!Thorough Pydantic validation tests for
PersonalityTrimInfoincluding cross-field invariants (before_tokens > max_tokens,after_tokens <= before_tokens) and thebudget_metcomputed field. Good coverage of rejection cases.
663-668: LGTM!Good verification that
WsEventType.PERSONALITY_TRIMMEDexists with the expected value, ensuring the WebSocket event infrastructure is properly wired.
525-528: Test correctly reflects implementation behavior.The test accurately verifies that
_truncate_description("", 100)returns"...". The implementation is designed to always append the ellipsis suffix to the result, and the test properly documents this edge case behavior. Withmax_chars=100anddescription="", the function budgets 97 characters for content, finds no content to truncate, and appends"..."to the empty string, yielding"...". The test is correctly marked with@pytest.mark.unitand is compliant with all testing guidelines.src/synthorg/engine/_prompt_helpers.py (5)
39-81: LGTM!
PersonalityTrimInfois well-designed with properConfigDict(frozen=True, allow_inf_nan=False), cross-field validation ensuring trimming invariants, and@computed_fieldfor the derivedbudget_metproperty. The docstring clearly explains tier 3 best-effort semantics.
146-193: LGTM!Token estimation correctly mirrors the Jinja2 template rendering logic for each personality mode, ensuring accurate budget calculations. The assembly of markdown-formatted text before estimation is a clean approach.
264-316: LGTM!Progressive trimming logic is well-structured with clear tier progression. The early return when within budget (line 290-291) avoids unnecessary work, and each tier helper returns
Noneto signal budget not met, enabling clean fallthrough to the next tier.
319-342: LGTM!
_make_trim_infoprovides a clean factory that handles both logging (at DEBUG level) and model construction. The docstring correctly notes that engine-layer logging at INFO happens elsewhere.
345-408: LGTM!
build_core_contextcorrectly integrates trimming into the context-building flow. Thetrimming_enabledflag provides proper control, and the tuple return type cleanly separates the context dict from optional trim metadata. Good use of_format_autonomyextraction for readability.
There was a problem hiding this comment.
Actionable comments posted: 4
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/prompt.py (1)
500-513:⚠️ Potential issue | 🟠 Major
_trim_sections()ignorespersonality_trimming_enabledon re-renders.If a caller sets
personality_trimming_enabled=Falseand the first render still exceedsmax_tokens, these re-renders call_render_and_estimate()without forwarding the flag. That falls back toTrue, so the final prompt can still have a trimmed personality, and because the re-renderedtrim_infois discarded,SystemPrompt.personality_trim_infocan remainNone. This breaks the new API contract on themax_tokenspath.Suggested fix
def _trim_sections( # noqa: PLR0913 *, @@ effective_autonomy: EffectiveAutonomy | None = None, context_budget: str | None = None, currency: str = DEFAULT_CURRENCY, profile: PromptProfile | None = None, + trimming_enabled: bool = True, ) -> tuple[ str, int, Task | None, Company | None, tuple[str, ...], + PersonalityTrimInfo | None, ]: @@ trimmed_sections: list[str] = [] + trim_info: PersonalityTrimInfo | None = None for section in _TRIMMABLE_SECTIONS: - content, estimated, _ = _render_and_estimate( + content, estimated, trim_info = _render_and_estimate( template_str, agent, role, @@ effective_autonomy=effective_autonomy, context_budget=context_budget, currency=currency, profile=profile, + trimming_enabled=trimming_enabled, ) @@ - content, estimated, _ = _render_and_estimate( + content, estimated, trim_info = _render_and_estimate( template_str, agent, role, @@ effective_autonomy=effective_autonomy, context_budget=context_budget, currency=currency, profile=profile, + trimming_enabled=trimming_enabled, ) _log_trim_results(agent, max_tokens, estimated, trimmed_sections) - return content, estimated, task, company, org_policies + return content, estimated, task, company, org_policies, trim_info @@ - content, estimated, task, company, org_policies = _trim_sections( + content, estimated, task, company, org_policies, trim_info = _trim_sections( template_str=template_str, agent=agent, role=role, @@ effective_autonomy=effective_autonomy, context_budget=context_budget_indicator, currency=currency, profile=profile, + trimming_enabled=trimming_enabled, )Also applies to: 533-546, 595-640
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/prompt.py` around lines 500 - 513, The bug is that _trim_sections() can trigger re-renders which call _render_and_estimate() without propagating the personality_trimming_enabled flag, causing re-renders to default to trimming and discarding trim_info; update every call site that re-invokes _render_and_estimate (including the shown call and the other instances around the 533-546 and 595-640 regions) to pass the personality_trimming_enabled parameter through unchanged, and make sure the returned trim_info from _render_and_estimate is captured and assigned to SystemPrompt.personality_trim_info (or otherwise preserved) so the final prompt honors the original personality_trimming_enabled choice.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/design/engine.md`:
- Around line 711-715: The table row for the "standard" / medium profile
incorrectly lists "Bullet list" for Acceptance Criteria; update that cell to
"Nested list" to match the actual behavior controlled by the _STANDARD_PROFILE
flag (which keeps simplify_acceptance_criteria=False). Locate the "standard"
profile row in the table and change the Acceptance Criteria column to "Nested
list" so the docs reflect _STANDARD_PROFILE's nested-list output.
In `@src/synthorg/engine/_prompt_helpers.py`:
- Around line 42-45: The validator must reject over-budget states for trim_tier
1 and 2: add a guard in the personality-trimming validation (using the existing
symbols max_personality_tokens, after_tokens, and trim_tier) that raises/returns
an error when trim_tier is 1 or 2 and after_tokens > max_personality_tokens;
leave trim_tier==3 as best-effort. Apply the same check in the other validator
block that handles the communication_style/personality fallback (the section
referenced around lines 66-74) so public metadata cannot represent states the
trimming algorithm should never produce.
- Around line 151-157: The personality token estimator currently omits the
section heading and the template's static wrapper, making after_tokens and
budget_met optimistic; update the helper in _prompt_helpers.py so it either (a)
fully renders the Jinja2 template (including heading and static wrapper) and
passes that rendered string into the tokenizer/estimator, or (b) explicitly adds
the token cost of the known static wrapper and heading to after_tokens before
comparing to max_tokens/budget_met; apply the same fix to the other estimator
usage noted around the lines referenced (the other occurrence at the same
module), and ensure you update references to after_tokens, max_tokens and
budget_met accordingly so the final check reflects the whole rendered prompt.
In `@src/synthorg/engine/agent_engine.py`:
- Around line 889-900: The PROMPT_PERSONALITY_TRIMMED log emitted when
system_prompt.personality_trim_info is present is missing task context; update
the logger.info call inside the if block (where
system_prompt.personality_trim_info is assigned to ti) to include task_id as an
additional structured field alongside agent_id, agent_name (identity.name),
before_tokens, after_tokens, max_tokens, trim_tier, and budget_met so the trim
event can be correlated with the current task.
---
Outside diff comments:
In `@src/synthorg/engine/prompt.py`:
- Around line 500-513: The bug is that _trim_sections() can trigger re-renders
which call _render_and_estimate() without propagating the
personality_trimming_enabled flag, causing re-renders to default to trimming and
discarding trim_info; update every call site that re-invokes
_render_and_estimate (including the shown call and the other instances around
the 533-546 and 595-640 regions) to pass the personality_trimming_enabled
parameter through unchanged, and make sure the returned trim_info from
_render_and_estimate is captured and assigned to
SystemPrompt.personality_trim_info (or otherwise preserved) so the final prompt
honors the original personality_trimming_enabled choice.
🪄 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: b322c912-560c-4d1a-81cc-858785b87e94
📒 Files selected for processing (10)
docs/design/engine.mdsrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/settings/definitions/engine.pytests/unit/engine/test_personality_trimming.pytests/unit/settings/test_engine_settings.pyweb/src/api/types.tsweb/src/utils/constants.ts
📜 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). (7)
- GitHub Check: Dashboard Test
- 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 (7)
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx}: Use Tailwind semantic classes (text-foreground,bg-card,text-accent, etc.) or CSS variables (var(--so-*)) for colors. NEVER hardcode hex values or rgba() in.tsx/.tsfiles
Usefont-sansorfont-monofor typography (maps to Geist tokens). NEVER setfontFamilydirectly in styles
Use density-aware spacing tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing
Use token variables (var(--so-shadow-card-hover),border-border,border-bright) for shadows and borders
Do NOT usergba()with hardcoded values -- use design token variables
Do NOT hardcode Framer Motion transition durations -- use@/lib/motionpresets
Use/// <reference types="vite/client" />to enable side-effect imports for CSS in Storybook 10 with TypeScript 6
Ensure all TypeScript code passes type checking vianpm --prefix web run type-check
Bundle size must be auditable vianpm --prefix web run analyze(generates stats.html treemap)
Achieve Lighthouse performance audit target of 90+ vianpm --prefix web run lighthouse
web/src/**/*.{ts,tsx}: ALWAYS reuse existing components fromweb/src/components/ui/before creating new ones
Web Dashboard Design System (MANDATORY): Seeweb/CLAUDE.mdfor the full component inventory, design token rules, and post-training references (TS6, Storybook 10).
Files:
web/src/api/types.tsweb/src/utils/constants.ts
web/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
Run ESLint with zero warnings enforced via
npm --prefix web run lintLine length: 88 characters (ruff) for JavaScript/TypeScript files
Files:
web/src/api/types.tsweb/src/utils/constants.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and
@/lib/motionpresets
Files:
web/src/api/types.tsweb/src/utils/constants.ts
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations— Python 3.14 has PEP 649
PEP 758 except syntax: useexcept A, B:(no parentheses) — ruff enforces this on Python 3.14
Type hints: all public functions, mypy strict mode
Docstrings: Google style, required on public classes/functions (enforced by ruff D rules)
Files:
src/synthorg/engine/prompt_profiles.pytests/unit/settings/test_engine_settings.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.pytests/unit/engine/test_personality_trimming.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.py
src/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.py: Immutability: create new objects, never mutate existing ones. For non-Pydantic internal collections (registries, BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
Async concurrency: preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (e.g., multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Line length: 88 characters (ruff)
Files:
src/synthorg/engine/prompt_profiles.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.py
⚙️ CodeRabbit configuration file
This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.
Files:
src/synthorg/engine/prompt_profiles.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Config vs runtime state: frozen Pydantic models for config/identity; separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Models: Pydantic v2 (BaseModel,model_validator,computed_field,ConfigDict). Useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields at validation time.
Models: use@computed_fieldfor derived values instead of storing + validating redundant fields (e.g.,TokenUsage.total_tokens)
Models: useNotBlankStr(fromcore.types) for all identifier/name fields — including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants — instead of manual whitespace validators
Functions: < 50 lines, files < 800 lines
Errors: handle explicitly, never silently swallow
Validate: at system boundaries (user input, external APIs, config files)
Every module with business logic MUST have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__)
Never useimport logging/logging.getLogger()/print()in application code (exception:observability/setup.py,observability/sinks.py,observability/syslog_handler.py, andobservability/http_handler.pymay use stdlibloggingandprint(..., file=sys.stderr)for handler construction, bootstrap, and error reporting code)
Variable name: alwayslogger(not_logger, notlog)
Event names: always use constants from the domain-specific module undersynthorg.observability.events(e.g., API_REQUEST_STARTED from events.api, TOOL_INVOKE_START from events.tool). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
Structured kwargs: alwayslogger.info(EVENT, key=value)— neverlogger.info("msg %s", val)
All error paths must log at WARNING or ERROR with context before raising
All state transitions must log at INFO
DEBUG for object crea...
Files:
src/synthorg/engine/prompt_profiles.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Test markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow
Async:asyncio_mode = "auto"— no manual@pytest.mark.asyncioneeded
Timeout: 30 seconds per test (global inpyproject.toml— do not add per-filepytest.mark.timeout(30)markers; non-default overrides liketimeout(60)are allowed)
Parametrize: Prefer@pytest.mark.parametrizefor testing similar cases
Tests must usetest-provider,test-small-001, etc. (vendor-agnostic naming)
Property-based testing: Python uses Hypothesis (@given+@settings). Hypothesis profiles configured intests/conftest.py:ci(deterministic,max_examples=10+derandomize=True),dev(1000 examples),fuzz(10,000 examples, no deadline),extreme(500,000 examples, no deadline).
Flaky tests: NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep()to make them deterministic instead of widening timing margins.
For tasks that must block indefinitely until cancelled (e.g. simulating a slow provider or stubborn coroutine), useasyncio.Event().wait()instead ofasyncio.sleep(large_number)— it is cancellation-safe and carries no timing assumptions.
Files:
tests/unit/settings/test_engine_settings.pytests/unit/engine/test_personality_trimming.py
⚙️ CodeRabbit configuration file
Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare
@settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which@given() honors automatically.
Files:
tests/unit/settings/test_engine_settings.pytests/unit/engine/test_personality_trimming.py
🧠 Learnings (27)
📚 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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)
Applied to files:
tests/unit/settings/test_engine_settings.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.py
📚 Learning: 2026-04-03T21:18:15.006Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-03T21:18:15.006Z
Learning: Applies to tests/**/*.py : Property-based testing: Python uses Hypothesis (`given` + `settings`). Hypothesis profiles configured in `tests/conftest.py`: `ci` (deterministic, `max_examples=10` + `derandomize=True`), `dev` (1000 examples), `fuzz` (10,000 examples, no deadline), `extreme` (500,000 examples, no deadline).
Applied to files:
tests/unit/settings/test_engine_settings.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/settings/**/*.py : Settings use runtime-editable persistence with precedence: DB > env > YAML > code defaults. 8 namespaces with Fernet encryption for sensitive values.
Applied to files:
tests/unit/settings/test_engine_settings.pysrc/synthorg/settings/definitions/engine.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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)
Applied to files:
src/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/persistence/**/*.py : Persistence uses pluggable PersistenceBackend protocol. SQLite is the initial backend. Settings use SettingsRepository (namespaced settings CRUD).
Applied to files:
src/synthorg/settings/definitions/engine.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: Settings: Runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge, ConfigResolver (typed composed reads for controllers), validation, registry, change notifications via message bus. Per-namespace setting definitions in definitions/ submodule (api, company, providers, memory, budget, security, coordination, observability, backup).
Applied to files:
src/synthorg/settings/definitions/engine.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: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...
Applied to files:
docs/design/engine.md
📚 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/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
Applied to files:
src/synthorg/engine/agent_engine.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 : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-31T21:07:37.469Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.469Z
Learning: Applies to src/synthorg/providers/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-16T19:13:36.562Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:13:36.562Z
Learning: Applies to src/synthorg/providers/**/*.py : RetryConfig and RateLimiterConfig are set per-provider in ProviderConfig.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-04-03T21:18:15.006Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-03T21:18:15.006Z
Learning: Applies to src/synthorg/providers/**/*.py : RetryConfig and RateLimiterConfig are set per-provider in `ProviderConfig`
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.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/security/**/*.py : Security package (security/): 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), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.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 : Use Pydantic v2 BaseModel, model_validator, computed_field, ConfigDict.
Applied to files:
src/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.py
📚 Learning: 2026-03-15T18:42:17.990Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:42:17.990Z
Learning: Applies to src/synthorg/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`
Applied to files:
src/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.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 : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. For derived values use `computed_field` instead of storing + validating redundant fields. Use `NotBlankStr` (from `core.types`) for all identifier/name fields — including optional (`NotBlankStr | None`) and tuple (`tuple[NotBlankStr, ...]`) variants — instead of manual whitespace validators.
Applied to files:
src/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.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/_prompt_helpers.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state
Applied to files:
src/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/prompt.py
📚 Learning: 2026-04-01T09:09:43.948Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T09:09:43.948Z
Learning: Applies to **/*.py : Use `copy.deepcopy()` at construction and `MappingProxyType` wrapping for read-only enforcement in non-Pydantic internal collections (registries, BaseTool)
Applied to files:
src/synthorg/engine/_prompt_helpers.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 : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves
Applied to files:
src/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget package (budget/): cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError)
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-03T21:18:15.006Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-03T21:18:15.006Z
Learning: Applies to src/synthorg/**/*.py : Models: Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields at validation time.
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-02T11:49:21.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T11:49:21.202Z
Learning: Applies to **/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`) with `allow_inf_nan=False` in all `ConfigDict` declarations
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-01T15:36:39.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T15:36:39.993Z
Learning: Applies to src/**/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields at validation time
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. Use `computed_field` for derived values instead of storing redundant fields. Use `NotBlankStr` for all identifier/name fields.
Applied to files:
src/synthorg/engine/prompt.py
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/design/engine.md`:
- Around line 729-733: The docs currently mention
SystemPrompt.personality_trim_info and the PersonalityTrimInfo model plus the
ENGINE runtime flags personality_trimming_enabled and
personality_max_tokens_override but omit the operator-facing notification
toggle; update this section to document the third ENGINE control
personality_trimming_notify, describe its purpose (enables/disables operator
notifications when trimming occurs), expected values/type (e.g., boolean), and
how it interacts with personality_trimming_enabled and
personality_max_tokens_override so operators can fully configure trimming
behavior.
In `@src/synthorg/engine/_prompt_helpers.py`:
- Around line 275-281: The code currently computes max_chars as remaining * 4
which ignores the provided PromptTokenEstimator; instead use the estimator to
convert remaining tokens to characters (e.g., call the provided
PromptTokenEstimator method, such as token_estimator.tokens_to_chars(remaining))
and assign that to max_chars before calling _truncate_description(saved_desc,
max_chars) so tier-2 truncation respects non-default/tokenizer-specific
token->char ratios and avoids dropping to tier-3 unnecessarily.
In `@src/synthorg/engine/agent_engine.py`:
- Around line 867-877: The code currently calls
self._config_resolver.get_bool("engine","personality_trimming_enabled") and
get_int("engine","personality_max_tokens_override") which raise if keys are
absent, so wrap those two calls in a try/except (catch the resolver's
missing-key error or a broad Exception) and only override the local defaults
(trimming_enabled and tokens_override) when the resolver returns values
successfully; if an exception is raised, leave trimming_enabled and
tokens_override as previously initialized (i.e., True / None) so settings
rollout falls back to local defaults instead of crashing.
🪄 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: 75c0ab6a-df0f-4ae1-b9c1-182bc3f604a7
📒 Files selected for processing (4)
docs/design/engine.mdsrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations
Use PEP 758 except syntax:except A, B:(no parentheses) — ruff enforces this on Python 3.14
All public functions must have type hints with mypy strict mode
Public classes and functions must have Google-style docstrings (enforced by ruff D rules)
UseNotBlankStr(fromcore.types) for all identifier/name fields, including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants, instead of manual whitespace validators
For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction andMappingProxyTypewrapping for read-only enforcement
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
In all PydanticConfigDictdeclarations, useallow_inf_nan=Falseto rejectNaN/Infin numeric fields at validation time
Use@computed_fieldfor derived values in Pydantic models instead of storing and validating redundant fields (e.g.,TokenUsage.total_tokens)
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Functions must be less than 50 lines; files must be less than 800 lines
Handle errors explicitly; never silently swallow exceptions
Validate at system boundaries (user input, external APIs, config files)
Every module with business logic must importfrom synthorg.observability import get_loggerand setlogger = get_logger(__name__). Never useimport loggingorlogging.getLogger()in application code.
Always use variable namelogger(not_logger, notlog) for structured logging
Line length must be 88 characters (enforced by ruff)
Files:
src/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Use event name constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api,TOOL_INVOKE_STARTfromevents.tool). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
All logger calls must use structured kwargs:logger.info(EVENT, key=value)— never use string formatting likelogger.info('msg %s', val)
All error paths must log at WARNING or ERROR with context before raising
All state transitions must log at INFO level
Use DEBUG level for object creation, internal flow, and entry/exit of key functions
Never implement retry logic in driver subclasses or calling code — retry is handled automatically byBaseCompletionProvider. SetRetryConfigandRateLimiterConfigper-provider inProviderConfig.
Never use vendor-specific names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, or comments. Use generic names:example-provider,example-large-001,example-medium-001,example-small-001. Vendor names only appear in: (1)docs/design/operations.md, (2).claude/skill files, (3) third-party import paths, (4)src/synthorg/providers/presets.py(user-facing runtime data).
Create new objects instead of mutating existing ones. Immutability is enforced throughout the codebase.
Files:
src/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
src/**/*.py
⚙️ CodeRabbit configuration file
This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.
Files:
src/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
docs/design/**/*.md
📄 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.
Files:
docs/design/engine.md
🧠 Learnings (21)
📚 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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)
Applied to files:
src/synthorg/engine/agent_engine.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: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...
Applied to files:
src/synthorg/engine/agent_engine.pydocs/design/engine.md
📚 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/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
Applied to files:
src/synthorg/engine/agent_engine.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 : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-31T21:07:37.469Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.469Z
Learning: Applies to src/synthorg/providers/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-16T19:13:36.562Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:13:36.562Z
Learning: Applies to src/synthorg/providers/**/*.py : RetryConfig and RateLimiterConfig are set per-provider in ProviderConfig.
Applied to files:
src/synthorg/engine/agent_engine.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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.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/security/**/*.py : Security package (security/): 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), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.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 : Use Pydantic v2 BaseModel, model_validator, computed_field, ConfigDict.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-15T18:42:17.990Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:42:17.990Z
Learning: Applies to src/synthorg/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.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 : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. For derived values use `computed_field` instead of storing + validating redundant fields. Use `NotBlankStr` (from `core.types`) for all identifier/name fields — including optional (`NotBlankStr | None`) and tuple (`tuple[NotBlankStr, ...]`) variants — instead of manual whitespace validators.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget package (budget/): cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError)
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-02T11:49:21.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T11:49:21.202Z
Learning: Applies to **/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`) with `allow_inf_nan=False` in all `ConfigDict` declarations
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-01T15:36:39.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T15:36:39.993Z
Learning: Applies to src/**/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields at validation time
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. Use `computed_field` for derived values instead of storing redundant fields. Use `NotBlankStr` for all identifier/name fields.
Applied to files:
src/synthorg/engine/prompt.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 : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.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/_prompt_helpers.py
📚 Learning: 2026-04-01T09:09:43.948Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T09:09:43.948Z
Learning: Applies to **/*.py : Use `copy.deepcopy()` at construction and `MappingProxyType` wrapping for read-only enforcement in non-Pydantic internal collections (registries, BaseTool)
Applied to files:
src/synthorg/engine/_prompt_helpers.py
🔇 Additional comments (1)
src/synthorg/engine/prompt.py (1)
184-188: Good use ofmodel_copy()for the override.Since
get_prompt_profile()returns shared built-in profiles, copying here keeps the override per-call instead of leaking it across later prompt builds.
| Trimming metadata is attached to `SystemPrompt.personality_trim_info` | ||
| (`PersonalityTrimInfo` model with `before_tokens`, `after_tokens`, | ||
| `max_tokens`, `trim_tier`, and `budget_met` computed field). Runtime | ||
| settings in the `ENGINE` namespace control trimming | ||
| (`personality_trimming_enabled`, `personality_max_tokens_override`). |
There was a problem hiding this comment.
Document the notification toggle here as well.
This section lists only two of the three ENGINE controls introduced by the feature. Without personality_trimming_notify, the operator-facing runtime surface is incomplete.
📝 Suggested doc tweak
- settings in the `ENGINE` namespace control trimming
- (`personality_trimming_enabled`, `personality_max_tokens_override`).
+ settings in the `ENGINE` namespace control trimming and trim notifications
+ (`personality_trimming_enabled`, `personality_trimming_notify`,
+ `personality_max_tokens_override`).📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Trimming metadata is attached to `SystemPrompt.personality_trim_info` | |
| (`PersonalityTrimInfo` model with `before_tokens`, `after_tokens`, | |
| `max_tokens`, `trim_tier`, and `budget_met` computed field). Runtime | |
| settings in the `ENGINE` namespace control trimming | |
| (`personality_trimming_enabled`, `personality_max_tokens_override`). | |
| Trimming metadata is attached to `SystemPrompt.personality_trim_info` | |
| (`PersonalityTrimInfo` model with `before_tokens`, `after_tokens`, | |
| `max_tokens`, `trim_tier`, and `budget_met` computed field). Runtime | |
| settings in the `ENGINE` namespace control trimming and trim notifications | |
| (`personality_trimming_enabled`, `personality_trimming_notify`, | |
| `personality_max_tokens_override`). |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/design/engine.md` around lines 729 - 733, The docs currently mention
SystemPrompt.personality_trim_info and the PersonalityTrimInfo model plus the
ENGINE runtime flags personality_trimming_enabled and
personality_max_tokens_override but omit the operator-facing notification
toggle; update this section to document the third ENGINE control
personality_trimming_notify, describe its purpose (enables/disables operator
notifications when trimming occurs), expected values/type (e.g., boolean), and
how it interacts with personality_trimming_enabled and
personality_max_tokens_override so operators can fully configure trimming
behavior.
| remaining = max_tokens - tokens_without | ||
| if remaining > 0: | ||
| max_chars = remaining * 4 # Inverse of char/4 heuristic. | ||
| ctx["personality_description"] = _truncate_description( | ||
| saved_desc, | ||
| max_chars, | ||
| ) |
There was a problem hiding this comment.
Use the provided estimator for tier-2 truncation.
remaining * 4 hardcodes the default char/4 heuristic even though this path accepts any PromptTokenEstimator. With a real tokenizer or any non-default estimator, tier 2 can miss the budget and drop straight to tier 3 even when a shorter truncated description would fit.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/_prompt_helpers.py` around lines 275 - 281, The code
currently computes max_chars as remaining * 4 which ignores the provided
PromptTokenEstimator; instead use the estimator to convert remaining tokens to
characters (e.g., call the provided PromptTokenEstimator method, such as
token_estimator.tokens_to_chars(remaining)) and assign that to max_chars before
calling _truncate_description(saved_desc, max_chars) so tier-2 truncation
respects non-default/tokenizer-specific token->char ratios and avoids dropping
to tier-3 unnecessarily.
de91d02 to
e09ccda
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/synthorg/engine/prompt.py (2)
500-515:⚠️ Potential issue | 🟡 MinorSection trimming re-applies personality trimming on every pass.
Each
_render_and_estimate()call rebuilds the core context from raw agent data withtrimming_enabled=True, so prompts that also needmax_tokenstrimming can emit multiplePROMPT_PERSONALITY_TRIMMEDhelper logs and repeated tier-3 warnings for a single build. Reuse the first trimmed context, or suppress trim side effects during these re-renders.Also applies to: 535-548
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/prompt.py` around lines 500 - 515, The loop over _TRIMMABLE_SECTIONS repeatedly calls _render_and_estimate with trimming_enabled=True, causing personality trimming side-effects (multiple PROMPT_PERSONALITY_TRIMMED logs and warnings) on each re-render; fix by performing one initial call with trimming_enabled=True to obtain the trimmed core/context (store its content/estimated result) and then reuse that trimmed context for subsequent iterations or call _render_and_estimate with trimming_enabled=False for all later re-renders (update the loop around _render_and_estimate and references to the returned values to use the cached trimmed result instead of re-trimming).
232-247:⚠️ Potential issue | 🟠 MajorSkip personality-cap trimming for custom templates until it is template-aware.
The trim decision is made in
_build_core_context()before Jinja rendering, using the default personality block estimator. Withcustom_template, that can trim fields that never render, or emitpersonality_trim_info/ trim events even when the template has no personality section at all.Suggested fix
- result = _render_with_trimming( + apply_personality_trimming = ( + personality_trimming_enabled and custom_template is None + ) + result = _render_with_trimming( template_str=template_str, agent=agent, role=role, task=task, available_tools=available_tools, @@ effective_autonomy=effective_autonomy, context_budget_indicator=context_budget_indicator, currency=currency, profile=profile, - trimming_enabled=personality_trimming_enabled, + trimming_enabled=apply_personality_trimming, )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/prompt.py` around lines 232 - 247, The current call to _render_with_trimming passes trimming_enabled=personality_trimming_enabled which allows pre-render trimming even for custom_template; change the callsite so that when a custom_template is supplied you disable personality-cap trimming (pass trimming_enabled=False) until the trimming logic becomes template-aware; update the invocation that sets trimming_enabled (in the block calling _render_with_trimming) to use False when custom_template is present to avoid trimming fields that never render and emitting spurious personality_trim_info/trim events.
♻️ Duplicate comments (2)
docs/design/engine.md (1)
729-733:⚠️ Potential issue | 🟡 MinorDocument
personality_trimming_notifyalongside the other ENGINE knobs.This section still lists only the enable and override settings, so the operator-facing runtime surface is incomplete.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/design/engine.md` around lines 729 - 733, The docs currently describe trimming settings (SystemPrompt.personality_trim_info / PersonalityTrimInfo and ENGINE knobs personality_trimming_enabled and personality_max_tokens_override) but omit the runtime flag personality_trimming_notify; update the ENGINE runtime settings list to include personality_trimming_notify with a short description of its purpose and behavior (how/when notifications are emitted and interaction with personality_trimming_enabled), and ensure the mention appears next to personality_trimming_enabled and personality_max_tokens_override so the operator-facing surface is complete.src/synthorg/engine/_prompt_helpers.py (1)
275-281:⚠️ Potential issue | 🟠 MajorTier-2 truncation still hardcodes the char/4 heuristic.
remaining * 4ignores the injectedPromptTokenEstimator, so tokenizer-backed estimators can miss a tier-2 description length that fits and fall straight to tier 3. Pick the truncation point by re-estimating withestimatorinstead of assuming 4 chars/token.Suggested fix
remaining = max_tokens - tokens_without if remaining > 0: - max_chars = remaining * 4 # Inverse of char/4 heuristic. - ctx["personality_description"] = _truncate_description( - saved_desc, - max_chars, - ) + low, high = 0, len(saved_desc) + best = "" + while low <= high: + max_chars = (low + high) // 2 + candidate = _truncate_description(saved_desc, max_chars) + ctx["personality_description"] = candidate + if _estimate_personality_tokens(ctx, mode, estimator) <= max_tokens: + best = candidate + low = max_chars + 1 + else: + high = max_chars - 1 + ctx["personality_description"] = best else: ctx["personality_description"] = ""
🤖 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/agent_engine.py`:
- Around line 879-884: The current except block in agent_engine.py logs a
ConfigResolver fallback as PROMPT_PERSONALITY_TRIMMED; change this to an
appropriate engine/settings error event constant (e.g., ENGINE_SETTINGS_ERROR or
ENGINE_SETTINGS_LOAD_FAILED) so the logger.warning call uses that event instead
of PROMPT_PERSONALITY_TRIMMED, keep the same message ("failed to read ENGINE
settings, using defaults") and exc_info=True to preserve exception details, and
ensure any metrics/telemetry emitted by the logger reflect an error event for
settings load rather than a trim event.
---
Outside diff comments:
In `@src/synthorg/engine/prompt.py`:
- Around line 500-515: The loop over _TRIMMABLE_SECTIONS repeatedly calls
_render_and_estimate with trimming_enabled=True, causing personality trimming
side-effects (multiple PROMPT_PERSONALITY_TRIMMED logs and warnings) on each
re-render; fix by performing one initial call with trimming_enabled=True to
obtain the trimmed core/context (store its content/estimated result) and then
reuse that trimmed context for subsequent iterations or call
_render_and_estimate with trimming_enabled=False for all later re-renders
(update the loop around _render_and_estimate and references to the returned
values to use the cached trimmed result instead of re-trimming).
- Around line 232-247: The current call to _render_with_trimming passes
trimming_enabled=personality_trimming_enabled which allows pre-render trimming
even for custom_template; change the callsite so that when a custom_template is
supplied you disable personality-cap trimming (pass trimming_enabled=False)
until the trimming logic becomes template-aware; update the invocation that sets
trimming_enabled (in the block calling _render_with_trimming) to use False when
custom_template is present to avoid trimming fields that never render and
emitting spurious personality_trim_info/trim events.
---
Duplicate comments:
In `@docs/design/engine.md`:
- Around line 729-733: The docs currently describe trimming settings
(SystemPrompt.personality_trim_info / PersonalityTrimInfo and ENGINE knobs
personality_trimming_enabled and personality_max_tokens_override) but omit the
runtime flag personality_trimming_notify; update the ENGINE runtime settings
list to include personality_trimming_notify with a short description of its
purpose and behavior (how/when notifications are emitted and interaction with
personality_trimming_enabled), and ensure the mention appears next to
personality_trimming_enabled and personality_max_tokens_override so the
operator-facing surface is complete.
🪄 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: a7655ffa-abad-4ebc-803c-5b04d4c28866
📒 Files selected for processing (15)
CLAUDE.mddocs/design/engine.mdsrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/settings/enums.pytests/unit/engine/test_personality_trimming.pytests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pyweb/src/api/types.tsweb/src/utils/constants.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations
Use PEP 758 except syntax:except A, B:(no parentheses) — ruff enforces this on Python 3.14
All public functions must have type hints with mypy strict mode
Public classes and functions must have Google-style docstrings (enforced by ruff D rules)
UseNotBlankStr(fromcore.types) for all identifier/name fields, including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants, instead of manual whitespace validators
For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction andMappingProxyTypewrapping for read-only enforcement
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
In all PydanticConfigDictdeclarations, useallow_inf_nan=Falseto rejectNaN/Infin numeric fields at validation time
Use@computed_fieldfor derived values in Pydantic models instead of storing and validating redundant fields (e.g.,TokenUsage.total_tokens)
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Functions must be less than 50 lines; files must be less than 800 lines
Handle errors explicitly; never silently swallow exceptions
Validate at system boundaries (user input, external APIs, config files)
Every module with business logic must importfrom synthorg.observability import get_loggerand setlogger = get_logger(__name__). Never useimport loggingorlogging.getLogger()in application code.
Always use variable namelogger(not_logger, notlog) for structured logging
Line length must be 88 characters (enforced by ruff)
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pytests/unit/engine/test_prompt.pysrc/synthorg/engine/prompt_profiles.pytests/unit/settings/test_engine_settings.pysrc/synthorg/engine/prompt.pytests/unit/engine/test_personality_trimming.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Use event name constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api,TOOL_INVOKE_STARTfromevents.tool). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
All logger calls must use structured kwargs:logger.info(EVENT, key=value)— never use string formatting likelogger.info('msg %s', val)
All error paths must log at WARNING or ERROR with context before raising
All state transitions must log at INFO level
Use DEBUG level for object creation, internal flow, and entry/exit of key functions
Never implement retry logic in driver subclasses or calling code — retry is handled automatically byBaseCompletionProvider. SetRetryConfigandRateLimiterConfigper-provider inProviderConfig.
Never use vendor-specific names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, or comments. Use generic names:example-provider,example-large-001,example-medium-001,example-small-001. Vendor names only appear in: (1)docs/design/operations.md, (2).claude/skill files, (3) third-party import paths, (4)src/synthorg/providers/presets.py(user-facing runtime data).
Create new objects instead of mutating existing ones. Immutability is enforced throughout the codebase.
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.py
src/**/*.py
⚙️ CodeRabbit configuration file
This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.py
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Always reuse existing components fromweb/src/components/ui/before creating new ones
Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and@/lib/motionpresets
Files:
web/src/api/types.tsweb/src/utils/constants.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: A PostToolUse hook (scripts/check_web_design_system.py) enforces design system rules on every Edit/Write toweb/src/
Use property-based testing with fast-check (fc.assert+fc.property) for React component tests
Files:
web/src/api/types.tsweb/src/utils/constants.ts
web/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx,js,jsx}: Always usecreateLoggerfrom@/lib/logger-- never bareconsole.warn/console.error/console.debugin application code
Variable name for logger: alwayslog(e.g.const log = createLogger('module-name'))
Uselog.debug()(DEV-only, stripped in production),log.warn(),log.error()logging levels
Pass dynamic/untrusted values as separate args to logger (not interpolated into the message string) so they go throughsanitizeArg
Attacker-controlled fields inside structured objects must be wrapped insanitizeForLog()before embedding in log messages
Files:
web/src/api/types.tsweb/src/utils/constants.ts
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{tsx,ts}: Do NOT create complex (>8 line) JSX inside.map()-- extract to a shared component
Colors: use Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)). NEVER hardcode hex values in.tsx/.tsfiles
Typography: usefont-sansorfont-mono(maps to Geist tokens). NEVER setfontFamilydirectly
Spacing: use density-aware tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing
Shadows/Borders: use token variables (var(--so-shadow-card-hover),border-border,border-bright)
Do NOT usergba()with hardcoded values -- use design token variables
Hardcoded hex colors and rgba values inweb/src/files are automatically caught by a PostToolUse hook and must be fixed
Hardcoded font-family declarations inweb/src/files are automatically caught by a PostToolUse hook and must be fixed
Hardcoded Framer Motion transition durations (should use@/lib/motionpresets) are automatically caught by a PostToolUse hook and must be fixed
Duplicate patterns that should use existing shared components inweb/src/are automatically caught by a PostToolUse hook and must be fixed
Complex.map()blocks that should be extracted to components inweb/src/are automatically caught by a PostToolUse hook and must be fixed
CSS side-effect imports need type declarations (Vite's/// <reference types="vite/client" />covers this) asnoUncheckedSideEffectImportsdefaults to true in TypeScript 6
Files:
web/src/api/types.tsweb/src/utils/constants.ts
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Mark all tests with pytest markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e, or@pytest.mark.slow
Maintain 80% minimum test coverage (enforced in CI) withpytest --cov=synthorg --cov-fail-under=80
Useasyncio_mode = 'auto'(configured in pyproject.toml) — no manual@pytest.mark.asyncioneeded
Tests have a global 30-second timeout per test (configured in pyproject.toml). Non-default overrides liketimeout(60)are allowed.
Always include-n 8when running pytest locally for parallelism via pytest-xdist. Never run tests sequentially.
Prefer@pytest.mark.parametrizefor testing similar cases instead of multiple test functions
Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, or tests. Use generic names:example-provider,example-large-001,example-medium-001,example-small-001,large/medium/smallas aliases, ortest-provider,test-small-001in tests.
Never skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep()instead of widening timing margins. For indefinite blocking, useasyncio.Event().wait()instead ofasyncio.sleep(large_number).
Files:
tests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pytests/unit/engine/test_personality_trimming.py
⚙️ CodeRabbit configuration file
Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare
@settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which@given() honors automatically.
Files:
tests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pytests/unit/engine/test_personality_trimming.py
docs/design/**/*.md
📄 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.
Files:
docs/design/engine.md
🧠 Learnings (35)
📚 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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)
Applied to files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pytests/unit/settings/test_engine_settings.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/settings/**/*.py : Settings use runtime-editable persistence with precedence: DB > env > YAML > code defaults. 8 namespaces with Fernet encryption for sensitive values.
Applied to files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/engine.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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)
Applied to files:
src/synthorg/settings/definitions/__init__.pyCLAUDE.mdsrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.py
📚 Learning: 2026-04-02T07:18:02.381Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T07:18:02.381Z
Learning: Applies to {pyproject.toml,src/synthorg/__init__.py} : Update version in `pyproject.toml` (`[tool.commitizen].version`) and `src/synthorg/__init__.py` (`__version__`)
Applied to files:
src/synthorg/settings/definitions/__init__.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/settings/definitions/__init__.pyCLAUDE.mdsrc/synthorg/engine/agent_engine.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: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...
Applied to files:
src/synthorg/settings/definitions/__init__.pyCLAUDE.mddocs/design/engine.mdsrc/synthorg/engine/agent_engine.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/observability/**/*.py : Observability package (observability/): structured logging, correlation tracking, log sinks; event constants organized by domain under observability/events/ (e.g., events.api, events.tool, events.git, events.context_budget, events.backup)
Applied to files:
src/synthorg/settings/definitions/__init__.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget tracking includes pre-flight/in-flight checks, auto-downgrade, billing periods, cost tiers, quota/subscription. CFO includes anomaly detection, efficiency analysis, downgrade recommendations.
Applied to files:
src/synthorg/settings/definitions/__init__.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: Budget: Cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError).
Applied to files:
src/synthorg/settings/definitions/__init__.py
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)
Applied to files:
CLAUDE.md
📚 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/communication/**/*.py : Communication package (communication/): message bus, dispatcher, messenger, channels, delegation, loop prevention, conflict resolution; meeting/ subpackage for meeting protocol (round-robin, position papers, structured phases), scheduler (frequency, participant resolver), orchestrator
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/hr/**/*.py : HR engine must provide: hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, trend detection), promotion/demotion
Applied to files:
CLAUDE.md
📚 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: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.
Applied to files:
CLAUDE.md
📚 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 docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/hr/**/*.py : HR package (hr/): hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, LLM calibration, collaboration overrides, trend detection), promotion/demotion (criteria evaluation, approval strategies, model mapping)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/engine/coordination/**/*.py : Task coordination uses multi-agent pipeline with 4 dispatchers (SAS/centralized/decentralized/context-dependent), wave execution, and workspace lifecycle integration.
Applied to files:
CLAUDE.md
📚 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 : Use Pydantic v2 BaseModel, model_validator, computed_field, ConfigDict.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-15T18:42:17.990Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:42:17.990Z
Learning: Applies to src/synthorg/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.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 : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. For derived values use `computed_field` instead of storing + validating redundant fields. Use `NotBlankStr` (from `core.types`) for all identifier/name fields — including optional (`NotBlankStr | None`) and tuple (`tuple[NotBlankStr, ...]`) variants — instead of manual whitespace validators.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget package (budget/): cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError)
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-02T11:49:21.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T11:49:21.202Z
Learning: Applies to **/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`) with `allow_inf_nan=False` in all `ConfigDict` declarations
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-01T15:36:39.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T15:36:39.993Z
Learning: Applies to src/**/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields at validation time
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. Use `computed_field` for derived values instead of storing redundant fields. Use `NotBlankStr` for all identifier/name fields.
Applied to files:
src/synthorg/engine/prompt.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: Settings: Runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge, ConfigResolver (typed composed reads for controllers), validation, registry, change notifications via message bus. Per-namespace setting definitions in definitions/ submodule (api, company, providers, memory, budget, security, coordination, observability, backup).
Applied to files:
src/synthorg/settings/definitions/engine.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/persistence/**/*.py : Persistence uses pluggable PersistenceBackend protocol. SQLite is the initial backend. Settings use SettingsRepository (namespaced settings CRUD).
Applied to files:
src/synthorg/settings/definitions/engine.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/_prompt_helpers.py
📚 Learning: 2026-04-01T09:09:43.948Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T09:09:43.948Z
Learning: Applies to **/*.py : Use `copy.deepcopy()` at construction and `MappingProxyType` wrapping for read-only enforcement in non-Pydantic internal collections (registries, BaseTool)
Applied to files:
src/synthorg/engine/_prompt_helpers.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 : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves
Applied to files:
src/synthorg/engine/_prompt_helpers.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/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
Applied to files:
src/synthorg/engine/agent_engine.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 : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-31T21:07:37.469Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.469Z
Learning: Applies to src/synthorg/providers/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-16T19:13:36.562Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:13:36.562Z
Learning: Applies to src/synthorg/providers/**/*.py : RetryConfig and RateLimiterConfig are set per-provider in ProviderConfig.
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.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/security/**/*.py : Security package (security/): 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), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)
Applied to files:
src/synthorg/engine/agent_engine.py
🔇 Additional comments (9)
src/synthorg/settings/enums.py (1)
22-22: LGTM!The
ENGINEnamespace is correctly added to theSettingNamespaceenum, following the existing pattern. This enables the settings persistence layer to recognize the new engine namespace for personality trimming settings.src/synthorg/observability/events/prompt.py (1)
17-17: LGTM!The
PROMPT_PERSONALITY_TRIMMEDevent constant follows the established naming convention (prompt.<subsystem>.<action>) and is correctly typed withFinal[str].src/synthorg/settings/definitions/engine.py (2)
1-38: LGTM!The engine settings definitions are well-structured and follow the established pattern from other namespace modules. Both settings have appropriate types, defaults, bounds, and grouping.
9-38: The settingpersonality_trimming_notifydoes not exist in the codebase and has no implementation or references anywhere. A comprehensive search finds zero matches. The fileengine.pycontains exactly two settings:personality_trimming_enabledandpersonality_max_tokens_override.If the PR summary mentions a third setting, that reference appears to be incorrect or refers to work deferred beyond this PR. Verify the PR objectives are aligned with the implementation.
> Likely an incorrect or invalid review comment.src/synthorg/settings/definitions/__init__.py (1)
13-13: LGTM!The
enginemodule is correctly imported and exported, maintaining alphabetical ordering consistent with the other namespace definition modules.Also applies to: 26-26
web/src/utils/constants.ts (1)
70-70: LGTM!The
enginenamespace is correctly added to bothNAMESPACE_ORDERandNAMESPACE_DISPLAY_NAMES, following the existing patterns. The display name "Engine" is appropriately capitalized consistent with other entries.Also applies to: 84-84
web/src/api/types.ts (1)
1448-1448: LGTM!The
'engine'literal is correctly added to theSettingNamespaceunion type, maintaining alignment with the backendSettingNamespace.ENGINEenum member.tests/unit/settings/test_engine_settings.py (1)
1-45: LGTM!The test suite provides comprehensive coverage of the ENGINE namespace settings:
- Namespace registration verification
- Type and default value assertions for each setting
- Bounds validation for the integer setting
- Count verification to catch unintended additions/removals
Well-structured with proper
@pytest.mark.unitmarker and type hints.CLAUDE.md (1)
99-99: LGTM!The documentation accurately reflects the new personality trimming feature within the engine package description, maintaining consistency with the existing documentation style.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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 `@src/synthorg/engine/agent_engine.py`:
- Around line 870-889: The try/except around config reads
(_config_resolver.get_bool/get_int) currently swallows system-level errors
(e.g., MemoryError, RecursionError, KeyboardInterrupt) and falls back to
defaults; modify the except block to re-raise system/fatal exceptions and only
log/handle regular exceptions: catch Exception as e and if isinstance(e,
(MemoryError, RecursionError, KeyboardInterrupt, SystemExit)): raise, otherwise
call logger.warning(...) as before so trimming_enabled/tokens_override fallback
only occurs for non-fatal errors.
- Around line 901-913: The code dereferences
system_prompt.personality_trim_info.budget_met although PersonalityTrimInfo
(from _prompt_helpers.py) doesn't define budget_met; either stop referencing it
here or add a safe guard. Fix by updating this call site in agent_engine.py:
when system_prompt.personality_trim_info is not None set ti =
system_prompt.personality_trim_info and remove budget_met from the
PROMPT_PERSONALITY_TRIMMED logger args (or wrap it with getattr(ti,
"budget_met", None) if you intend to support an optional field). Reference
symbols: system_prompt.personality_trim_info, ti, PROMPT_PERSONALITY_TRIMMED,
PersonalityTrimInfo.
🪄 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: ae8c4445-e0af-4810-b5b3-45c962d0f55e
📒 Files selected for processing (1)
src/synthorg/engine/agent_engine.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations
Use PEP 758 except syntax:except A, B:(no parentheses) — ruff enforces this on Python 3.14
All public functions must have type hints with mypy strict mode
Public classes and functions must have Google-style docstrings (enforced by ruff D rules)
UseNotBlankStr(fromcore.types) for all identifier/name fields, including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants, instead of manual whitespace validators
For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction andMappingProxyTypewrapping for read-only enforcement
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
In all PydanticConfigDictdeclarations, useallow_inf_nan=Falseto rejectNaN/Infin numeric fields at validation time
Use@computed_fieldfor derived values in Pydantic models instead of storing and validating redundant fields (e.g.,TokenUsage.total_tokens)
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Functions must be less than 50 lines; files must be less than 800 lines
Handle errors explicitly; never silently swallow exceptions
Validate at system boundaries (user input, external APIs, config files)
Every module with business logic must importfrom synthorg.observability import get_loggerand setlogger = get_logger(__name__). Never useimport loggingorlogging.getLogger()in application code.
Always use variable namelogger(not_logger, notlog) for structured logging
Line length must be 88 characters (enforced by ruff)
Files:
src/synthorg/engine/agent_engine.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Use event name constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api,TOOL_INVOKE_STARTfromevents.tool). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
All logger calls must use structured kwargs:logger.info(EVENT, key=value)— never use string formatting likelogger.info('msg %s', val)
All error paths must log at WARNING or ERROR with context before raising
All state transitions must log at INFO level
Use DEBUG level for object creation, internal flow, and entry/exit of key functions
Never implement retry logic in driver subclasses or calling code — retry is handled automatically byBaseCompletionProvider. SetRetryConfigandRateLimiterConfigper-provider inProviderConfig.
Never use vendor-specific names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, or comments. Use generic names:example-provider,example-large-001,example-medium-001,example-small-001. Vendor names only appear in: (1)docs/design/operations.md, (2).claude/skill files, (3) third-party import paths, (4)src/synthorg/providers/presets.py(user-facing runtime data).
Create new objects instead of mutating existing ones. Immutability is enforced throughout the codebase.
Files:
src/synthorg/engine/agent_engine.py
src/**/*.py
⚙️ CodeRabbit configuration file
This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.
Files:
src/synthorg/engine/agent_engine.py
🧠 Learnings (10)
📚 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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)
Applied to files:
src/synthorg/engine/agent_engine.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: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...
Applied to files:
src/synthorg/engine/agent_engine.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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)
Applied to files:
src/synthorg/engine/agent_engine.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/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
Applied to files:
src/synthorg/engine/agent_engine.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 : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-31T21:07:37.469Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.469Z
Learning: Applies to src/synthorg/providers/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-16T19:13:36.562Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:13:36.562Z
Learning: Applies to src/synthorg/providers/**/*.py : RetryConfig and RateLimiterConfig are set per-provider in ProviderConfig.
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.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/security/**/*.py : Security package (security/): 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), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.py
🔇 Additional comments (1)
src/synthorg/engine/agent_engine.py (1)
231-233: Nice threading of the optional settings resolver.The constructor docs, typing, and stored field make the new runtime settings hook explicit while keeping the no-resolver path unchanged.
Also applies to: 265-265, 335-335
| if self._config_resolver is not None: | ||
| try: | ||
| trimming_enabled = await self._config_resolver.get_bool( | ||
| "engine", | ||
| "personality_trimming_enabled", | ||
| ) | ||
| raw_override = await self._config_resolver.get_int( | ||
| "engine", | ||
| "personality_max_tokens_override", | ||
| ) | ||
| if raw_override > 0: | ||
| tokens_override = raw_override | ||
| except Exception: | ||
| logger.warning( | ||
| EXECUTION_ENGINE_ERROR, | ||
| agent_id=agent_id, | ||
| task_id=task_id, | ||
| msg="failed to read ENGINE settings, using defaults", | ||
| exc_info=True, | ||
| ) |
There was a problem hiding this comment.
Re-raise system errors before falling back to defaults.
Line 882 will also catch MemoryError and RecursionError, unlike the other broad catches in this module. That turns a non-recoverable failure in config resolution into a default fallback instead of aborting cleanly.
Suggested fix
if self._config_resolver is not None:
try:
trimming_enabled = await self._config_resolver.get_bool(
"engine",
"personality_trimming_enabled",
)
raw_override = await self._config_resolver.get_int(
"engine",
"personality_max_tokens_override",
)
if raw_override > 0:
tokens_override = raw_override
+ except MemoryError, RecursionError:
+ raise
except Exception:
logger.warning(
EXECUTION_ENGINE_ERROR,
agent_id=agent_id,
task_id=task_id,
msg="failed to read ENGINE settings, using defaults",
exc_info=True,
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/agent_engine.py` around lines 870 - 889, The try/except
around config reads (_config_resolver.get_bool/get_int) currently swallows
system-level errors (e.g., MemoryError, RecursionError, KeyboardInterrupt) and
falls back to defaults; modify the except block to re-raise system/fatal
exceptions and only log/handle regular exceptions: catch Exception as e and if
isinstance(e, (MemoryError, RecursionError, KeyboardInterrupt, SystemExit)):
raise, otherwise call logger.warning(...) as before so
trimming_enabled/tokens_override fallback only occurs for non-fatal errors.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/synthorg/engine/agent_engine.py (1)
871-890:⚠️ Potential issue | 🟠 MajorDon't partially apply ENGINE settings on fallback.
trimming_enabledis assigned beforepersonality_max_tokens_overridefinishes resolving. Ifget_bool()succeeds andget_int()then raises, the warning on Line 889 says defaults are being used, but the run still keeps the non-defaulttrimming_enabledvalue from the first lookup. Read both settings into temporaries and only commit them after both calls succeed.Proposed fix
if self._config_resolver is not None: try: - trimming_enabled = await self._config_resolver.get_bool( + resolved_trimming_enabled = await self._config_resolver.get_bool( "engine", "personality_trimming_enabled", ) raw_override = await self._config_resolver.get_int( "engine", "personality_max_tokens_override", ) - if raw_override > 0: - tokens_override = raw_override + trimming_enabled = resolved_trimming_enabled + tokens_override = raw_override if raw_override > 0 else None except MemoryError, RecursionError: raise except Exception: logger.warning(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/agent_engine.py` around lines 871 - 890, The current logic calls self._config_resolver.get_bool(...) and assigns trimming_enabled before calling get_int(...), causing a partial application if get_int fails; change the code in the method containing this snippet (the agent engine configuration load) to first read both values into local temporaries (e.g., tmp_trimming_enabled and tmp_raw_override using self._config_resolver.get_bool and get_int), and only after both calls complete without exception assign trimming_enabled and tokens_override from those temporaries (and apply the >0 check to tmp_raw_override); keep the same exception handling and logging but ensure no state is mutated until both lookups succeed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/synthorg/engine/agent_engine.py`:
- Around line 871-890: The current logic calls
self._config_resolver.get_bool(...) and assigns trimming_enabled before calling
get_int(...), causing a partial application if get_int fails; change the code in
the method containing this snippet (the agent engine configuration load) to
first read both values into local temporaries (e.g., tmp_trimming_enabled and
tmp_raw_override using self._config_resolver.get_bool and get_int), and only
after both calls complete without exception assign trimming_enabled and
tokens_override from those temporaries (and apply the >0 check to
tmp_raw_override); keep the same exception handling and logging but ensure no
state is mutated until both lookups succeed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4df1ed70-60db-44f8-9d72-f35a31866287
📒 Files selected for processing (1)
src/synthorg/engine/agent_engine.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations.
Useexcept A, B:syntax (no parentheses) per PEP 758 for Python 3.14 exception handling, enforced by ruff.
All public functions and classes require type hints and Google-style docstrings. Type hints must satisfy mypy strict mode.
Use line length of 88 characters, enforced by ruff.
Files:
src/synthorg/engine/agent_engine.py
src/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.py: Create new objects rather than mutating existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
For non-Pydantic internal collections and non-frozen Pydantic models, usecopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence).
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Use Pydantic v2 (BaseModel,model_validator,computed_field,ConfigDict). Useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields.
Use@computed_fieldfor derived values instead of storing + validating redundant fields (e.g.TokenUsage.total_tokens).
UseNotBlankStr(fromcore.types) for all identifier/name fields — including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants — instead of manual whitespace validators.
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Keep functions under 50 lines and files under 800 lines.
Handle errors explicitly; never silently swallow exceptions.
Validate at system boundaries (user input, external APIs, config files).
Files:
src/synthorg/engine/agent_engine.py
⚙️ CodeRabbit configuration file
This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.
Files:
src/synthorg/engine/agent_engine.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Every module with business logic MUST have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__).
Never useimport logging/logging.getLogger()/print()in application code. Exception:observability/setup.py,observability/sinks.py,observability/syslog_handler.py, andobservability/http_handler.pymay use stdlib logging and stderr print for handler construction and bootstrap.
Always useloggeras the variable name (not_logger, notlog).
Use event name constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api,TOOL_INVOKE_STARTfromevents.tool). Import directly and uselogger.info(EVENT, key=value).
Always use structured kwargs in logging:logger.info(EVENT, key=value)— never uselogger.info("msg %s", val)style formatting.
All error paths must log at WARNING or ERROR with context before raising.
All state transitions must log at INFO level.
Use DEBUG level for object creation, internal flow, and entry/exit of key functions.
Maintain 80% minimum test coverage, enforced in CI with--cov=synthorg --cov-fail-under=80.
Files:
src/synthorg/engine/agent_engine.py
src/synthorg/{providers,engine}/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
RetryExhaustedErrorsignals that all retries failed — the engine layer catches this to trigger fallback chains.
Files:
src/synthorg/engine/agent_engine.py
{src,tests}/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples. Use generic names:
example-provider,example-large-001,example-medium-001,example-small-001,large/medium/smallas aliases. Vendor names may only appear in: (1) Operations design page provider list, (2).claude/files, (3) third-party import paths, (4) provider presets. Tests usetest-provider,test-small-001, etc.
Files:
src/synthorg/engine/agent_engine.py
🧠 Learnings (18)
📚 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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)
Applied to files:
src/synthorg/engine/agent_engine.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: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...
Applied to files:
src/synthorg/engine/agent_engine.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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.py
📚 Learning: 2026-04-01T17:49:14.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T17:49:14.133Z
Learning: Applies to src/synthorg/{providers,engine}/**/*.py : Retryable errors are `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`; non-retryable errors raise immediately; `RetryExhaustedError` signals all retries failed
Applied to files:
src/synthorg/engine/agent_engine.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 : `RetryConfig` and `RateLimiterConfig` are set per-provider in `ProviderConfig`. 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. Rate limiter respects `RateLimitError.retry_after` from providers — automatically pauses future requests.
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.py
📚 Learning: 2026-04-04T10:51:32.691Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T10:51:32.691Z
Learning: Applies to src/synthorg/{providers,engine}/**/*.py : `RetryExhaustedError` signals that all retries failed — the engine layer catches this to trigger fallback chains.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-04-04T10:51:32.691Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T10:51:32.691Z
Learning: Applies to src/synthorg/providers/**/*.py : `RetryConfig` and `RateLimiterConfig` are set per-provider in `ProviderConfig`. Retryable errors (`is_retryable=True`): `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately without retry.
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.py
📚 Learning: 2026-03-15T16:55:07.730Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:55:07.730Z
Learning: Applies to src/synthorg/**/*.py : All error paths must log at WARNING or ERROR with context before raising.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget tracking includes pre-flight/in-flight checks, auto-downgrade, billing periods, cost tiers, quota/subscription. CFO includes anomaly detection, efficiency analysis, downgrade recommendations.
Applied to files:
src/synthorg/engine/agent_engine.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/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
Applied to files:
src/synthorg/engine/agent_engine.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 : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-31T21:07:37.469Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.469Z
Learning: Applies to src/synthorg/providers/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-16T19:13:36.562Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:13:36.562Z
Learning: Applies to src/synthorg/providers/**/*.py : RetryConfig and RateLimiterConfig are set per-provider in ProviderConfig.
Applied to files:
src/synthorg/engine/agent_engine.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/security/**/*.py : Security package (security/): 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), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.py
🔇 Additional comments (1)
src/synthorg/engine/agent_engine.py (1)
903-915: Nice trim observability payload.This includes the right agent/task context plus before/after budget fields, which should make prompt-budget regressions much easier to trace.
…ity_tokens Activate the previously reserved max_personality_tokens field as a hard cap on the personality section's token count. When the personality section exceeds the profile's budget, progressive trimming applies: 1. Tier 1: Drop behavioral enum fields (switch to condensed mode) 2. Tier 2: Truncate personality_description at word boundary 3. Tier 3: Fall back to minimal mode (communication_style only) Token trimming is secondary to personality_mode -- the mode selects which fields are included, the token limit enforces a hard cap. Changes: - Add _estimate_personality_tokens() and _trim_personality() in engine/_prompt_helpers.py with progressive trimming logic - Add PersonalityTrimInfo model on SystemPrompt for callers to react - Add personality_trimming_enabled and max_personality_tokens_override params to build_system_prompt() for runtime control - Add ENGINE settings namespace with 3 settings: trimming enabled, notification toggle, and global token override - Add PERSONALITY_TRIMMED WebSocket event type for dashboard notifications - Add PROMPT_PERSONALITY_TRIMMED observability event constant - Log trimming in agent_engine._prepare_context() when trim info present - Update PromptProfile.max_personality_tokens docstring Closes #1045
- Move PersonalityTrimInfo to _prompt_helpers.py (prompt.py 826->787 lines) - Add cross-field model_validator (before > max, after <= before) - Add @computed_field budget_met for tier-3 best-effort detection - Split _trim_personality into tier helpers (95->45 lines each) - Extract _format_autonomy from build_core_context (75->48 lines) - Fix double logging: _make_trim_info logs at DEBUG, engine at INFO - Pass trimming_enabled=False in _trim_sections re-renders (perf) - Add _truncate_description parametrized tests (6 cases + property) - Add PersonalityTrimInfo validation boundary tests - Add condensed direct-entry, tier2->tier3 fallthrough, WS enum tests - Add negative override test, build_core_context disabled test - Add TODO for ENGINE settings wiring in agent_engine - Update docs/design/engine.md: profiles table, trimming section - Update CLAUDE.md: engine/ package structure Pre-reviewed by 6 agents, 19 findings addressed
…nd CodeRabbit Critical fixes: - Fix personality trimming reverted during section-level re-rendering (_trim_sections now re-applies trimming instead of skipping it) - Fix _truncate_description: handle empty input (return '') and already-fitting input (return unchanged) instead of always appending '...' - Fix 'Soft limit' -> 'Hard cap' in PromptProfile.max_personality_tokens Field description to match docstring and implementation - Remove dead personality_trimming_notify setting and WsEventType.PERSONALITY_TRIMMED (no code consumed them) - Add 'engine' to frontend SettingNamespace type and display names Major fixes: - Thread token estimator through build_core_context/_trim_personality instead of hardcoding DefaultTokenEstimator (consistency with caller) - Remove dead code: 'full' in tier 2 mode guard was unreachable - Wire ConfigResolver into AgentEngine for ENGINE settings (personality_trimming_enabled, personality_max_tokens_override) - Add WARNING log when tier 3 budget not met (budget_met=False) - Document _try_condensed/_try_truncate_description side-effects - Parametrize 3 identical tier-limit tests per CLAUDE.md convention - Add test for full->tier1-fail->tier2-succeed path - Clarify build_system_prompt docstring: <=0 override values ignored - Add warning log for negative/zero max_personality_tokens_override - Add yaml_path to engine settings definitions Medium/minor fixes: - Use consistent .get() for all ctx keys in _estimate_personality_tokens - Fix docstring imprecisions (tier 1 only for full mode, markdown overhead) - Add frozen immutability test for PersonalityTrimInfo - Strengthen assertion in test_full_mode_includes_all_fields (>= 20) - Tighten test_condensed_over_budget assertion to exact tier 2 - Update truncation test cases for new already-fits behavior - Update engine.md to remove personality_trimming_notify reference
- Fix docs/design/engine.md: standard profile Acceptance Criteria column 'Bullet list' -> 'Nested list' (simplify_acceptance_criteria=False) - Add tier 1/2 budget-met invariant to PersonalityTrimInfo validator (after_tokens must not exceed max_tokens for tiers 1 and 2; only tier 3 is best-effort) - Include '## Personality' heading in _estimate_personality_tokens so budget_met reflects actual rendered section cost - Add task_id to PROMPT_PERSONALITY_TRIMMED log in agent_engine for task correlation - Propagate trimming_enabled through _trim_sections so re-renders honor the original personality_trimming_enabled flag instead of defaulting to True
ConfigResolver.get_bool/get_int raise SettingNotFoundError if keys are absent. Wrap both calls so _prepare_context falls back to defaults (trimming_enabled=True, tokens_override=None) instead of crashing the agent run.
The except block for ConfigResolver failures was using PROMPT_PERSONALITY_TRIMMED which is semantically wrong for a settings-read failure. Use EXECUTION_ENGINE_ERROR instead.
Bare 'except Exception' swallows MemoryError and RecursionError which inherit from Exception. Re-raise them per project convention (PEP 758 syntax).
Read both settings into temporaries and only assign to trimming_enabled/tokens_override in the else block after both calls succeed. Prevents a state where get_bool succeeds (overwriting trimming_enabled) but get_int fails (tokens_override stays default).
3a0deb4 to
c662162
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/synthorg/engine/_prompt_helpers.py (1)
272-285:⚠️ Potential issue | 🟠 MajorDon't hardcode the default char/token ratio in tier 2.
remaining * 4only matchesDefaultTokenEstimator. With any tokenizer-backedPromptTokenEstimator, this can miss a description length that actually fits and fall through to tier 3 unnecessarily.🛠️ Suggested fix
remaining = max_tokens - tokens_without if remaining > 0: - max_chars = remaining * 4 # Inverse of char/4 heuristic. - ctx["personality_description"] = _truncate_description( - saved_desc, - max_chars, - ) + low = 0 + high = len(saved_desc) + best = "" + while low <= high: + mid = (low + high) // 2 + candidate = _truncate_description(saved_desc, mid) + ctx["personality_description"] = candidate + if _estimate_personality_tokens(ctx, mode, estimator) <= max_tokens: + best = candidate + low = mid + 1 + else: + high = mid - 1 + ctx["personality_description"] = best else: ctx["personality_description"] = ""🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/_prompt_helpers.py` around lines 272 - 285, The code currently uses a hardcoded char/token ratio (remaining * 4) when computing max_chars, which only matches DefaultTokenEstimator; instead use the provided estimator to find the largest description slice that fits remaining tokens by replacing the fixed multiplier with logic that calls _estimate_personality_tokens during a small binary search over description length: keep saved_desc, set ctx["personality_description"] to a truncated candidate via _truncate_description, call _estimate_personality_tokens(ctx, mode, estimator) to check if it ≤ remaining, and adjust the search bounds until you find the maximal char length that fits, then set ctx["personality_description"] to that candidate (or "" if none fit). Ensure you reference and use _estimate_personality_tokens, _truncate_description, saved_desc, remaining and avoid any hardcoded ratio.src/synthorg/settings/definitions/engine.py (1)
9-38:⚠️ Potential issue | 🟠 MajorAdd the missing
personality_trimming_notifysetting.The new trimming surface still exposes only two ENGINE keys. Without
personality_trimming_notify, operators cannot suppress trim notifications while leaving trimming enabled, andAgentEngine._prepare_context()has nothing to consult before emittingPROMPT_PERSONALITY_TRIMMED.🛠️ Suggested addition
_r.register( SettingDefinition( namespace=SettingNamespace.ENGINE, key="personality_trimming_enabled", type=SettingType.BOOLEAN, default="true", description=( "Enable token-based personality trimming when section exceeds budget" ), group="Personality Trimming", yaml_path="engine.personality_trimming_enabled", ) ) +_r.register( + SettingDefinition( + namespace=SettingNamespace.ENGINE, + key="personality_trimming_notify", + type=SettingType.BOOLEAN, + default="true", + description="Emit personality trimming notifications when trimming occurs", + group="Personality Trimming", + yaml_path="engine.personality_trimming_notify", + ) +) + _r.register( SettingDefinition( namespace=SettingNamespace.ENGINE, key="personality_max_tokens_override",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/settings/definitions/engine.py` around lines 9 - 38, Add a new SettingDefinition named "personality_trimming_notify" in the same block as the other ENGINE settings: use namespace SettingNamespace.ENGINE, key="personality_trimming_notify", type=SettingType.BOOLEAN, group="Personality Trimming", yaml_path="engine.personality_trimming_notify" and set a sensible default (e.g., "true") so operators can toggle trim notifications independently of trimming; ensure the new setting is read where AgentEngine._prepare_context emits PROMPT_PERSONALITY_TRIMMED so notification behavior can be suppressed when the setting is false.
🤖 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/agent_engine.py`:
- Around line 870-893: The current logic uses one try/except around both
_config_resolver.get_bool and get_int, so a failure in get_int discards a
successful get_bool; change to resolve each ENGINE knob independently by calling
_config_resolver.get_bool("engine","personality_trimming_enabled") inside its
own try/except (re-raising MemoryError/RecursionError, logging other exceptions
and leaving trimming_enabled as the default) and then calling
_config_resolver.get_int("engine","personality_max_tokens_override") in a
separate try/except (same re-raise/log semantics) and only set tokens_override
if resolved_override > 0; keep use of trimming_enabled and tokens_override as
before.
---
Duplicate comments:
In `@src/synthorg/engine/_prompt_helpers.py`:
- Around line 272-285: The code currently uses a hardcoded char/token ratio
(remaining * 4) when computing max_chars, which only matches
DefaultTokenEstimator; instead use the provided estimator to find the largest
description slice that fits remaining tokens by replacing the fixed multiplier
with logic that calls _estimate_personality_tokens during a small binary search
over description length: keep saved_desc, set ctx["personality_description"] to
a truncated candidate via _truncate_description, call
_estimate_personality_tokens(ctx, mode, estimator) to check if it ≤ remaining,
and adjust the search bounds until you find the maximal char length that fits,
then set ctx["personality_description"] to that candidate (or "" if none fit).
Ensure you reference and use _estimate_personality_tokens,
_truncate_description, saved_desc, remaining and avoid any hardcoded ratio.
In `@src/synthorg/settings/definitions/engine.py`:
- Around line 9-38: Add a new SettingDefinition named
"personality_trimming_notify" in the same block as the other ENGINE settings:
use namespace SettingNamespace.ENGINE, key="personality_trimming_notify",
type=SettingType.BOOLEAN, group="Personality Trimming",
yaml_path="engine.personality_trimming_notify" and set a sensible default (e.g.,
"true") so operators can toggle trim notifications independently of trimming;
ensure the new setting is read where AgentEngine._prepare_context emits
PROMPT_PERSONALITY_TRIMMED so notification behavior can be suppressed when the
setting is false.
🪄 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: 4e4dbc6c-7597-4c2e-9b2b-c211bdfed290
📒 Files selected for processing (15)
CLAUDE.mddocs/design/engine.mdsrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/settings/enums.pytests/unit/engine/test_personality_trimming.pytests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pyweb/src/api/types.tsweb/src/utils/constants.ts
📜 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). (7)
- GitHub Check: Dashboard Test
- 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 (8)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Nofrom __future__ import annotations— Python 3.14 has PEP 649 native lazy annotations.
Useexcept A, B:syntax (no parentheses) per PEP 758 for Python 3.14 exception handling, enforced by ruff.
All public functions and classes require type hints and Google-style docstrings. Type hints must satisfy mypy strict mode.
Use line length of 88 characters, enforced by ruff.
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pytests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.pytests/unit/engine/test_personality_trimming.py
src/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.py: Create new objects rather than mutating existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
For non-Pydantic internal collections and non-frozen Pydantic models, usecopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence).
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Use Pydantic v2 (BaseModel,model_validator,computed_field,ConfigDict). Useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields.
Use@computed_fieldfor derived values instead of storing + validating redundant fields (e.g.TokenUsage.total_tokens).
UseNotBlankStr(fromcore.types) for all identifier/name fields — including optional (NotBlankStr | None) and tuple (tuple[NotBlankStr, ...]) variants — instead of manual whitespace validators.
Preferasyncio.TaskGroupfor fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over barecreate_task.
Keep functions under 50 lines and files under 800 lines.
Handle errors explicitly; never silently swallow exceptions.
Validate at system boundaries (user input, external APIs, config files).
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.py
⚙️ CodeRabbit configuration file
This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Every module with business logic MUST have:from synthorg.observability import get_loggerthenlogger = get_logger(__name__).
Never useimport logging/logging.getLogger()/print()in application code. Exception:observability/setup.py,observability/sinks.py,observability/syslog_handler.py, andobservability/http_handler.pymay use stdlib logging and stderr print for handler construction and bootstrap.
Always useloggeras the variable name (not_logger, notlog).
Use event name constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api,TOOL_INVOKE_STARTfromevents.tool). Import directly and uselogger.info(EVENT, key=value).
Always use structured kwargs in logging:logger.info(EVENT, key=value)— never uselogger.info("msg %s", val)style formatting.
All error paths must log at WARNING or ERROR with context before raising.
All state transitions must log at INFO level.
Use DEBUG level for object creation, internal flow, and entry/exit of key functions.
Maintain 80% minimum test coverage, enforced in CI with--cov=synthorg --cov-fail-under=80.
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.py
{src,tests}/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
NEVER use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples. Use generic names:
example-provider,example-large-001,example-medium-001,example-small-001,large/medium/smallas aliases. Vendor names may only appear in: (1) Operations design page provider list, (2).claude/files, (3) third-party import paths, (4) provider presets. Tests usetest-provider,test-small-001, etc.
Files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pysrc/synthorg/observability/events/prompt.pytests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pysrc/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.pytests/unit/engine/test_personality_trimming.py
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always reuse existing components from
web/src/components/ui/before creating new ones.
web/src/**/*.{ts,tsx}: Use Tailwind semantic classes (e.g.,text-foreground,bg-card,text-accent,text-success,bg-danger) or CSS variables (e.g.,var(--so-accent)) for colors; never hardcode hex values in.tsx/.tsfiles
Usefont-sansorfont-monofor typography; never setfontFamilydirectly
Use density-aware tokens (e.g.,p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use token variables (e.g.,var(--so-shadow-card-hover),border-border,border-bright) for shadows and borders; never hardcode values
Importcnfrom@/lib/utilsfor conditional class merging in component files
Do not usergba()with hardcoded values; use design token variables instead
Do not use hardcoded Framer Motion transition durations; use presets from@/lib/motioninstead
Files:
web/src/api/types.tsweb/src/utils/constants.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and
@/lib/motionpresets.
Files:
web/src/api/types.tsweb/src/utils/constants.ts
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Use@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slowfor test markers.
Configureasyncio_mode = "auto"in pytest — no manual@pytest.mark.asyncioneeded for async tests.
Default test timeout is 30 seconds per test (global inpyproject.toml). Non-default overrides liketimeout(60)are allowed, but do not add per-filepytest.mark.timeout(30)markers.
Prefer@pytest.mark.parametrizefor testing similar cases.
Python uses Hypothesis for property-based testing (@given+@settings). Hypothesis profiles:ci(deterministic,max_examples=10+derandomize=True),dev(1000 examples),fuzz(10,000 examples, no deadline),extreme(500,000 examples, no deadline). Controlled viaHYPOTHESIS_PROFILEenv var.
Failing Hypothesis examples are persisted to~/.synthorg/hypothesis-examples/via_WriteOnlyDatabaseintests/conftest.py. When Hypothesis finds a failure, it is a real bug — fix the underlying bug and add an explicit@example(...)decorator to permanently cover the case in CI.
Never skip, dismiss, or ignore flaky tests — always fix them fully. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep()to make them deterministic. For tasks that must block indefinitely until cancelled, useasyncio.Event().wait()instead ofasyncio.sleep(large_number).
Files:
tests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pytests/unit/engine/test_personality_trimming.py
⚙️ CodeRabbit configuration file
Test files do not require Google-style docstrings on classes or functions -- ruff D rules are only enforced on src/. A bare
@settings() decorator with no arguments on Hypothesis property tests is a no-op and should not be suggested -- the HYPOTHESIS_PROFILE env var controls example counts via registered profiles, which@given() honors automatically.
Files:
tests/unit/engine/test_prompt.pytests/unit/settings/test_engine_settings.pytests/unit/engine/test_personality_trimming.py
src/synthorg/{providers,engine}/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
RetryExhaustedErrorsignals that all retries failed — the engine layer catches this to trigger fallback chains.
Files:
src/synthorg/engine/prompt_profiles.pysrc/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.pysrc/synthorg/engine/agent_engine.py
🧠 Learnings (41)
📚 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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)
Applied to files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/__init__.pytests/unit/settings/test_engine_settings.pysrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/settings/**/*.py : Settings use runtime-editable persistence with precedence: DB > env > YAML > code defaults. 8 namespaces with Fernet encryption for sensitive values.
Applied to files:
src/synthorg/settings/enums.pysrc/synthorg/settings/definitions/engine.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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)
Applied to files:
src/synthorg/settings/definitions/__init__.pyCLAUDE.mdsrc/synthorg/settings/definitions/engine.pysrc/synthorg/engine/agent_engine.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/settings/definitions/__init__.pyCLAUDE.mdsrc/synthorg/engine/agent_engine.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: Engine: Agent orchestration, execution loops, parallel execution, task decomposition, routing, task assignment, centralized single-writer task state engine (TaskEngine), task lifecycle, recovery, shutdown, workspace isolation, coordination (multi-agent pipeline: TopologyDispatcher protocol, 4 dispatchers — SAS/centralized/decentralized/context-dependent, wave execution, workspace lifecycle integration, CoordinationSectionConfig company config bridge, build_coordinator factory), coordination error classification, prompt policy validation, checkpoint recovery (checkpoint/, per-turn persistence, heartbeat detection, CheckpointRecoveryStrategy), approval gate (escalation detection, context parking/resume, EscalationInfo/ResumePayload models), stagnation detection (stagnation/, StagnationDetector protocol, ToolRepetitionDetector, dual-signal analysis, corrective prompt injection), agent runtime state (AgentRuntimeState, lightweight per-agent execution status for dashboard queries and recove...
Applied to files:
src/synthorg/settings/definitions/__init__.pyCLAUDE.mddocs/design/engine.mdsrc/synthorg/engine/agent_engine.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/observability/**/*.py : Observability package (observability/): structured logging, correlation tracking, log sinks; event constants organized by domain under observability/events/ (e.g., events.api, events.tool, events.git, events.context_budget, events.backup)
Applied to files:
src/synthorg/settings/definitions/__init__.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget tracking includes pre-flight/in-flight checks, auto-downgrade, billing periods, cost tiers, quota/subscription. CFO includes anomaly detection, efficiency analysis, downgrade recommendations.
Applied to files:
src/synthorg/settings/definitions/__init__.pysrc/synthorg/engine/agent_engine.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: Budget: Cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError).
Applied to files:
src/synthorg/settings/definitions/__init__.py
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/hr/**/*.py : HR engine must provide: hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, trend detection), promotion/demotion
Applied to files:
CLAUDE.md
📚 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/communication/**/*.py : Communication package (communication/): message bus, dispatcher, messenger, channels, delegation, loop prevention, conflict resolution; meeting/ subpackage for meeting protocol (round-robin, position papers, structured phases), scheduler (frequency, participant resolver), orchestrator
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/engine/coordination/**/*.py : Task coordination uses multi-agent pipeline with 4 dispatchers (SAS/centralized/decentralized/context-dependent), wave execution, and workspace lifecycle integration.
Applied to files:
CLAUDE.md
📚 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: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.
Applied to files:
CLAUDE.md
📚 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 docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/hr/**/*.py : HR package (hr/): hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, LLM calibration, collaboration overrides, trend detection), promotion/demotion (criteria evaluation, approval strategies, model mapping)
Applied to files:
CLAUDE.md
📚 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 : Use Pydantic v2 BaseModel, model_validator, computed_field, ConfigDict.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-15T18:42:17.990Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:42:17.990Z
Learning: Applies to src/synthorg/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.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 : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. For derived values use `computed_field` instead of storing + validating redundant fields. Use `NotBlankStr` (from `core.types`) for all identifier/name fields — including optional (`NotBlankStr | None`) and tuple (`tuple[NotBlankStr, ...]`) variants — instead of manual whitespace validators.
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/budget/**/*.py : Budget package (budget/): cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports, budget errors (BudgetExhaustedError, DailyLimitExceededError, QuotaExhaustedError)
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-02T11:49:21.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T11:49:21.202Z
Learning: Applies to **/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`) with `allow_inf_nan=False` in all `ConfigDict` declarations
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-04T10:51:32.691Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T10:51:32.691Z
Learning: Applies to src/**/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields.
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-04-01T15:36:39.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T15:36:39.993Z
Learning: Applies to src/**/*.py : Use Pydantic v2 (`BaseModel`, `model_validator`, `computed_field`, `ConfigDict`). Use `allow_inf_nan=False` in all `ConfigDict` declarations to reject `NaN`/`Inf` in numeric fields at validation time
Applied to files:
src/synthorg/engine/prompt.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/**/*.py : Use Pydantic v2 conventions: `BaseModel`, `model_validator`, `computed_field`, `ConfigDict`. Use `computed_field` for derived values instead of storing redundant fields. Use `NotBlankStr` for all identifier/name fields.
Applied to files:
src/synthorg/engine/prompt.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 : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves
Applied to files:
src/synthorg/engine/prompt.pysrc/synthorg/engine/_prompt_helpers.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: Settings: Runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge, ConfigResolver (typed composed reads for controllers), validation, registry, change notifications via message bus. Per-namespace setting definitions in definitions/ submodule (api, company, providers, memory, budget, security, coordination, observability, backup).
Applied to files:
src/synthorg/settings/definitions/engine.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/_prompt_helpers.py
📚 Learning: 2026-04-01T09:09:43.948Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T09:09:43.948Z
Learning: Applies to **/*.py : Use `copy.deepcopy()` at construction and `MappingProxyType` wrapping for read-only enforcement in non-Pydantic internal collections (registries, BaseTool)
Applied to files:
src/synthorg/engine/_prompt_helpers.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/agent_engine.py
📚 Learning: 2026-04-01T17:49:14.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T17:49:14.133Z
Learning: Applies to src/synthorg/{providers,engine}/**/*.py : Retryable errors are `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`; non-retryable errors raise immediately; `RetryExhaustedError` signals all retries failed
Applied to files:
src/synthorg/engine/agent_engine.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 : `RetryConfig` and `RateLimiterConfig` are set per-provider in `ProviderConfig`. 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. Rate limiter respects `RateLimitError.retry_after` from providers — automatically pauses future requests.
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.py
📚 Learning: 2026-04-04T10:51:32.691Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T10:51:32.691Z
Learning: Applies to src/synthorg/{providers,engine}/**/*.py : `RetryExhaustedError` signals that all retries failed — the engine layer catches this to trigger fallback chains.
Applied to files:
src/synthorg/engine/agent_engine.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/agent_engine.py
📚 Learning: 2026-04-04T10:51:32.691Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T10:51:32.691Z
Learning: Applies to src/synthorg/providers/**/*.py : `RetryConfig` and `RateLimiterConfig` are set per-provider in `ProviderConfig`. Retryable errors (`is_retryable=True`): `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately without retry.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-15T16:55:07.730Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:55:07.730Z
Learning: Applies to src/synthorg/**/*.py : All error paths must log at WARNING or ERROR with context before raising.
Applied to files:
src/synthorg/engine/agent_engine.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/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
Applied to files:
src/synthorg/engine/agent_engine.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 : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`.
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-31T21:07:37.469Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.469Z
Learning: Applies to src/synthorg/providers/**/*.py : Set `RetryConfig` and `RateLimiterConfig` per-provider in `ProviderConfig`
Applied to files:
src/synthorg/engine/agent_engine.py
📚 Learning: 2026-03-16T19:13:36.562Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:13:36.562Z
Learning: Applies to src/synthorg/providers/**/*.py : RetryConfig and RateLimiterConfig are set per-provider in ProviderConfig.
Applied to files:
src/synthorg/engine/agent_engine.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/security/**/*.py : Security package (security/): 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), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)
Applied to files:
src/synthorg/engine/agent_engine.py
🔇 Additional comments (8)
src/synthorg/observability/events/prompt.py (1)
17-17: Event constant addition is clean and consistent.Line 17 introduces a correctly scoped prompt-domain event constant and aligns with the existing observability event naming pattern.
src/synthorg/settings/enums.py (1)
22-22: Namespace extension looks correct.Line 22 cleanly adds the
ENGINEnamespace in the same format as existing persisted namespaces.CLAUDE.md (1)
99-99: Docs update aligns with the feature behavior.Line 99 accurately reflects that engine prompt profiles now include personality trimming via
max_personality_tokens.web/src/api/types.ts (1)
1438-1449: Type union update is correct and necessary.Adding
'engine'toSettingNamespacekeeps frontend API typing in sync with the backend settings namespace set.src/synthorg/settings/definitions/__init__.py (1)
13-13: Definitions aggregator update is complete.Including
enginein both the import list and__all__ensures engine settings definitions are registered and exported with the rest of the namespaces.Also applies to: 26-26
tests/unit/engine/test_prompt.py (1)
1221-1224: Test adjustment correctly tracks the new return contract.The tuple unpacking and
trim_info is Noneassertion accurately validate theprofile=Nonedefault path after thebuild_core_contextsignature change.Also applies to: 1229-1229
web/src/utils/constants.ts (1)
62-71: Settings constants are correctly synchronized with the new namespace.Adding
engineto both namespace order and display-name mapping keeps the settings UI consistent with the expandedSettingNamespacetype.Also applies to: 74-85
tests/unit/settings/test_engine_settings.py (1)
1-45: Strong targeted coverage for engine settings registration.This test module validates namespace wiring and key metadata (type/default/bounds) for both engine settings, which is exactly the right guardrail for this feature.
| if self._config_resolver is not None: | ||
| try: | ||
| resolved_enabled = await self._config_resolver.get_bool( | ||
| "engine", | ||
| "personality_trimming_enabled", | ||
| ) | ||
| resolved_override = await self._config_resolver.get_int( | ||
| "engine", | ||
| "personality_max_tokens_override", | ||
| ) | ||
| except MemoryError, RecursionError: | ||
| raise | ||
| except Exception: | ||
| logger.warning( | ||
| EXECUTION_ENGINE_ERROR, | ||
| agent_id=agent_id, | ||
| task_id=task_id, | ||
| msg="failed to read ENGINE settings, using defaults", | ||
| exc_info=True, | ||
| ) | ||
| else: | ||
| trimming_enabled = resolved_enabled | ||
| if resolved_override > 0: | ||
| tokens_override = resolved_override |
There was a problem hiding this comment.
Resolve the ENGINE knobs independently.
A failure in the get_int() call currently discards a successful get_bool() result. That means an explicit personality_trimming_enabled=false can be silently ignored whenever personality_max_tokens_override is missing or invalid. These controls should fall back independently instead of behaving as an all-or-nothing bundle.
🛠️ Suggested fix
if self._config_resolver is not None:
try:
- resolved_enabled = await self._config_resolver.get_bool(
+ trimming_enabled = await self._config_resolver.get_bool(
"engine",
"personality_trimming_enabled",
)
- resolved_override = await self._config_resolver.get_int(
- "engine",
- "personality_max_tokens_override",
- )
except MemoryError, RecursionError:
raise
except Exception:
logger.warning(
EXECUTION_ENGINE_ERROR,
agent_id=agent_id,
task_id=task_id,
- msg="failed to read ENGINE settings, using defaults",
+ msg=(
+ "failed to read ENGINE personality_trimming_enabled, "
+ "using default"
+ ),
exc_info=True,
)
- else:
- trimming_enabled = resolved_enabled
+
+ try:
+ resolved_override = await self._config_resolver.get_int(
+ "engine",
+ "personality_max_tokens_override",
+ )
+ except MemoryError, RecursionError:
+ raise
+ except Exception:
+ logger.warning(
+ EXECUTION_ENGINE_ERROR,
+ agent_id=agent_id,
+ task_id=task_id,
+ msg=(
+ "failed to read ENGINE personality_max_tokens_override, "
+ "using default"
+ ),
+ exc_info=True,
+ )
+ else:
if resolved_override > 0:
tokens_override = resolved_override🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/agent_engine.py` around lines 870 - 893, The current
logic uses one try/except around both _config_resolver.get_bool and get_int, so
a failure in get_int discards a successful get_bool; change to resolve each
ENGINE knob independently by calling
_config_resolver.get_bool("engine","personality_trimming_enabled") inside its
own try/except (re-raising MemoryError/RecursionError, logging other exceptions
and leaving trimming_enabled as the default) and then calling
_config_resolver.get_int("engine","personality_max_tokens_override") in a
separate try/except (same re-raise/log semantics) and only set tokens_override
if resolved_override > 0; keep use of trimming_enabled and tokens_override as
before.
🤖 I have created a release *beep* *boop* --- ## [0.6.1](v0.6.0...v0.6.1) (2026-04-04) ### Features * capability-aware prompt profiles for model tier adaptation ([#1047](#1047)) ([67650c5](67650c5)), closes [#805](#805) * implement procedural memory auto-generation from agent failures ([#1048](#1048)) ([55f5206](55f5206)), closes [#420](#420) * implement quality scoring Layers 2+3 -- LLM judge and human override ([#1057](#1057)) ([4a8adfe](4a8adfe)), closes [#230](#230) * token-based personality trimming via PromptProfile.max_personality_tokens ([#1059](#1059)) ([75afd52](75afd52)), closes [#1045](#1045) * workflow execution lifecycle + editor improvements ([#1058](#1058)) ([7b54262](7b54262)), closes [#1029](#1029) [#1042](#1042) ### Refactoring * **web:** address complexity and logging issues in dashboard ([#1056](#1056)) ([ada997b](ada997b)), closes [#1055](#1055) ### Documentation * comprehensive documentation refresh ([#1050](#1050)) ([c7a4259](c7a4259)) ### Tests * fix Hypothesis fuzzing infra and speed up slow unit tests ([#1044](#1044)) ([1111602](1111602)) ### Maintenance * add text=auto catch-all to .gitattributes ([#1051](#1051)) ([fc65d72](fc65d72)) * bump defu from 6.1.4 to 6.1.6 in /site ([#1062](#1062)) ([f0cc439](f0cc439)) --- 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
Activate the previously reserved
max_personality_tokensfield as a hard cap on the personality section's token count. When the personality section exceeds the profile's budget, progressive trimming applies:"condensed"(removes behavioral enum fields)personality_descriptionat word boundary with"..."suffix"minimal"(communication_style only)Token trimming is secondary to
personality_mode-- the mode selects which fields are included, the token limit enforces a hard cap.Changes
Core trimming engine
_estimate_personality_tokens(),_try_condensed(),_try_truncate_description(),_truncate_description()helpers inengine/_prompt_helpers.py_trim_personality()orchestrator with progressive 3-tier trimmingPersonalityTrimInfomodel with cross-fieldmodel_validatorand@computed_field budget_metbuild_core_context()returnstuple[dict, PersonalityTrimInfo | None]-- trimming applied automaticallyPrompt layer integration
SystemPrompt.personality_trim_infofield exposes trimming metadata to callersbuild_system_prompt()new params:personality_trimming_enabled(master switch),max_personality_tokens_override(runtime override)_trim_sections()skips redundant personality trimming on re-renders (perf)Runtime settings
ENGINEsettings namespace with 3 settings:personality_trimming_enabled(bool, default: true)personality_trimming_notify(bool, default: true)personality_max_tokens_override(int, default: 0 = use profile defaults)Notifications & observability
PERSONALITY_TRIMMEDWebSocket event type for dashboard notificationsPROMPT_PERSONALITY_TRIMMEDobservability event constantDocumentation
docs/design/engine.md: profiles table with Max Personality Tokens column, new Personality Trimming subsection, pipeline step 3, invariantsCLAUDE.mdpackage structurePromptProfile.max_personality_tokensdocstringTest plan
TestEstimatePersonalityTokens(4): full > condensed > minimal estimationTestTrimPersonality(8): all 3 tiers, edge cases (empty desc, word boundary, already minimal)TestTrimPersonalityLogging(2): event presence/absenceTestTierLimits(3): small=80, medium=200, large=500 token capsTestBuildSystemPromptIntegration(7): end-to-end, disable, override, negative overrideTestTruncateDescription(8): parametrized edge cases + property testTestPersonalityTrimInfoValidation(6): field constraints + cross-field invariantsTestAdditionalEdgeCases(4): condensed direct entry, tier2->tier3, disabled+profile, WS enumTestEngineSettingDefinitions(5): namespace, types, defaults, countReview coverage
Pre-reviewed by 6 agents (docs-consistency, code-reviewer, type-design-analyzer, test-analyzer, conventions-enforcer, issue-resolution-verifier). 19 findings addressed.
Closes #1045