feat: config fixes and deferred improvements from PR #1058 review#1067
feat: config fixes and deferred improvements from PR #1058 review#1067
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
🧰 Additional context used📓 Path-based instructions (3)**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/synthorg/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/**/*.py⚙️ CodeRabbit configuration file
Files:
🧠 Learnings (17)📓 Common learnings📚 Learning: 2026-03-19T07:12:14.508ZApplied to files:
📚 Learning: 2026-03-17T22:08:13.456ZApplied to files:
📚 Learning: 2026-03-17T22:08:13.456ZApplied to files:
📚 Learning: 2026-03-17T06:30:14.180ZApplied to files:
📚 Learning: 2026-03-31T21:07:37.470ZApplied to files:
📚 Learning: 2026-03-20T21:44:04.528ZApplied to files:
📚 Learning: 2026-04-04T17:42:47.768ZApplied to files:
📚 Learning: 2026-03-16T07:22:28.134ZApplied to files:
📚 Learning: 2026-03-14T16:18:57.267ZApplied to files:
📚 Learning: 2026-03-16T07:22:28.134ZApplied to files:
📚 Learning: 2026-03-14T15:43:05.601ZApplied to files:
📚 Learning: 2026-03-14T15:43:05.601ZApplied to files:
📚 Learning: 2026-03-14T16:18:57.267ZApplied to files:
📚 Learning: 2026-03-15T16:55:07.730ZApplied to files:
📚 Learning: 2026-04-01T15:36:39.993ZApplied to files:
📚 Learning: 2026-04-04T17:42:47.768ZApplied to files:
🔇 Additional comments (10)
WalkthroughAdds a top-level 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 introduces performance tracking configuration, implements an asynchronous observer dispatch mechanism in the TaskEngine to prevent slow observers from blocking mutations, and adds support for compound boolean operators (AND, OR, NOT) and parenthesized groups in workflow condition evaluations. Additionally, it optimizes workflow execution lookups using SQLite's JSON features and improves security by migrating JWT storage from localStorage to sessionStorage. A critical syntax error was identified in the TaskEngine where Python 2 exception handling syntax was used, which will cause a failure in Python 3 environments.
| except MemoryError, RecursionError: | ||
| raise |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1067 +/- ##
==========================================
- Coverage 89.69% 89.65% -0.05%
==========================================
Files 730 731 +1
Lines 42539 42698 +159
Branches 4267 4287 +20
==========================================
+ Hits 38157 38282 +125
- Misses 3636 3663 +27
- Partials 746 753 +7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds configuration plumbing and several deferred engine/editor improvements, including YAML-driven performance tracking config, safer JWT storage, richer condition evaluation, faster workflow execution lookup, background observer dispatch, and round-trip-stable YAML branch metadata.
Changes:
- Wire
PerformanceConfigintoRootConfig/ defaults and pass it into_build_performance_tracker, with docs + config loader/schema tests. - Migrate web auth token persistence from
localStoragetosessionStorage, updating API client/interceptors and related tests. - Improve workflow system ergonomics/perf: compound condition evaluator (AND/OR/NOT + parens), repository
find_by_task_id, background TaskEngine observer dispatch, and explicit{id, branch}YAMLdepends_onmetadata with importer/exporter tests.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/stores/auth.ts | Switch token persistence to sessionStorage and update expiry/must-change-password handling. |
| web/src/pages/workflow-editor/yaml-to-nodes.ts | Parse depends_on entries as `string |
| web/src/pages/workflow-editor/workflow-to-yaml.ts | Export depends_on with explicit {id, branch} objects for conditional edges to preserve round-trip fidelity. |
| web/src/api/endpoints/providers.ts | Use sessionStorage token for SSE model-pull auth and clear session keys on 401. |
| web/src/api/client.ts | Update interceptor JWT storage note + switch auth token reads/clears to sessionStorage. |
| web/src/tests/stores/auth.test.ts | Update auth-store tests for sessionStorage persistence/cleanup. |
| web/src/tests/router/guards.test.tsx | Ensure session storage is cleared in guard-related test resets. |
| web/src/tests/pages/workflow-editor/yaml-to-nodes.test.ts | Add tests for YAML importer depends_on branch metadata parsing and fallback inference. |
| web/src/tests/pages/workflow-editor/workflow-to-yaml.test.ts | Add tests for YAML exporter branch metadata emission. |
| web/src/tests/hooks/useWebSocket.test.ts | Clear session storage in test reset to avoid cross-test token leakage. |
| web/src/tests/hooks/useAuth.test.ts | Clear session storage in test reset to avoid cross-test token leakage. |
| web/src/tests/api/client.test.ts | Update interceptor tests to validate sessionStorage token injection and 401 cleanup. |
| web/src/tests/api/client-bypass.test.ts | Update dev-bypass interceptor tests for sessionStorage. |
| tests/unit/persistence/test_protocol.py | Extend protocol compliance fake with find_by_task_id. |
| tests/unit/engine/workflow/test_execution_service.py | Update fake repo with find_by_task_id to match new protocol. |
| tests/unit/engine/workflow/test_execution_lifecycle.py | Update fake repo with find_by_task_id to match new protocol. |
| tests/unit/engine/workflow/test_condition_eval.py | Add extensive tests for compound condition evaluation semantics and edge cases. |
| tests/unit/engine/test_task_engine_observers.py | Add observer-queue flushing helper and test that slow observers don’t block mutations. |
| tests/unit/config/test_schema.py | Add RootConfig.performance default/custom tests. |
| tests/unit/config/test_loader.py | Add YAML round-trip test for performance namespace. |
| tests/unit/config/conftest.py | Include PerformanceConfig in RootConfigFactory. |
| tests/unit/api/fakes_workflow.py | Fix runtime import and add fake repo find_by_task_id. |
| src/synthorg/persistence/workflow_execution_repo.py | Add protocol method find_by_task_id. |
| src/synthorg/persistence/sqlite/workflow_execution_repo.py | Implement find_by_task_id via SQLite JSON search + structured events. |
| src/synthorg/observability/events/task_engine.py | Add new TaskEngine observer queue/drain observability event keys. |
| src/synthorg/observability/events/persistence.py | Add new persistence observability event keys for task lookup. |
| src/synthorg/engine/workflow/execution_service.py | Delegate task->execution lookup to repository method. |
| src/synthorg/engine/workflow/condition_eval.py | Implement tokenizer + recursive-descent parser for compound conditions with quick-path for legacy expressions. |
| src/synthorg/engine/task_engine.py | Add background observer dispatcher queue/loop and adjust shutdown/drain behavior. |
| src/synthorg/config/schema.py | Add performance: PerformanceConfig to RootConfig. |
| src/synthorg/config/defaults.py | Add "performance": {} to default config dict to support YAML merge base. |
| src/synthorg/api/app.py | Pass effective_config.performance into _build_performance_tracker. |
| docs/design/operations.md | Document performance YAML namespace fields, defaults, and validation rules. |
| CLAUDE.md | Update repo architecture notes to reflect background observer dispatch and compound condition evaluator. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| tokens = _tokenize(expr) | ||
| if not tokens: | ||
| return False | ||
| result, _ = _parse_or(tokens, 0, context) |
There was a problem hiding this comment.
In the compound-expression path, the parser result is returned even if it didn't consume all tokens. This means malformed expressions with trailing junk (e.g. "true OR false garbage" or "(a == 1) extra") can incorrectly evaluate to True instead of falling back to the never-raise/malformed->False behavior. Consider treating any unconsumed tokens (or unexpected closing parens) as a parse failure and returning False when the final parse position is not at the end of the token list.
| result, _ = _parse_or(tokens, 0, context) | |
| result, pos = _parse_or(tokens, 0, context) | |
| if pos != len(tokens): | |
| return False |
src/synthorg/engine/task_engine.py
Outdated
| while self._running or not self._observer_queue.empty(): | ||
| try: | ||
| event = await asyncio.wait_for( | ||
| self._observer_queue.get(), | ||
| timeout=self._POLL_INTERVAL_SECONDS, | ||
| ) | ||
| except TimeoutError: | ||
| continue |
There was a problem hiding this comment.
Shutdown race: stop() sets _running=False before the processing loop drains, and _observer_dispatch_loop exits when (_running is False and _observer_queue is empty). If the observer queue is momentarily empty at shutdown start, the dispatcher task can terminate early and miss events enqueued later by the still-draining _processing_loop. The dispatcher loop should also stay alive while the processing task is still running (or use a separate "shutdown complete" signal) so observer delivery is truly drained after mutation draining.
| const depEntries: DependsOnEntry[] = [] | ||
| for (const srcId of incoming.get(nodeId) ?? []) { | ||
| const srcNode = nodeMap.get(srcId) | ||
| return srcNode && !skipTypes.has(srcNode.type ?? '') | ||
| }) | ||
| if (deps.length > 0) step.depends_on = deps | ||
| if (!srcNode || skipTypes.has(srcNode.type ?? '')) continue | ||
| // Find the edge from srcId to this node | ||
| const edge = edges.find((e) => e.source === srcId && e.target === nodeId) | ||
| const edgeType = (edge?.data as Record<string, unknown> | undefined)?.edgeType as string | undefined | ||
| if (edgeType === 'conditional_true') { |
There was a problem hiding this comment.
Exporter performance: inside the per-node dependency loop, this does edges.find(...) for each incoming edge, which makes YAML generation O(E^2) in dense graphs. Since an outgoing map is already built above, prefer looking up the src->target edge from outgoing.get(srcId) (or precomputing a source/target->edge map once) to keep preview generation linear.
| cursor = await self._db.execute( | ||
| f"SELECT {_SELECT_COLUMNS} FROM workflow_executions" # noqa: S608 | ||
| " WHERE status = ?" | ||
| " AND EXISTS (" | ||
| " SELECT 1 FROM json_each(node_executions)" | ||
| " WHERE json_extract(value, '$.task_id') = ?" | ||
| " )" | ||
| " LIMIT 1", | ||
| (WorkflowExecutionStatus.RUNNING.value, task_id), |
There was a problem hiding this comment.
This query filters by RUNNING (good, uses idx_wfe_status) but still needs to scan/parse node_executions JSON via json_each() for every RUNNING execution, so the lookup is not truly O(1) and may remain a hot-path cost at scale. If task_id lookups are frequent, consider a normalized mapping (task_id -> execution_id) maintained on save, or another indexable representation, to avoid JSON scans.
There was a problem hiding this comment.
Actionable comments posted: 9
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/task_engine.py (1)
139-145:⚠️ Potential issue | 🔴 CriticalThese observers are no longer safe to treat as best-effort.
put_nowait()turns observer backpressure into droppedTaskStateChangedevents, butWorkflowExecutionObserverconsumes those events to advance running workflows. If the queue fills here, the task mutation still succeeds whileWorkflowExecutionService.handle_task_state_changed()never sees the terminal transition, so the workflow can remainRUNNINGforever. This path needs lossless delivery for stateful observers, or a separate best-effort channel for telemetry-only observers.Also applies to: 711-720
🤖 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/workflow/condition_eval.py`:
- Around line 22-25: The tokenizer and operator-detection routines are treating
tokens like AND/OR/NOT or parentheses as operators even when they appear inside
a comparison atom (e.g., "AND == yes", "status == OR", "title == Research AND
Development"); update _tokenize() to first recognize full comparison atoms (lhs,
comparator, rhs) as a single token before splitting for compound operators and
update _has_compound_operators() to check for operator tokens only after
tokenization of comparisons, ensuring that strings on the right-hand side
(including words that match operator names or contain spaces/parentheses) are
not re-classified as logical operators; refer to _tokenize(),
_has_compound_operators(), and the comparison parsing code paths where tokens
are currently split so the comparison-form escape hatch is honored.
- Around line 180-195: The parser currently accepts partial/ malformed
expressions as true; update _parse_atom_token (the block handling "(" and bare
operator tokens) to treat any unexpected/missing operands or unmatched
parentheses as a parse error that returns False and a position that signals
failure (e.g. do not claim to have successfully consumed a valid atom), and then
make evaluate_condition verify the parser consumed the entire token stream and
the top-level parse returned success (return False if pos != len(tokens) or
parse returned an error). Concretely: in the "(" branch of _parse_atom_token
ensure a parse failure inside the parentheses propagates as False and the caller
sees failure (don’t return a truthy value when closing parenthesis is missing),
treat bare operator tokens ("AND","OR","NOT",")") as parse errors (return False
and indicate failure), and add a final check in evaluate_condition that the
returned pos equals len(tokens) and the returned value is a successful parse
before returning True.
- Around line 31-32: Add a module logger and use it to record parsing failures
instead of silently swallowing them: import get_logger with "from
synthorg.observability import get_logger" and add "logger =
get_logger(__name__)" at module scope, then in the try/except that
parses/evaluates the condition_expression (the block that currently catches
parser exceptions and returns False) call logger.exception or logger.error with
the exception and include the offending condition_expression in the message
before returning False so parse errors are logged with context.
In `@src/synthorg/persistence/sqlite/workflow_execution_repo.py`:
- Around line 466-472: The deserialization call passes task_id into
_deserialize_row causing any PERSISTENCE_WORKFLOW_EXEC_DESERIALIZE_FAILED logs
to show the task id instead of the workflow execution id; fix by extracting the
execution id from the retrieved row (e.g., id = row["id"] or
row["execution_id"]) and pass that execution id into _deserialize_row instead of
task_id, then use execution.id (or the extracted id) when emitting
PERSISTENCE_WORKFLOW_EXEC_FOUND_BY_TASK so the failure and found logs reference
the correct workflow execution identifier.
In `@tests/unit/engine/test_task_engine_observers.py`:
- Around line 18-31: The helper _flush_observers currently returns silently if
the observer queue isn't drained; change it to enforce a deterministic failure:
add a timeout parameter (e.g., timeout=0.5) and after the polling loop raise an
AssertionError or asyncio.TimeoutError if engine._observer_queue is still not
empty so tests fail instead of hiding races; keep using
engine._observer_queue.empty() and the same small sleeps but wrap the logic so
unmet timeout triggers the exception, and update callers/tests to mock
time.monotonic()/asyncio.sleep() when needed per guidelines.
In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts`:
- Around line 32-93: Add a new test in workflow-to-yaml.test.ts that uses
makeNode/makeEdge to create a small graph with a parallel_branch edge (e.g.,
start -> a, start -> b as parallel branches, then both -> end) and call
generateYamlPreview(nodes, edges, 'test', 'agile'); assert the generated YAML
includes plain string depends_on entries for the parallel targets (e.g.,
expect(yaml).toContain('- a') / '- b') and does NOT include branch metadata
(expect(yaml).not.toContain('branch:') / not.toMatch(/id:\s*.../)), so the
exporter’s fallback for parallel_branch is explicitly validated.
- Around line 71-73: The regexes in the test (the expectations using
/branch:\s*.true./ and /branch:\s*.false./) are too permissive because the dots
match any char; update them to precisely match quoted boolean strings or word
boundaries — for example replace with patterns that assert quotes and the full
word like /branch:\s*['"]true['"]/ and /branch:\s*['"]false['"]/ or use word
boundaries /\btrue\b/ and /\bfalse\b/ so malformed outputs like "Xtruez" won't
pass; modify the expect calls in workflow-to-yaml.test (the three
expect(yaml).toMatch(...) assertions) accordingly.
In `@web/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts`:
- Around line 136-171: Add a new test case to verify unrecognized branch values
produce a warning and fall back to inference: create a YAML where a conditional
step "check" is depended on by "step_b" with depends_on entry { id: "check",
branch: "maybe" }, call parseYamlToNodesEdges(yaml), assert result.errors has
length 0, result.warnings length > 0 and result.warnings[0] contains
'unrecognized branch', then locate the edge with findEdge(result.edges, 'check',
'step_b') and assert its data.edgeType equals 'conditional_true' to confirm
fallback inference.
In `@web/src/pages/workflow-editor/yaml-to-nodes.ts`:
- Around line 261-271: Add a non-fatal warning when explicit branch metadata is
present on a non-conditional source step: inside the branch where explicitBranch
!== undefined (the block that sets edgeType to 'conditional_true' or
'conditional_false'), check if sourceStep.type !== 'conditional' and emit a
warning (e.g., via console.warn or the project logger) that explicit branch
metadata was provided for depId/sourceStep and will be treated as a conditional
edge; keep existing behavior (setting edgeType) and do not change the
conditionalBranchCounters or fallback logic in inferDependsOnEdgeType.
🪄 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: 98f61de8-926e-433c-831c-607af6826929
📒 Files selected for processing (34)
CLAUDE.mddocs/design/operations.mdsrc/synthorg/api/app.pysrc/synthorg/config/defaults.pysrc/synthorg/config/schema.pysrc/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.pysrc/synthorg/engine/workflow/execution_service.pysrc/synthorg/observability/events/persistence.pysrc/synthorg/observability/events/task_engine.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.pysrc/synthorg/persistence/workflow_execution_repo.pytests/unit/api/fakes_workflow.pytests/unit/config/conftest.pytests/unit/config/test_loader.pytests/unit/config/test_schema.pytests/unit/engine/test_task_engine_observers.pytests/unit/engine/workflow/test_condition_eval.pytests/unit/engine/workflow/test_execution_lifecycle.pytests/unit/engine/workflow/test_execution_service.pytests/unit/persistence/test_protocol.pyweb/src/__tests__/api/client-bypass.test.tsweb/src/__tests__/api/client.test.tsweb/src/__tests__/hooks/useAuth.test.tsweb/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.tsweb/src/__tests__/router/guards.test.tsxweb/src/__tests__/stores/auth.test.tsweb/src/api/client.tsweb/src/api/endpoints/providers.tsweb/src/pages/workflow-editor/workflow-to-yaml.tsweb/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/stores/auth.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: Agent
- GitHub Check: Dashboard Test
- GitHub Check: Build Web
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Backend
- 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 (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
web/src/**/*.{ts,tsx}: Web dashboard: 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.
Web dashboard: design token rules enforced by PostToolUse hook (scripts/check_web_design_system.py)
TypeScript/JavaScript: Node.js 22+, TypeScript 6.0+, ESLint with zero warnings enforced onweb/src/**/*.{ts,tsx}
Web dashboard YAML parsing: usejs-yamllibrary (in package.json)
Files:
web/src/__tests__/router/guards.test.tsxweb/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/api/client-bypass.test.tsweb/src/__tests__/hooks/useAuth.test.tsweb/src/api/endpoints/providers.tsweb/src/api/client.tsweb/src/stores/auth.tsweb/src/__tests__/api/client.test.tsweb/src/__tests__/stores/auth.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/pages/workflow-editor/workflow-to-yaml.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
web/src/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
React testing: use fast-check for property-based testing (
fc.assert+fc.property)
Files:
web/src/__tests__/router/guards.test.tsxweb/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/api/client-bypass.test.tsweb/src/__tests__/hooks/useAuth.test.tsweb/src/__tests__/api/client.test.tsweb/src/__tests__/stores/auth.test.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Web dashboard styling: Tailwind CSS 4 for utility classes; never hardcode pixel values or colors
Files:
web/src/__tests__/router/guards.test.tsxweb/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/api/client-bypass.test.tsweb/src/__tests__/hooks/useAuth.test.tsweb/src/api/endpoints/providers.tsweb/src/api/client.tsweb/src/stores/auth.tsweb/src/__tests__/api/client.test.tsweb/src/__tests__/stores/auth.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/pages/workflow-editor/workflow-to-yaml.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Python 3.14+ required; nofrom __future__ import annotations(PEP 649 native lazy annotations)
Use PEP 758 except syntax:except A, B:(no parentheses) -- ruff enforces this on Python 3.14
Type hints required on all public functions; mypy strict mode enforced
Docstrings in Google style, required on all public classes and functions (enforced by ruff D rules)
Create new objects, never mutate existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
Fordict/listfields in frozen Pydantic models, rely onfrozen=Truefor field reassignment prevention andcopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state. Never mix static config fields with mutable runtime fields in one model.
Pydantic v2: useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields at validation time
Use@computed_fieldfor derived values in Pydantic models instead of storing + validating redundant fields (e.g.TokenUsage.total_tokens)
UseNotBlankStr(fromcore.types) for all identifier/name fields in Pydantic models -- 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.
Line length: 88 characters (ruff enforced)
Functions must be < 50 lines, files < 800 lines
Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Files:
src/synthorg/config/defaults.pysrc/synthorg/api/app.pytests/unit/persistence/test_protocol.pysrc/synthorg/engine/workflow/execution_service.pytests/unit/config/conftest.pytests/unit/config/test_schema.pysrc/synthorg/observability/events/task_engine.pysrc/synthorg/config/schema.pytests/unit/engine/workflow/test_execution_lifecycle.pytests/unit/api/fakes_workflow.pytests/unit/engine/workflow/test_execution_service.pysrc/synthorg/observability/events/persistence.pytests/unit/engine/workflow/test_condition_eval.pysrc/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.pytests/unit/engine/test_task_engine_observers.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.pysrc/synthorg/persistence/workflow_execution_repo.pytests/unit/config/test_loader.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 stdlibloggingandprint(..., file=sys.stderr)for handler construction
Logger variable name must always belogger(not_logger, notlog)
Event names: always use constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
Structured kwargs in logging: 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 level
DEBUG logging for object creation, internal flow, entry/exit of key functions
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. Vendor names allowed only in: Operations design page,.claude/files, third-party import paths, andsrc/synthorg/providers/presets.py
Files:
src/synthorg/config/defaults.pysrc/synthorg/api/app.pysrc/synthorg/engine/workflow/execution_service.pysrc/synthorg/observability/events/task_engine.pysrc/synthorg/config/schema.pysrc/synthorg/observability/events/persistence.pysrc/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.pysrc/synthorg/persistence/workflow_execution_repo.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/config/defaults.pysrc/synthorg/api/app.pysrc/synthorg/engine/workflow/execution_service.pysrc/synthorg/observability/events/task_engine.pysrc/synthorg/config/schema.pysrc/synthorg/observability/events/persistence.pysrc/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.pysrc/synthorg/persistence/workflow_execution_repo.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Vendor names in test files must usetest-provider,test-small-001, etc.
Test markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow
Coverage minimum 80% enforced in CI
Async testing:asyncio_mode = "auto"in conftest -- no manual@pytest.mark.asyncioneeded
Default timeout: 30 seconds per test (global inpyproject.toml). Non-default overrides liketimeout(60)are allowed but avoid adding per-file markers.
Prefer@pytest.mark.parametrizefor testing similar cases in Python tests
Property-based testing in Python: use Hypothesis (@given+@settings). Profiles intests/conftest.py:ci(deterministic, 10 examples),dev(1000 examples),fuzz(10,000 examples, no deadline),extreme(500,000 examples). Controlled viaHYPOTHESIS_PROFILEenv var.
When Hypothesis finds a failure, 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 fundamentally. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep(). For indefinite blocking, useasyncio.Event().wait()instead ofasyncio.sleep(large_number).
Files:
tests/unit/persistence/test_protocol.pytests/unit/config/conftest.pytests/unit/config/test_schema.pytests/unit/engine/workflow/test_execution_lifecycle.pytests/unit/api/fakes_workflow.pytests/unit/engine/workflow/test_execution_service.pytests/unit/engine/workflow/test_condition_eval.pytests/unit/engine/test_task_engine_observers.pytests/unit/config/test_loader.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/persistence/test_protocol.pytests/unit/config/conftest.pytests/unit/config/test_schema.pytests/unit/engine/workflow/test_execution_lifecycle.pytests/unit/api/fakes_workflow.pytests/unit/engine/workflow/test_execution_service.pytests/unit/engine/workflow/test_condition_eval.pytests/unit/engine/test_task_engine_observers.pytests/unit/config/test_loader.py
🧠 Learnings (47)
📚 Learning: 2026-03-27T12:44:29.466Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:44:29.466Z
Learning: Applies to web/src/stores/**/*.{ts,tsx} : Use Zustand stores in web dashboard for state management (auth, WebSocket, toast, analytics, domain shells)
Applied to files:
web/src/__tests__/router/guards.test.tsxweb/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/hooks/useAuth.test.tsweb/src/stores/auth.tsweb/src/__tests__/stores/auth.test.ts
📚 Learning: 2026-03-30T10:41:40.176Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:41:40.176Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use Zustand stores for state management in the web dashboard; each domain has its own store module (auth, WebSocket, toast, analytics, setup, company, agents, budget, tasks, settings, providers, theme, per-domain stores)
Applied to files:
web/src/__tests__/router/guards.test.tsxweb/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/hooks/useAuth.test.tsweb/src/stores/auth.tsweb/src/__tests__/stores/auth.test.ts
📚 Learning: 2026-03-30T10:20:08.544Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:20:08.544Z
Learning: Applies to web/**/*.test.{ts,tsx} : Web dashboard: Use React Hypothesis (fast-check) for property-based testing with fc.assert + fc.property
Applied to files:
web/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/api/client.test.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 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/config/defaults.pyCLAUDE.mdsrc/synthorg/config/schema.pysrc/synthorg/engine/task_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/engine/workflow/execution_service.pyCLAUDE.mdsrc/synthorg/observability/events/task_engine.pysrc/synthorg/config/schema.pysrc/synthorg/engine/task_engine.pytests/unit/engine/test_task_engine_observers.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:
CLAUDE.mdtests/unit/config/conftest.pysrc/synthorg/config/schema.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.mdtests/unit/config/conftest.pysrc/synthorg/config/schema.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/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.mdsrc/synthorg/config/schema.pysrc/synthorg/engine/task_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: 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.mddocs/design/operations.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.mdtests/unit/config/conftest.pysrc/synthorg/config/schema.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:
tests/unit/config/conftest.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:
tests/unit/config/conftest.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:
tests/unit/config/conftest.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:
tests/unit/config/conftest.py
📚 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/core/**/*.py : Core module must contain shared domain models, base classes, resilience config (RetryConfig, RateLimiterConfig)
Applied to files:
tests/unit/config/conftest.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:
tests/unit/config/conftest.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/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.
Applied to files:
tests/unit/config/conftest.pysrc/synthorg/config/schema.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:
tests/unit/config/conftest.pysrc/synthorg/config/schema.py
📚 Learning: 2026-03-30T10:20:08.544Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:20:08.544Z
Learning: Applies to web/**/*.stories.{ts,tsx} : Storybook 10: Use storybook/test (not storybook/test) and storybook/actions (not storybook/addon-actions) import paths
Applied to files:
web/src/__tests__/hooks/useAuth.test.ts
📚 Learning: 2026-03-30T10:41:40.176Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:41:40.176Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: import from `storybook/test` (not `storybook/test`), `storybook/actions` (not `storybook/addon-actions`)
Applied to files:
web/src/__tests__/hooks/useAuth.test.ts
📚 Learning: 2026-04-04T10:51:58.893Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-04T10:51:58.893Z
Learning: Applies to web/**/*.stories.tsx : Use `storybook/test` (not `storybook/test`) and `storybook/actions` (not `storybook/addon-actions`) for Storybook imports
Applied to files:
web/src/__tests__/hooks/useAuth.test.ts
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: Import from `storybook/test` instead of `storybook/test`
Applied to files:
web/src/__tests__/hooks/useAuth.test.tsweb/src/__tests__/api/client.test.tsweb/src/__tests__/stores/auth.test.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 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 event name constants from synthorg.observability.events domain-specific modules (e.g., PROVIDER_CALL_START from events.provider). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT.
Applied to files:
src/synthorg/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.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/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.pydocs/design/operations.md
📚 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 : 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 synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
src/synthorg/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.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/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.py
📚 Learning: 2026-03-18T21:23:23.586Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T21:23:23.586Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from the domain-specific module under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api, TOOL_INVOKE_START from events.tool). Import directly from synthorg.observability.events.<domain>.
Applied to files:
src/synthorg/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.py
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`
Applied to files:
src/synthorg/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.py
📚 Learning: 2026-03-31T16:09:24.320Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T16:09:24.320Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from `synthorg.observability.events.<domain>` modules (e.g., `API_REQUEST_STARTED` from `events.api`, `TOOL_INVOKE_START` from `events.tool`); import directly and use in structured logging
Applied to files:
src/synthorg/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under synthorg.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
src/synthorg/observability/events/task_engine.pysrc/synthorg/observability/events/persistence.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 : Always 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 rather than using string literals
Applied to files:
src/synthorg/observability/events/task_engine.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 : Always use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`); import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`
Applied to files:
src/synthorg/observability/events/task_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: 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: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).
Applied to files:
src/synthorg/config/schema.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/config/schema.pydocs/design/operations.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/__tests__/**/*.{test,spec}.{ts,tsx} : Vitest unit tests must use coverage scoped to files changed vs origin/main branch
Applied to files:
web/src/__tests__/api/client.test.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 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 web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/api/client.test.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-30T10:41:40.176Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:41:40.176Z
Learning: Applies to web/src/__tests__/**/*.test.{ts,tsx} : Use property-based testing with fast-check in React tests (`fc.assert` + `fc.property`)
Applied to files:
web/src/__tests__/api/client.test.ts
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Applied to files:
src/synthorg/engine/task_engine.pytests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : For tasks that must block indefinitely until cancelled (e.g. simulating a slow provider or stubborn coroutine), use `asyncio.Event().wait()` instead of `asyncio.sleep(large_number)` -- it is cancellation-safe
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : Never skip, dismiss, or ignore flaky tests; fix them fully and fundamentally by mocking `time.monotonic()` and `asyncio.sleep()` for determinism or using `asyncio.Event().wait()` for indefinite blocking
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-16T10:40:25.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T10:40:25.144Z
Learning: Applies to tests/**/*.py : Async testing: asyncio_mode = 'auto' — no manual pytest.mark.asyncio needed.
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard YAML parsing: use `js-yaml` library (in package.json)
Applied to files:
web/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/pages/workflow-editor/workflow-to-yaml.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.
Applied to files:
web/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/pages/workflow-editor/workflow-to-yaml.ts
🔇 Additional comments (46)
web/src/__tests__/router/guards.test.tsx (1)
53-54: LGTM!Clearing
sessionStoragebeforelocalStoragecorrectly aligns the test cleanup with the auth storage migration. This ensures auth-related state is properly reset between tests.web/src/__tests__/hooks/useAuth.test.ts (1)
14-18: LGTM!The
resetStore()helper correctly clearssessionStorageto match the auth storage migration, ensuring clean test isolation.web/src/__tests__/hooks/useWebSocket.test.ts (1)
14-20: LGTM!Consistent with other test files—
resetStores()now clears both storage types to properly isolate tests after the auth storage migration.web/src/api/endpoints/providers.ts (1)
172-191: LGTM!The
pullModelfunction correctly usessessionStoragefor auth token retrieval and cleanup on 401, consistent with the migration inclient.ts.web/src/__tests__/api/client-bypass.test.ts (1)
4-34: LGTM!Test correctly updated to use
sessionStoragefor setup, cleanup, and assertions. The test logic properly validates that the dev auth bypass prevents storage clearing on 401.web/src/api/client.ts (2)
22-41: LGTM!The security commentary is comprehensive and accurately describes the sessionStorage trade-offs. The tab-scoped storage limitation is clearly documented, and the migration to sessionStorage provides meaningful security benefits (tokens don't persist across sessions or leak to other tabs).
48-53: LGTM!The 401 handler correctly clears all three auth-related
sessionStoragekeys synchronously before the Zustand cleanup, preventing stale-token retries.web/src/__tests__/stores/auth.test.ts (5)
40-52: LGTM!The
resetStore()helper correctly clearssessionStorageand the store state, ensuring proper test isolation after the auth storage migration.
61-74: LGTM!Tests correctly updated to assert
sessionStoragepersistence for token and expiry.
76-112: LGTM!
clearAuthtests correctly verify that all three auth keys are removed fromsessionStorage.
171-198: LGTM!
fetchUsertests properly verifysessionStorageinteractions for themust_change_passwordflag and 401 cleanup.
210-236: LGTM!
changePasswordandlogouttests correctly assertsessionStoragekey management.web/src/stores/auth.ts (7)
1-6: LGTM!Docstring correctly updated to reflect the tab-scoped storage behavior.
56-71: LGTM!
getInitialToken()correctly reads fromsessionStorageand cleans up expired/invalid tokens. The early return on valid token and cleanup of all three keys on invalid state is well-structured.
78-86: LGTM!Token expiry scheduling correctly reads the expiry timestamp from
sessionStoragefor restored tokens.
121-142: LGTM!
_mustChangePasswordFallbackinitialization andsetToken()correctly usesessionStoragefor persistence.
144-160: LGTM!
clearAuth()correctly removes all three auth-related keys fromsessionStorageand maintains the redirect logic.
170-194: LGTM!
fetchUser()correctly persists/clears themust_change_passwordflag insessionStoragebased on the user's state.
196-214: LGTM!
changePassword()correctly clears themust_change_passwordflag fromsessionStoragewhen the password change succeeds.web/src/__tests__/api/client.test.ts (3)
4-6: LGTM!Comment accurately reflects the sessionStorage migration, and the mock hoisting requirement is correctly documented.
190-208: LGTM!Request interceptor tests correctly verify the sessionStorage-based token injection. The
afterEachcleanup is appropriate, and test names clearly describe the behavior under test.
210-251: LGTM!The 401 interceptor tests comprehensively verify the sessionStorage clearing behavior:
- All three auth-related keys are correctly cleared on 401 responses
- Non-401 errors properly preserve the auth token
- Using
sessionStorage.clear()inafterEachis appropriate given the multi-key setupweb/src/pages/workflow-editor/workflow-to-yaml.ts (2)
11-12: LGTM: Well-defined discriminated type for dependency entries.The
DependsOnEntrytype cleanly models the mixed-format YAML output (plain string vs object with branch metadata), enabling type-safe consumption by callers.
117-134: LGTM: Dependency serialization with explicit branch metadata.The logic correctly:
- Emits
{ id, branch: 'true' }forconditional_trueedges- Emits
{ id, branch: 'false' }forconditional_falseedges- Falls back to plain string for sequential/parallel_branch edges
This ensures round-trip fidelity with the parser's explicit-branch handling.
One minor observation: the
edges.find()on line 124 is O(E) per incoming edge, but this is acceptable for typical workflow sizes and keeps the code readable.web/src/pages/workflow-editor/yaml-to-nodes.ts (2)
38-38: LGTM: Extended type supports both legacy and new dependency formats.The expanded type
(string | number | { id: string; branch?: string })[]correctly handles:
- Backward-compatible string/number entries
- New object entries with optional branch metadata
228-247: LGTM: Robust parsing of mixed dependency entry formats.The parsing logic correctly handles all valid entry shapes:
- Objects with
idand optionalbranch- Plain strings and numbers (coerced to strings)
- Invalid shapes trigger errors
The warning for unrecognized branch values (line 240) provides helpful feedback while preserving backward compatibility via fallback inference.
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts (1)
8-30: LGTM: Clean helper factories for test fixtures.The
makeNodeandmakeEdgehelpers provide a concise way to construct test fixtures with sensible defaults while allowing customization of edge types and branch metadata.web/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts (2)
7-13: LGTM: Clean helper for edge lookup.The
findEdgehelper provides a simple way to locate edges by source/target, making assertions readable.
15-134: Excellent coverage of the newdepends_onparsing behavior.The tests comprehensively validate:
- Backward compatibility with plain string dependencies
- Explicit
branch: 'true'andbranch: 'false'handling- Mixed string/object dependency arrays
- Counter-based inference fallback
The inference test (lines 110-134) correctly verifies that two sequential string dependencies from a conditional source alternate between
conditional_trueandconditional_false.src/synthorg/config/schema.py (1)
28-28: LGTM!The
PerformanceConfigintegration intoRootConfigis correctly implemented:
- Import is properly placed
- Field uses
default_factoryfor the nested Pydantic model- Docstring accurately describes the field's purpose (quality judge, CI/LLM weights, trend thresholds)
PerformanceConfigalready enforcesfrozen=Trueandallow_inf_nan=Falseper coding guidelinesAlso applies to: 567-568, 681-684
src/synthorg/persistence/workflow_execution_repo.py (1)
87-103: LGTM!The new
find_by_task_idprotocol method is well-defined:
- Clear contract: searches only RUNNING executions for a node containing the task ID
- Proper type hints with
NotBlankStrfor the identifier- Google-style docstring with Args, Returns, and Raises sections
- Return type correctly handles the not-found case with
Nonetests/unit/config/test_loader.py (1)
360-375: LGTM!The round-trip test is well-constructed:
- Covers the key
performanceconfig fields (quality judge, weights, data points)- Uses test-prefixed vendor names (
test-judge-001,test-provider) per coding guidelines- Weight values (0.3 + 0.7 = 1.0) satisfy the
PerformanceConfigsum validator- Follows the existing test patterns in
TestLoadConfigFromStringsrc/synthorg/config/defaults.py (1)
41-41: LGTM!The
"performance": {}entry is correctly placed in alphabetical/logical order (matchingRootConfigfield sequence), and the empty dict allowsPerformanceConfigto apply its defaults during Pydantic validation.tests/unit/persistence/test_protocol.py (1)
416-420: LGTM!The fake implementation correctly satisfies the
WorkflowExecutionRepositoryprotocol by adding thefind_by_task_idmethod with matching signature. The existingtest_fake_workflow_exec_repo_is_workflow_execution_repositorytest (lines 611-616) verifies protocol compliance viaisinstancecheck.src/synthorg/api/app.py (1)
785-790: LGTM!This is the critical wiring change that fulfills the PR objective:
effective_config.performanceis now passed to_build_performance_tracker, ensuring YAML-driven quality scoring settings (quality judge model/provider, CI/LLM weights) are respected at startup instead of using hardcoded defaults.CLAUDE.md (1)
99-99: LGTM!Documentation accurately reflects the PR's implementation changes:
- "background observer dispatch" documents the new
_observer_queueand_observer_dispatch_loopinTaskEngine- "(compound AND/OR/NOT)" documents the new tokenizer + recursive-descent parser for condition expressions with precedence handling
src/synthorg/engine/workflow/execution_service.py (1)
697-702: LGTM!Excellent refactoring that replaces the O(R×N) in-memory scan with a single repository call. The previous implementation fetched all RUNNING executions and iterated through
node_executionsin Python; now the SQLite implementation can usejson_each()+ status index for efficient lookup. The method contract is preserved while delegating the complexity to the persistence layer.tests/unit/config/test_schema.py (1)
511-537: Performance config schema tests are well-targeted.These assertions cover both defaults and explicit overrides for
RootConfig.performanceas expected.tests/unit/config/conftest.py (1)
28-28: Factory wiring forperformanceis correct.Good update to keep
RootConfigFactoryaligned with the new schema field.Also applies to: 105-105
tests/unit/engine/workflow/test_execution_lifecycle.py (1)
111-121:find_by_task_idfake implementation looks good.The RUNNING-status filter and deep-copy return are consistent with expected repo behavior.
tests/unit/engine/workflow/test_execution_service.py (1)
109-119: Repository fake update is aligned with the new lookup path.Good addition for exercising
_find_execution_by_taskvia repository delegation.src/synthorg/observability/events/task_engine.py (1)
24-25: New observer event constants are a good addition.This cleanly supports structured logging for queue-full and drain-timeout observer scenarios.
tests/unit/api/fakes_workflow.py (1)
6-6: Nice fix to the fake workflow execution repository.The runtime enum import and
find_by_task_idimplementation are both correct for the updated service path.Also applies to: 95-105
src/synthorg/observability/events/persistence.py (1)
294-299: Persistence event coverage for task-based lookup is solid.These constants complete structured logging support for find-by-task success/failure paths.
tests/unit/engine/test_task_engine_observers.py (2)
119-119: Good synchronization additions around observer assertions.Waiting for dispatcher progress before asserting observer side effects is the right test pattern.
Also applies to: 181-181, 209-209, 248-248
256-295: Strong coverage for the non-blocking observer requirement.This test captures the intended background-dispatch behavior well.
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (3)
src/synthorg/engine/workflow/condition_eval.py (2)
115-142:⚠️ Potential issue | 🟠 MajorComparison values containing operator words still break parsing.
_has_compound_operators()and_tokenize()split onAND|OR|NOTbefore recognizing a full comparison atom, sostatus == ORandtitle == Research AND Developmentstill route through the compound parser and evaluate incorrectly. The new note documents the limitation, but the workflow can still take the wrong branch at runtime.Also applies to: 221-223
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workflow/condition_eval.py` around lines 115 - 142, The tokenizer currently splits on AND/OR/NOT even when those words are inside comparison values; update _tokenize and the compound-detection logic so comparison expressions are recognized as single atoms before keyword splitting: modify _tokenize to first scan for comparison operators (e.g., ==, !=, <=, >=, <, >) and treat the entire "lhs operator rhs" span as one token (so values like "OR" or "Research AND Development" remain inside the comparison atom), and adjust _has_compound_operators to operate on these comparison-aware tokens (or run the comparison-atom pass first) so compound parsing only triggers for true logical operators outside comparison atoms; reference _tokenize and _has_compound_operators to locate the changes.
189-210:⚠️ Potential issue | 🟠 MajorMalformed compound expressions still succeed on a valid prefix.
_parse_atom_token()returns(False, pos)for missing operands and unclosed groups instead of signaling a parse error. That means inputs liketrue ORor(a == 1are accepted when the prefix is truthy, because_evaluate_inner()only rejects trailing tokens.Also applies to: 292-302
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workflow/condition_eval.py` around lines 189 - 210, _pars e_atom_token currently masks malformed expressions by returning (False, pos) for missing operands and unclosed groups, allowing prefixes to be treated as valid; change it (and the similar logic around lines 292-302) so that instead of returning a benign False you raise a clear parse exception (e.g., ValueError or a new ParseError) when you encounter end-of-input after an operator, an unclosed '(' or a bare operator token, and let that exception propagate out of _parse_or/_parse_and/_evaluate_inner so callers reject malformed inputs rather than silently accepting valid prefixes.web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts (1)
76-94:⚠️ Potential issue | 🟡 MinorAdd a positive assertion for the plain-string dependency form here.
not.toContain('branch:')only proves branch metadata is absent. This test would still pass if thedepends_onentry were dropped entirely or emitted in the wrong non-branch shape.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts` around lines 76 - 94, Test currently only asserts absence of branch metadata; update the assertion to positively verify the plain-string dependency form produced by generateYamlPreview for parallel_branch edges: assert the generated yaml contains a depends_on key and the plain string items for the branch targets (e.g., contains "depends_on:" and the list entries for "a" and "b") so the test ensures depends_on wasn't dropped and is emitted as plain strings rather than branch objects.
🤖 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/security.md`:
- Line 88: Update the "JWT storage" table row to qualify the sessionStorage
claim: note that sessionStorage is tab-scoped but a newly opened window created
via window.open() can inherit an initial copy from the opener, so tokens may be
exposed to such child tabs unless the opener is suppressed; recommend using
rel="noopener" or window.open(..., 'noopener')/window.open(url, '_blank',
'noopener') (or the equivalent noopener option) to prevent this transfer, and
mention that cookie-based httpOnly auth is still a planned future enhancement.
In `@src/synthorg/engine/task_engine.py`:
- Around line 187-191: stop() currently uses
self._observer_queue.put_nowait(None) which can raise QueueFull and abort
shutdown before _drain_observer() runs; change this to use the async put so the
sentinel is enqueued reliably (replace put_nowait(None) with await
self._observer_queue.put(None) inside the stop() coroutine) or otherwise handle
QueueFull by awaiting until space is available, ensuring any QueueFull is
caught/awaited so _drain_observer() is always reached.
- Around line 763-774: The observer loop can break early because stop() clears
_running before _drain_processing() finishes, so if processing enqueues more
events later the dispatcher will exit and leave them stranded; change the
shutdown ordering so _drain_processing() completes before clearing the
loop-running flag (i.e. have stop() await self._drain_processing() or set a
dedicated _stopping/_drain_complete event and only set _running = False after
draining), and/or modify the timeout branch in the loop to check the
drain-completion flag (not just _running) before breaking; reference stop(),
_drain_processing(), _running, and _observer_queue to locate the relevant
changes.
In `@src/synthorg/engine/workflow/condition_eval.py`:
- Around line 78-100: _summary: Bare-key lookups in _eval_atom now use
context.get and silently return False for missing keys, hiding misconfigurations
that should raise a KeyError/WorkflowConditionEvalError._
In _eval_atom, stop using context.get(expr) for bare-key lookups; instead access
the key so a missing name raises the KeyError that the production caller (the
workflow activation helper that treats KeyError as a workflow-condition failure)
can catch and convert to a WorkflowConditionEvalError; i.e., detect bare
identifiers after comparisons and either return bool(context[expr]) or
explicitly raise the appropriate WorkflowConditionEvalError/KeyError when expr
is not present in context so missing workflow context is not silently treated as
False.
In `@web/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts`:
- Around line 110-127: Update the test "falls back to counter inference for
object without branch" in yaml-to-nodes.test.ts so that the depends_on entries
use the object form instead of strings: replace the depends_on string entries
for yes_step and no_step with object-form entries like "- { id: check }" (i.e.,
use { id: check } for each depends_on item) so the test covers the branchless
object-form path used by the YAML-to-nodes conversion logic.
In `@web/src/pages/workflow-editor/yaml-to-nodes.ts`:
- Around line 261-278: The bug is that conditionalBranchCounters is incremented
for every explicit branch value, causing legacy implicit dependencies to become
desynchronized when an explicit 'false' is seen; change the explicit-branch
handling so you only advance the counter when the explicitBranch indicates the
true branch. Concretely, in the explicitBranch !== undefined branch (where you
set edgeType and check sourceStep.type), only call
conditionalBranchCounters.set(depId, branchIdx + 1) when sourceStep.type ===
'conditional' && sourceStep.step.condition && explicitBranch === 'true' (leave
the existing counter increment in the fallback/implicit branch logic unchanged);
this preserves behavior for explicit true branches while keeping explicit false
from shifting the legacy counter used by inferDependsOnEdgeType.
---
Duplicate comments:
In `@src/synthorg/engine/workflow/condition_eval.py`:
- Around line 115-142: The tokenizer currently splits on AND/OR/NOT even when
those words are inside comparison values; update _tokenize and the
compound-detection logic so comparison expressions are recognized as single
atoms before keyword splitting: modify _tokenize to first scan for comparison
operators (e.g., ==, !=, <=, >=, <, >) and treat the entire "lhs operator rhs"
span as one token (so values like "OR" or "Research AND Development" remain
inside the comparison atom), and adjust _has_compound_operators to operate on
these comparison-aware tokens (or run the comparison-atom pass first) so
compound parsing only triggers for true logical operators outside comparison
atoms; reference _tokenize and _has_compound_operators to locate the changes.
- Around line 189-210: _pars e_atom_token currently masks malformed expressions
by returning (False, pos) for missing operands and unclosed groups, allowing
prefixes to be treated as valid; change it (and the similar logic around lines
292-302) so that instead of returning a benign False you raise a clear parse
exception (e.g., ValueError or a new ParseError) when you encounter end-of-input
after an operator, an unclosed '(' or a bare operator token, and let that
exception propagate out of _parse_or/_parse_and/_evaluate_inner so callers
reject malformed inputs rather than silently accepting valid prefixes.
In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts`:
- Around line 76-94: Test currently only asserts absence of branch metadata;
update the assertion to positively verify the plain-string dependency form
produced by generateYamlPreview for parallel_branch edges: assert the generated
yaml contains a depends_on key and the plain string items for the branch targets
(e.g., contains "depends_on:" and the list entries for "a" and "b") so the test
ensures depends_on wasn't dropped and is emitted as plain strings rather than
branch objects.
🪄 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: c9fc3b12-d4f8-41cd-99a9-d976adfb89b5
📒 Files selected for processing (15)
docs/design/engine.mddocs/security.mdsrc/synthorg/config/schema.pysrc/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.pysrc/synthorg/observability/events/condition_eval.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.pysrc/synthorg/persistence/workflow_execution_repo.pytests/unit/config/test_loader.pytests/unit/engine/test_task_engine_observers.pytests/unit/engine/workflow/test_execution_service.pytests/unit/observability/test_events.pyweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.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 Backend
- GitHub Check: Build Sandbox
- GitHub Check: Build Web
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Python 3.14+ required; nofrom __future__ import annotations(PEP 649 native lazy annotations)
Use PEP 758 except syntax:except A, B:(no parentheses) -- ruff enforces this on Python 3.14
Type hints required on all public functions; mypy strict mode enforced
Docstrings in Google style, required on all public classes and functions (enforced by ruff D rules)
Create new objects, never mutate existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
Fordict/listfields in frozen Pydantic models, rely onfrozen=Truefor field reassignment prevention andcopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state. Never mix static config fields with mutable runtime fields in one model.
Pydantic v2: useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields at validation time
Use@computed_fieldfor derived values in Pydantic models instead of storing + validating redundant fields (e.g.TokenUsage.total_tokens)
UseNotBlankStr(fromcore.types) for all identifier/name fields in Pydantic models -- 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.
Line length: 88 characters (ruff enforced)
Functions must be < 50 lines, files < 800 lines
Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Files:
tests/unit/observability/test_events.pysrc/synthorg/observability/events/condition_eval.pytests/unit/config/test_loader.pysrc/synthorg/config/schema.pysrc/synthorg/persistence/workflow_execution_repo.pytests/unit/engine/test_task_engine_observers.pysrc/synthorg/engine/workflow/condition_eval.pytests/unit/engine/workflow/test_execution_service.pysrc/synthorg/engine/task_engine.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Vendor names in test files must usetest-provider,test-small-001, etc.
Test markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow
Coverage minimum 80% enforced in CI
Async testing:asyncio_mode = "auto"in conftest -- no manual@pytest.mark.asyncioneeded
Default timeout: 30 seconds per test (global inpyproject.toml). Non-default overrides liketimeout(60)are allowed but avoid adding per-file markers.
Prefer@pytest.mark.parametrizefor testing similar cases in Python tests
Property-based testing in Python: use Hypothesis (@given+@settings). Profiles intests/conftest.py:ci(deterministic, 10 examples),dev(1000 examples),fuzz(10,000 examples, no deadline),extreme(500,000 examples). Controlled viaHYPOTHESIS_PROFILEenv var.
When Hypothesis finds a failure, 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 fundamentally. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep(). For indefinite blocking, useasyncio.Event().wait()instead ofasyncio.sleep(large_number).
Files:
tests/unit/observability/test_events.pytests/unit/config/test_loader.pytests/unit/engine/test_task_engine_observers.pytests/unit/engine/workflow/test_execution_service.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/observability/test_events.pytests/unit/config/test_loader.pytests/unit/engine/test_task_engine_observers.pytests/unit/engine/workflow/test_execution_service.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 stdlibloggingandprint(..., file=sys.stderr)for handler construction
Logger variable name must always belogger(not_logger, notlog)
Event names: always use constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
Structured kwargs in logging: 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 level
DEBUG logging for object creation, internal flow, entry/exit of key functions
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. Vendor names allowed only in: Operations design page,.claude/files, third-party import paths, andsrc/synthorg/providers/presets.py
Files:
src/synthorg/observability/events/condition_eval.pysrc/synthorg/config/schema.pysrc/synthorg/persistence/workflow_execution_repo.pysrc/synthorg/engine/workflow/condition_eval.pysrc/synthorg/engine/task_engine.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.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/observability/events/condition_eval.pysrc/synthorg/config/schema.pysrc/synthorg/persistence/workflow_execution_repo.pysrc/synthorg/engine/workflow/condition_eval.pysrc/synthorg/engine/task_engine.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.py
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
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
web/src/**/*.{ts,tsx}: Web dashboard: 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.
Web dashboard: design token rules enforced by PostToolUse hook (scripts/check_web_design_system.py)
TypeScript/JavaScript: Node.js 22+, TypeScript 6.0+, ESLint with zero warnings enforced onweb/src/**/*.{ts,tsx}
Web dashboard YAML parsing: usejs-yamllibrary (in package.json)
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.ts
web/src/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
React testing: use fast-check for property-based testing (
fc.assert+fc.property)
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Web dashboard styling: Tailwind CSS 4 for utility classes; never hardcode pixel values or colors
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.ts
🧠 Learnings (64)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Git commits: `<type>: <description>` -- types: feat, fix, refactor, docs, test, chore, perf, ci (enforced by commitizen)
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...
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)
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to src/ai_company/!(observability)/**/*.py : Use event name constants from domain-specific modules under `ai_company.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
tests/unit/observability/test_events.pysrc/synthorg/observability/events/condition_eval.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 src/**/*.py : Use event name constants from domain-specific modules under ai_company.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.) — import directly
Applied to files:
tests/unit/observability/test_events.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:
tests/unit/observability/test_events.pysrc/synthorg/observability/events/condition_eval.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 : 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 synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
tests/unit/observability/test_events.pysrc/synthorg/observability/events/condition_eval.py
📚 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/**/*.py : Always use event name constants from the domain-specific module under `synthorg.observability.events` in logging calls
Applied to files:
tests/unit/observability/test_events.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 event name constants from synthorg.observability.events domain-specific modules (e.g., PROVIDER_CALL_START from events.provider). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT.
Applied to files:
src/synthorg/observability/events/condition_eval.py
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`
Applied to files:
src/synthorg/observability/events/condition_eval.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under synthorg.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.
Applied to files:
src/synthorg/observability/events/condition_eval.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 : Always use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`); import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`
Applied to files:
src/synthorg/observability/events/condition_eval.py
📚 Learning: 2026-03-18T21:23:23.586Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T21:23:23.586Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from the domain-specific module under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api, TOOL_INVOKE_START from events.tool). Import directly from synthorg.observability.events.<domain>.
Applied to files:
src/synthorg/observability/events/condition_eval.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/observability/events/condition_eval.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 : Always 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 rather than using string literals
Applied to files:
src/synthorg/observability/events/condition_eval.py
📚 Learning: 2026-04-01T20:43:51.878Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T20:43:51.878Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.{ts,tsx,css} : Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions in web code — use design tokens and `@/lib/motion` presets
Applied to files:
docs/security.md
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard: ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones. NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.
Applied to files:
docs/security.md
📚 Learning: 2026-03-31T14:31:11.894Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:31:11.894Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets
Applied to files:
docs/security.md
📚 Learning: 2026-03-31T14:31:11.894Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:31:11.894Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
Applied to files:
docs/security.md
📚 Learning: 2026-03-30T10:20:08.544Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:20:08.544Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from web/src/components/ui/ (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast/ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem, Drawer, form fields, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor) before creating new components
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use density-aware tokens (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing
Applied to files:
docs/security.md
📚 Learning: 2026-03-27T22:32:26.927Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T22:32:26.927Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Applied to files:
docs/security.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:
src/synthorg/config/schema.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/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:
src/synthorg/config/schema.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/config/schema.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/config/schema.pytests/unit/engine/test_task_engine_observers.pysrc/synthorg/engine/task_engine.pydocs/design/engine.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:
src/synthorg/config/schema.pysrc/synthorg/engine/task_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: 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: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).
Applied to files:
src/synthorg/config/schema.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/config/schema.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/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.
Applied to files:
src/synthorg/config/schema.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/config/schema.pysrc/synthorg/engine/task_engine.pydocs/design/engine.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: 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/config/schema.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : For tasks that must block indefinitely until cancelled (e.g. simulating a slow provider or stubborn coroutine), use `asyncio.Event().wait()` instead of `asyncio.sleep(large_number)` -- it is cancellation-safe
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to tests/**/*.py : NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally; mock `time.monotonic()` and `asyncio.sleep()` for determinism; use `asyncio.Event().wait()` for indefinite blocking instead of `asyncio.sleep(large_number)`
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : Never skip, dismiss, or ignore flaky tests; fix them fully and fundamentally by mocking `time.monotonic()` and `asyncio.sleep()` for determinism or using `asyncio.Event().wait()` for indefinite blocking
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to tests/**/*.py : NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally. For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to tests/**/*.py : Never skip, dismiss, or ignore flaky tests -- always fix them fundamentally. For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()`. For indefinite blocking, use `asyncio.Event().wait()` instead of `asyncio.sleep(large_number)`.
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : Flaky tests: NEVER skip, dismiss, or ignore flaky tests -- always fix them fully and fundamentally. For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-16T10:40:25.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T10:40:25.144Z
Learning: Applies to tests/**/*.py : Async testing: asyncio_mode = 'auto' — no manual pytest.mark.asyncio needed.
Applied to files:
tests/unit/engine/test_task_engine_observers.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 : Every module with business logic MUST have `from synthorg.observability import get_logger` followed by `logger = get_logger(__name__)`.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-17T06:43:14.114Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:43:14.114Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging` / `logging.getLogger()` / `print()` in application code. Variable name: always `logger`.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging` / `logging.getLogger()` / `print()` in application code. Variable name: always `logger` (not `_logger`, not `log`).
Applied to files:
src/synthorg/engine/workflow/condition_eval.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 : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use import logging / logging.getLogger() / print() in application code.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-19T11:33:01.580Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:33:01.580Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic must import logger via `from synthorg.observability import get_logger` and initialize with `logger = get_logger(__name__)`
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : All error paths must log at WARNING or ERROR with context before raising. All state transitions must log at INFO. DEBUG for object creation, internal flow, entry/exit of key functions.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/__tests__/**/*.{test,spec}.{ts,tsx} : Vitest unit tests must use coverage scoped to files changed vs origin/main branch
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard YAML parsing: use `js-yaml` library (in package.json)
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.ts
📚 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 web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to **/*.py : Use `except A, B:` (no parentheses) per PEP 758 exception syntax on Python 3.14
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use `except A, B:` syntax (without parentheses) per PEP 758 for exception handling in Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for exception handling — PEP 758 exception syntax enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Use PEP 758 except syntax with `except A, B:` (no parentheses) for multiple exceptions—ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Handle errors explicitly; never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Handle errors explicitly, never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) — enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Handle errors explicitly—never silently swallow exceptions.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) -- ruff enforces this on Python 3.14
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use PEP 758 except syntax: use `except A, B:` (no parentheses) — ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: Import from `storybook/test` instead of `storybook/test`
Applied to files:
web/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.
Applied to files:
web/src/pages/workflow-editor/yaml-to-nodes.ts
🔇 Additional comments (10)
src/synthorg/config/schema.py (3)
28-28: LGTM!The
PerformanceConfigimport is correctly placed and follows the existing import organization pattern.
93-98: Documentation improvements look good.The cost field descriptions now correctly reference "base currency" instead of hardcoded "USD", and the subscription_token description is more accurate. No functional changes.
Also applies to: 185-185
567-568: LGTM!The
performancefield is correctly added following the established pattern:
- Uses
default_factory=PerformanceConfigfor proper frozen model initialization- Docstring comprehensively documents the field's purpose (quality judge, CI/LLM weights, trend thresholds)
- Integrates properly with
_build_performance_trackerinapp.pywhich receiveseffective_config.performanceAlso applies to: 681-684
tests/unit/config/test_loader.py (2)
4-4: LGTM!The refactored test helper is cleaner and more readable:
Neverreturn type correctly indicates the function always raises- Direct
raise PermissionError(msg)is simpler than the previous generator-based pattern- Proper typing with
*a: object, **kw: objectto match any call signatureAlso applies to: 69-76
362-378: LGTM!The round-trip test is well-designed:
- Validates the YAML
performance:section is correctly parsed and populated inRootConfig.performance- Uses compliant vendor-neutral names (
test-judge-001,test-provider)- Weight values (0.3 + 0.7 = 1.0) satisfy the
PerformanceConfigvalidator constraint- Covers the key fields consumed by
_build_performance_tracker:quality_judge_model,quality_judge_provider,quality_ci_weight,quality_llm_weightThis directly validates the
#1061objective to ensure the YAML loader parses theperformance:section.src/synthorg/persistence/sqlite/workflow_execution_repo.py (1)
30-31: Repository-level task lookup looks correct.Scoping the query to
RUNNING, reusing_deserialize_row(), and logging hit/miss/error paths gives the service the fast lookup it needed without losing observability context.Also applies to: 418-474
tests/unit/engine/workflow/test_execution_service.py (1)
95-121: The fake repository now matches the new contract well.Deep-copying returned executions and adding
find_by_task_id()keeps the tests isolated while exercising the same lookup path the service now uses.web/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts (1)
15-108: Coverage is strong across explicit branches, warnings, and invalid shapes.These cases exercise backward-compatible strings, explicit
true/falsemetadata, mixed arrays, unrecognized-branch warnings, and malformed dependency inputs.Also applies to: 136-195
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts (1)
53-74: Conditional branch serialization is covered well.This checks both branch polarities and the quoted
'true'/'false'values the exporter is supposed to emit.docs/design/engine.md (1)
220-222: The design doc now reflects the new runtime contracts clearly.The updated sections document explicit branch metadata, boolean-expression precedence, and the observer queue’s best-effort dispatch and shutdown behavior in a way that matches the implementation changes in this PR.
Also applies to: 265-271, 370-430
| def _eval_atom( | ||
| expr: str, | ||
| context: Mapping[str, object], | ||
| ) -> bool: | ||
| """Evaluate a single atomic expression (no compound operators). | ||
|
|
||
| Handles boolean literals, comparisons, and key lookups. | ||
| """ | ||
| expr = expr.strip() | ||
| if not expr: | ||
| return False | ||
|
|
||
| lower = expr.lower() | ||
| if lower == "true": | ||
| return True | ||
| if lower == "false": | ||
| return False | ||
|
|
||
| result = _eval_comparison(expr, context) | ||
| if result is not None: | ||
| return result | ||
|
|
||
| return bool(context.get(expr)) |
There was a problem hiding this comment.
Bare-key lookups now hide missing workflow context.
_eval_atom() switched has_budget-style expressions to context.get(), so absent keys silently evaluate to False. The only production caller in src/synthorg/engine/workflow/execution_activation_helpers.py:185-196 still treats KeyError as a workflow-condition failure, so this turns a misconfigured workflow into the false branch instead of a WorkflowConditionEvalError.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/workflow/condition_eval.py` around lines 78 - 100,
_summary: Bare-key lookups in _eval_atom now use context.get and silently return
False for missing keys, hiding misconfigurations that should raise a
KeyError/WorkflowConditionEvalError._
In _eval_atom, stop using context.get(expr) for bare-key lookups; instead access
the key so a missing name raises the KeyError that the production caller (the
workflow activation helper that treats KeyError as a workflow-condition failure)
can catch and convert to a WorkflowConditionEvalError; i.e., detect bare
identifiers after comparisons and either return bool(context[expr]) or
explicitly raise the appropriate WorkflowConditionEvalError/KeyError when expr
is not present in context so missing workflow context is not silently treated as
False.
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/synthorg/engine/workflow/condition_eval.py (1)
237-273:⚠️ Potential issue | 🟠 MajorMove normalization inside the guarded path.
Line 259 calls
expression.strip()before thetry. If malformed workflow data passesNoneor any other non-string here, this raisesAttributeErrorbefore the WARNING log and before the fail-closed behavior; the main caller insrc/synthorg/engine/workflow/execution_activation_helpers.py:185-196does not catch that exception either.🛡️ Proposed fix
- expr = expression.strip() - if not expr: - return False - try: + if not isinstance(expression, str): + raise TypeError("Condition expression must be a string") + expr = expression.strip() + if not expr: + return False return _evaluate_inner(expr, context) except MemoryError, RecursionError: raise🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workflow/condition_eval.py` around lines 237 - 273, The call to expression.strip() happens before the try, so non-string inputs (e.g. None) raise AttributeError before the parse-error guard; move normalization into the guarded path inside evaluate_condition: remove the top-level expr = expression.strip() and the pre-try empty check, and inside the try block compute expr = expression.strip() only when isinstance(expression, str) else expr = "" (or otherwise coerce safely), then proceed to call _evaluate_inner(expr, context); ensure the except Exception logging/return False behavior remains unchanged so malformed/non-string inputs fail closed and are logged.
♻️ Duplicate comments (1)
src/synthorg/engine/workflow/condition_eval.py (1)
22-29:⚠️ Potential issue | 🟠 MajorDon’t paper over the comparison regression with documentation.
The new note is accurate about the current behavior, but
_has_compound_operators()and_tokenize()still splitstatus == OR,title == Research AND Development, andlabel == Draft (v2)into boolean syntax. Those used to be valid simple comparisons; now they fail closed and can send a workflow down the wrong branch. The parser needs to keep fulllhs == rhs/lhs != rhsatoms opaque until operators outside the comparison are identified.Also applies to: 115-142, 223-231
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workflow/condition_eval.py` around lines 22 - 29, The parser currently splits operator words inside comparison values because _has_compound_operators() and _tokenize() eagerly tokenize AND/OR/NOT everywhere; change the tokenizer to first recognize and consume full comparison atoms (patterns matching lhs (==|!=) rhs, including rhs containing spaces and operator words or parens) and treat those atoms as single opaque tokens, then only run compound-operator splitting on the remaining token stream; update _has_compound_operators() to detect operators only outside these comparison-atom tokens so expressions like "status == OR", "title == Research AND Development", and "label == Draft (v2)" remain single comparison atoms.
🤖 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/workflow/condition_eval.py`:
- Around line 37-45: The function evaluate_condition() uses Mapping in its type
hints but Mapping is only imported inside the TYPE_CHECKING guard, which causes
typing.get_type_hints() to raise NameError under PEP 649; fix this by removing
the TYPE_CHECKING-only import and importing Mapping unconditionally at the
top-level (i.e., bring Mapping out of the TYPE_CHECKING block), delete the
guarded import, and ensure the runtime namespace contains Mapping so
evaluate_condition(), typing.get_type_hints, and related runtime introspection
work correctly.
In `@tests/unit/engine/workflow/test_condition_eval.py`:
- Around line 157-315: The TestCompoundConditions class repeats many cases that
only change the expression, context and expected result; refactor by replacing
groups of individual tests with pytest.mark.parametrize tests that call
evaluate_condition, e.g. create parameterized tables for AND cases, OR cases,
NOT cases, precedence/parentheses cases, edge cases and the complex expressions,
keeping the existing test names as parameter set ids where useful; update test
functions (e.g. test_and_..., test_or_..., test_not_..., test_precedence,
test_parens, test_edge_cases, test_complex_expression) to accept parameters
(expression, ctx, expected) and assert evaluate_condition(expression, ctx) is
expected, ensuring you preserve special cases like nested parens and malformed
input.
In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts`:
- Around line 79-95: The test constructs an impossible graph by using a node of
type 'parallel_branch' instead of the real split node type; update the fixture
so the fork node is created with makeNode('fork', 'parallel_split') and ensure
edges still use the 'parallel_branch' edge type; then assert the YAML uses the
split step's branches field (e.g., contains 'branches:' and branch entries)
rather than expecting child 'depends_on' strings — adjust expectations around
generateYamlPreview(nodes, edges, 'test', 'agile') accordingly to validate
correct parallel_split export.
- Around line 70-73: The current assertions on the generated yaml use
document-wide regexes and can pass without verifying a { id, branch } entry
inside a step's depends_on; instead parse the YAML string into an object
(yaml.parse or similar) and assert against the specific step's depends_on
structure (e.g., locate the dependent step by name in the parsed object and
check that its depends_on contains an entry with id: 'check' and branch:
true/false). Update the assertions that use expect(yaml).toMatch(/id:\s*check/)
and expect(yaml).toMatch(/branch:.../) to inspect the parsed object (the yaml
variable and its depends_on property) and make the same change for the other
test block referenced (lines 113-115).
In `@web/src/pages/workflow-editor/yaml-to-nodes.ts`:
- Around line 236-240: The code treats branch values as strings but YAML
booleans are parsed as booleans, so change handling to normalize obj.branch to a
string before checking: compute a branchStr = obj.branch !== undefined ?
String(obj.branch) : undefined (or use typeof check to preserve undefined), then
check branchStr === 'true' || branchStr === 'false' and assign explicitBranch =
branchStr; update the warnings to use String(obj.branch) for unrecognized
values. Apply the same normalization patch to the other branch-handling block
later in the file (the block around the 261–274 logic) so both places
consistently handle boolean and string branch values (use the same
branchStr/local variable names to locate the code).
---
Outside diff comments:
In `@src/synthorg/engine/workflow/condition_eval.py`:
- Around line 237-273: The call to expression.strip() happens before the try, so
non-string inputs (e.g. None) raise AttributeError before the parse-error guard;
move normalization into the guarded path inside evaluate_condition: remove the
top-level expr = expression.strip() and the pre-try empty check, and inside the
try block compute expr = expression.strip() only when isinstance(expression,
str) else expr = "" (or otherwise coerce safely), then proceed to call
_evaluate_inner(expr, context); ensure the except Exception logging/return False
behavior remains unchanged so malformed/non-string inputs fail closed and are
logged.
---
Duplicate comments:
In `@src/synthorg/engine/workflow/condition_eval.py`:
- Around line 22-29: The parser currently splits operator words inside
comparison values because _has_compound_operators() and _tokenize() eagerly
tokenize AND/OR/NOT everywhere; change the tokenizer to first recognize and
consume full comparison atoms (patterns matching lhs (==|!=) rhs, including rhs
containing spaces and operator words or parens) and treat those atoms as single
opaque tokens, then only run compound-operator splitting on the remaining token
stream; update _has_compound_operators() to detect operators only outside these
comparison-atom tokens so expressions like "status == OR", "title == Research
AND Development", and "label == Draft (v2)" remain single comparison atoms.
🪄 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: 25c897b6-d5e7-431b-b1d6-6a18ae23c703
📒 Files selected for processing (7)
docs/security.mdsrc/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.pytests/unit/engine/workflow/test_condition_eval.pyweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.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 Backend
- GitHub Check: Build Sandbox
- 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 (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
web/src/**/*.{ts,tsx}: Web dashboard: 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.
Web dashboard: design token rules enforced by PostToolUse hook (scripts/check_web_design_system.py)
TypeScript/JavaScript: Node.js 22+, TypeScript 6.0+, ESLint with zero warnings enforced onweb/src/**/*.{ts,tsx}
Web dashboard YAML parsing: usejs-yamllibrary (in package.json)
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
web/src/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
React testing: use fast-check for property-based testing (
fc.assert+fc.property)
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Web dashboard styling: Tailwind CSS 4 for utility classes; never hardcode pixel values or colors
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Python 3.14+ required; nofrom __future__ import annotations(PEP 649 native lazy annotations)
Use PEP 758 except syntax:except A, B:(no parentheses) -- ruff enforces this on Python 3.14
Type hints required on all public functions; mypy strict mode enforced
Docstrings in Google style, required on all public classes and functions (enforced by ruff D rules)
Create new objects, never mutate existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
Fordict/listfields in frozen Pydantic models, rely onfrozen=Truefor field reassignment prevention andcopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state. Never mix static config fields with mutable runtime fields in one model.
Pydantic v2: useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields at validation time
Use@computed_fieldfor derived values in Pydantic models instead of storing + validating redundant fields (e.g.TokenUsage.total_tokens)
UseNotBlankStr(fromcore.types) for all identifier/name fields in Pydantic models -- 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.
Line length: 88 characters (ruff enforced)
Functions must be < 50 lines, files < 800 lines
Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Files:
src/synthorg/engine/task_engine.pytests/unit/engine/workflow/test_condition_eval.pysrc/synthorg/engine/workflow/condition_eval.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 stdlibloggingandprint(..., file=sys.stderr)for handler construction
Logger variable name must always belogger(not_logger, notlog)
Event names: always use constants from domain-specific modules undersynthorg.observability.events(e.g.,API_REQUEST_STARTEDfromevents.api). Import directly:from synthorg.observability.events.<domain> import EVENT_CONSTANT
Structured kwargs in logging: 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 level
DEBUG logging for object creation, internal flow, entry/exit of key functions
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. Vendor names allowed only in: Operations design page,.claude/files, third-party import paths, andsrc/synthorg/providers/presets.py
Files:
src/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.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/task_engine.pysrc/synthorg/engine/workflow/condition_eval.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Vendor names in test files must usetest-provider,test-small-001, etc.
Test markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow
Coverage minimum 80% enforced in CI
Async testing:asyncio_mode = "auto"in conftest -- no manual@pytest.mark.asyncioneeded
Default timeout: 30 seconds per test (global inpyproject.toml). Non-default overrides liketimeout(60)are allowed but avoid adding per-file markers.
Prefer@pytest.mark.parametrizefor testing similar cases in Python tests
Property-based testing in Python: use Hypothesis (@given+@settings). Profiles intests/conftest.py:ci(deterministic, 10 examples),dev(1000 examples),fuzz(10,000 examples, no deadline),extreme(500,000 examples). Controlled viaHYPOTHESIS_PROFILEenv var.
When Hypothesis finds a failure, 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 fundamentally. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep(). For indefinite blocking, useasyncio.Event().wait()instead ofasyncio.sleep(large_number).
Files:
tests/unit/engine/workflow/test_condition_eval.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/workflow/test_condition_eval.py
🧠 Learnings (38)
📓 Common learnings
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...
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)
📚 Learning: 2026-04-01T20:43:51.878Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T20:43:51.878Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.{ts,tsx,css} : Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions in web code — use design tokens and `@/lib/motion` presets
Applied to files:
docs/security.md
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard: ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones. NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.
Applied to files:
docs/security.md
📚 Learning: 2026-03-31T14:31:11.894Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:31:11.894Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
Applied to files:
docs/security.md
📚 Learning: 2026-03-31T14:31:11.894Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:31:11.894Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Applied to files:
docs/security.md
📚 Learning: 2026-03-30T10:20:08.544Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:20:08.544Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from web/src/components/ui/ (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast/ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem, Drawer, form fields, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor) before creating new components
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use density-aware tokens (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing
Applied to files:
docs/security.md
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing
Applied to files:
docs/security.md
📚 Learning: 2026-03-27T22:32:26.927Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T22:32:26.927Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Applied to files:
docs/security.md
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard YAML parsing: use `js-yaml` library (in package.json)
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/__tests__/**/*.{test,spec}.{ts,tsx} : Vitest unit tests must use coverage scoped to files changed vs origin/main branch
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 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 web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: Import from `storybook/test` instead of `storybook/test`
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 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/task_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 : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Applied to files:
src/synthorg/engine/task_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/task_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/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:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to **/*.py : Use `except A, B:` (no parentheses) per PEP 758 exception syntax on Python 3.14
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use `except A, B:` syntax (without parentheses) per PEP 758 for exception handling in Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for exception handling — PEP 758 exception syntax enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Use PEP 758 except syntax with `except A, B:` (no parentheses) for multiple exceptions—ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Handle errors explicitly; never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Handle errors explicitly, never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) — enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Handle errors explicitly—never silently swallow exceptions.
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use PEP 758 except syntax: use `except A, B:` (no parentheses) — ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) -- ruff enforces this on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.
Applied to files:
web/src/pages/workflow-editor/yaml-to-nodes.ts
📚 Learning: 2026-03-30T10:41:40.176Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:41:40.176Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: import from `storybook/test` (not `storybook/test`), `storybook/actions` (not `storybook/addon-actions`)
Applied to files:
web/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.ts
📚 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 : Every module with business logic MUST have `from synthorg.observability import get_logger` followed by `logger = get_logger(__name__)`.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-17T06:43:14.114Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:43:14.114Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging` / `logging.getLogger()` / `print()` in application code. Variable name: always `logger`.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use `import logging` / `logging.getLogger()` / `print()` in application code. Variable name: always `logger` (not `_logger`, not `log`).
Applied to files:
src/synthorg/engine/workflow/condition_eval.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 : Every module with business logic MUST have: `from synthorg.observability import get_logger` then `logger = get_logger(__name__)`. Never use import logging / logging.getLogger() / print() in application code.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-19T11:33:01.580Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:33:01.580Z
Learning: Applies to src/synthorg/**/*.py : Every module with business logic must import logger via `from synthorg.observability import get_logger` and initialize with `logger = get_logger(__name__)`
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : All error paths must log at WARNING or ERROR with context before raising. All state transitions must log at INFO. DEBUG for object creation, internal flow, entry/exit of key functions.
Applied to files:
src/synthorg/engine/workflow/condition_eval.py
🔇 Additional comments (9)
docs/security.md (1)
88-88: Security caveat is now correctly documented.Line 88 now accurately qualifies
sessionStoragebehavior withwindow.openopener inheritance and includes concretenoopenermitigations plus the planned httpOnly-cookie direction.src/synthorg/engine/task_engine.py (8)
1-7: LGTM!The docstring update accurately describes the decoupled observer dispatch architecture, and the new event constant imports are appropriate for the added logging.
Also applies to: 56-58
123-126: LGTM!Bounded observer queue prevents unbounded memory growth. Using the same
max_queue_sizeas the mutation queue is a reasonable default for the decoupled dispatch model.
163-166: LGTM!The observer dispatch loop is correctly spawned as a sibling background task alongside the mutation processing loop.
187-193: Correct shutdown ordering addresses prior review concerns.The changes properly address both prior review comments:
- Uses
await self._observer_queue.put(None)instead ofput_nowait(None), preventingQueueFullfrom aborting shutdown.- Sentinel is placed only after
_drain_processing()completes, ensuring all mutation-generated events are enqueued before signaling the observer loop to exit.
197-226: LGTM!The
asyncio.shield+ explicit cancel pattern provides controlled shutdown, and theBaseExceptionhandler ensures in-flight futures are resolved on unexpected errors.
228-246: LGTM!Consistent drain pattern with proper timeout handling. The warning log with
remainingqueue size enables monitoring of dropped observer events, which aligns with the documented best-effort semantics.
723-733: LGTM!Non-blocking
put_nowaitwithQueueFullfallback ensures observer slowness never blocks the mutation pipeline—aligning with the PR objective. The warning log with full context enables monitoring for dropped events.
758-786: LGTM!The dispatch loop correctly relies on the sentinel (not
_runningflag) to exit, ensuring all enqueued events are processed before shutdown. This addresses the prior concern about premature dispatcher exit. Exception handling maintains best-effort semantics while propagating catastrophic errors.
| from typing import TYPE_CHECKING | ||
|
|
||
| from synthorg.observability import get_logger | ||
| from synthorg.observability.events.condition_eval import ( | ||
| CONDITION_EVAL_PARSE_ERROR, | ||
| ) | ||
|
|
||
| if TYPE_CHECKING: | ||
| from collections.abc import Mapping |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n src/synthorg/engine/workflow/condition_eval.py | head -80Repository: Aureliolo/synthorg
Length of output: 3380
🏁 Script executed:
rg -A 10 "def evaluate_condition" src/synthorg/engine/workflow/condition_eval.pyRepository: Aureliolo/synthorg
Length of output: 503
Import Mapping at runtime under the Python 3.14 baseline.
evaluate_condition() is a public API with type hints referencing Mapping, which exists only in the TYPE_CHECKING block. Under PEP 649, calling typing.get_type_hints() on this function will raise NameError because Mapping is not in the runtime namespace. Import Mapping unconditionally and drop the guard.
♻️ Proposed fix
import re
-from typing import TYPE_CHECKING
+from collections.abc import Mapping
from synthorg.observability import get_logger
from synthorg.observability.events.condition_eval import (
CONDITION_EVAL_PARSE_ERROR,
)
-
-if TYPE_CHECKING:
- from collections.abc import Mapping
logger = get_logger(__name__)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/workflow/condition_eval.py` around lines 37 - 45, The
function evaluate_condition() uses Mapping in its type hints but Mapping is only
imported inside the TYPE_CHECKING guard, which causes typing.get_type_hints() to
raise NameError under PEP 649; fix this by removing the TYPE_CHECKING-only
import and importing Mapping unconditionally at the top-level (i.e., bring
Mapping out of the TYPE_CHECKING block), delete the guarded import, and ensure
the runtime namespace contains Mapping so evaluate_condition(),
typing.get_type_hints, and related runtime introspection work correctly.
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
Outdated
Show resolved
Hide resolved
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts`:
- Line 46: The test declares a local variable named `yaml` which shadows the
imported `js-yaml` module; rename the test variable (e.g., to `output`) where
`generateYamlPreview(nodes, edges, 'test', 'agile')` is assigned and update any
subsequent assertions/usages to that new name so it no longer conflicts with the
`js-yaml` import and matches the naming used in other tests.
🪄 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: d45fe575-8b9f-400c-b7e9-9f382a0fd2b0
📒 Files selected for processing (3)
tests/unit/engine/workflow/test_condition_eval.pyweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/pages/workflow-editor/yaml-to-nodes.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). (6)
- GitHub Check: Test (Python 3.14)
- GitHub Check: Dashboard Test
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (5)
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
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
web/src/**/*.{ts,tsx}: Web dashboard: 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.
Web dashboard: design token rules enforced by PostToolUse hook (scripts/check_web_design_system.py)
TypeScript/JavaScript: Node.js 22+, TypeScript 6.0+, ESLint with zero warnings enforced onweb/src/**/*.{ts,tsx}
Web dashboard YAML parsing: usejs-yamllibrary (in package.json)
Files:
web/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Web dashboard styling: Tailwind CSS 4 for utility classes; never hardcode pixel values or colors
Files:
web/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
React testing: use fast-check for property-based testing (
fc.assert+fc.property)
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Python 3.14+ required; nofrom __future__ import annotations(PEP 649 native lazy annotations)
Use PEP 758 except syntax:except A, B:(no parentheses) -- ruff enforces this on Python 3.14
Type hints required on all public functions; mypy strict mode enforced
Docstrings in Google style, required on all public classes and functions (enforced by ruff D rules)
Create new objects, never mutate existing ones. For non-Pydantic internal collections (registries,BaseTool), usecopy.deepcopy()at construction +MappingProxyTypewrapping for read-only enforcement.
Fordict/listfields in frozen Pydantic models, rely onfrozen=Truefor field reassignment prevention andcopy.deepcopy()at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; separate mutable-via-copy models (usingmodel_copy(update=...)) for runtime state. Never mix static config fields with mutable runtime fields in one model.
Pydantic v2: useallow_inf_nan=Falsein allConfigDictdeclarations to rejectNaN/Infin numeric fields at validation time
Use@computed_fieldfor derived values in Pydantic models instead of storing + validating redundant fields (e.g.TokenUsage.total_tokens)
UseNotBlankStr(fromcore.types) for all identifier/name fields in Pydantic models -- 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.
Line length: 88 characters (ruff enforced)
Functions must be < 50 lines, files < 800 lines
Handle errors explicitly, never silently swallow. Validate at system boundaries (user input, external APIs, config files).
Files:
tests/unit/engine/workflow/test_condition_eval.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Vendor names in test files must usetest-provider,test-small-001, etc.
Test markers:@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slow
Coverage minimum 80% enforced in CI
Async testing:asyncio_mode = "auto"in conftest -- no manual@pytest.mark.asyncioneeded
Default timeout: 30 seconds per test (global inpyproject.toml). Non-default overrides liketimeout(60)are allowed but avoid adding per-file markers.
Prefer@pytest.mark.parametrizefor testing similar cases in Python tests
Property-based testing in Python: use Hypothesis (@given+@settings). Profiles intests/conftest.py:ci(deterministic, 10 examples),dev(1000 examples),fuzz(10,000 examples, no deadline),extreme(500,000 examples). Controlled viaHYPOTHESIS_PROFILEenv var.
When Hypothesis finds a failure, 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 fundamentally. For timing-sensitive tests, mocktime.monotonic()andasyncio.sleep(). For indefinite blocking, useasyncio.Event().wait()instead ofasyncio.sleep(large_number).
Files:
tests/unit/engine/workflow/test_condition_eval.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/workflow/test_condition_eval.py
🧠 Learnings (9)
📓 Common learnings
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...
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)
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.
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard YAML parsing: use `js-yaml` library (in package.json)
Applied to files:
web/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.
Applied to files:
web/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/__tests__/**/*.{test,spec}.{ts,tsx} : Vitest unit tests must use coverage scoped to files changed vs origin/main branch
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to tests/**/*.py : Parametrize: Prefer pytest.mark.parametrize for testing similar cases.
Applied to files:
tests/unit/engine/workflow/test_condition_eval.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Prefer `pytest.mark.parametrize` for testing similar cases.
Applied to files:
tests/unit/engine/workflow/test_condition_eval.py
📚 Learning: 2026-03-31T20:29:10.177Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T20:29:10.177Z
Learning: Applies to tests/**/*.py : Prefer `pytest.mark.parametrize` for testing similar cases
Applied to files:
tests/unit/engine/workflow/test_condition_eval.py
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to tests/**/*.py : Prefer `pytest.mark.parametrize` for testing similar cases in Python tests
Applied to files:
tests/unit/engine/workflow/test_condition_eval.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to tests/**/*.py : Test markers: pytest.mark.unit, pytest.mark.integration, pytest.mark.e2e, pytest.mark.slow. Coverage: 80% minimum (enforced in CI).
Applied to files:
tests/unit/engine/workflow/test_condition_eval.py
🔇 Additional comments (6)
tests/unit/engine/workflow/test_condition_eval.py (1)
157-354: Good refactor and coverage expansion for compound condition evaluation.The parametrized structure is cleaner, keeps intent readable, and adds strong edge-case coverage (precedence, malformed inputs, nested parentheses, case-insensitive operators, and double-NOT) without weakening backward-compatibility assertions.
Based on learnings: Applies to tests/**/*.py : Prefer
pytest.mark.parametrizefor testing similar cases in Python tests.web/src/pages/workflow-editor/yaml-to-nodes.ts (4)
38-38: LGTM!The type correctly reflects the new schema supporting plain IDs (string/number) and structured
{ id, branch }objects, withbranchtyped loosely to handle validation at runtime.
75-77: LGTM!The updated docstring clearly documents the new precedence: explicit
branchmetadata takes priority over counter-based inference.
228-247: Well-structured parsing with proper YAML boolean handling.The
String(obj.branch)normalization on line 236 correctly handles the YAML CORE_SCHEMA behavior where unquotedbranch: true/branch: falseare parsed as booleans. This ensures round-trip fidelity with the exporter.
259-281: Correct implementation of explicit branch precedence with proper counter semantics.The logic correctly addresses the prior review concerns:
- Explicit
branchtakes precedence over counter-based inference- Only
explicitBranch === 'true'advances the counter (line 270), so an explicit'false'entry doesn't desynchronize subsequent implicit entries- Warning emitted when explicit branch is applied to non-conditional source (lines 264-266)
This ensures mixed legacy imports (implicit) and new-format imports (explicit) can coexist correctly.
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts (1)
33-136: Well-structured test suite addressing all prior feedback.The tests properly validate the
depends_onexport contract by parsing YAML output and asserting on the actual structure rather than fragile regex matches. Coverage includes sequential, conditional, parallel_split, and mixed edge scenarios—aligning with the PR objectives for explicit{ id, branch }branch metadata support.
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts`:
- Around line 33-136: The tests under generateYamlPreview in
workflow-to-yaml.test.ts are fixture-only but must include property-based tests
using fast-check; add at least one fc.assert(fc.property(...)) that generates
random node/edge graphs and asserts exporter invariants: for conditional edges
produced by generateYamlPreview parsed YAML, depends_on entries for conditional
targets are objects with { id, branch } and for non-conditional edges they are
plain strings without a branch; use generateYamlPreview, yaml.load, and helper
makers (makeNode, makeEdge) to build randomized inputs and check the two
invariants (conditional -> object with branch; non-conditional -> no branch)
inside the property.
🪄 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: 5870a037-f4dc-4c21-8d0e-ccd3c211a562
📒 Files selected for processing (1)
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.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). (13)
- GitHub Check: Dashboard Storybook Build
- GitHub Check: Dashboard Type Check
- GitHub Check: Dashboard Build
- GitHub Check: Dashboard Test
- GitHub Check: Dashboard Lint
- GitHub Check: Type Check
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Build Sandbox
- GitHub Check: Build Preview
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (3)
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
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
web/src/**/*.{ts,tsx}: Web dashboard: 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.
Web dashboard: design token rules enforced by PostToolUse hook (scripts/check_web_design_system.py)
TypeScript/JavaScript: Node.js 22+, TypeScript 6.0+, ESLint with zero warnings enforced onweb/src/**/*.{ts,tsx}
Web dashboard YAML parsing: usejs-yamllibrary (in package.json)
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
React testing: use fast-check for property-based testing (
fc.assert+fc.property)
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Web dashboard styling: Tailwind CSS 4 for utility classes; never hardcode pixel values or colors
Files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
🧠 Learnings (4)
📓 Common learnings
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...
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)
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/__tests__/**/*.{test,spec}.{ts,tsx} : Vitest unit tests must use coverage scoped to files changed vs origin/main branch
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-04-04T15:08:44.009Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T15:08:44.009Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard YAML parsing: use `js-yaml` library (in package.json)
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
🔇 Additional comments (1)
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts (1)
69-79: Good move to parse YAML and assert step-level structure.Validating parsed
workflow_definition.steps[*].depends_on/branchesis robust and directly checks the export contract.Also applies to: 97-107, 125-135
…ring Add performance field to RootConfig so YAML-configured quality scoring settings (quality_judge_model, quality_judge_provider, CI/LLM weights) flow through to _build_performance_tracker at app startup instead of silently falling back to defaults. - Add PerformanceConfig import and field to RootConfig (schema.py) - Add performance entry to default_config_dict (defaults.py) - Wire effective_config.performance into _build_performance_tracker (app.py) - Update RootConfigFactory in test conftest - Add schema tests (defaults + custom) and YAML round-trip test - Document performance config section in operations design spec Closes #1061
Move auth token storage from localStorage to sessionStorage to reduce XSS blast radius. sessionStorage is tab-scoped -- tokens no longer persist across browser sessions or leak to other tabs. Updated all auth-related storage calls in: - stores/auth.ts (token lifecycle, expiry, must_change_password) - api/client.ts (request interceptor, 401 handler) - api/endpoints/providers.ts (SSE auth, 401 handler) - All corresponding test files Non-auth localStorage usage (theme, sidebar, viewport) unchanged. Full HttpOnly cookie migration deferred pending backend CSRF support. Ref #1060
Extend evaluate_condition() to support compound expressions with AND/OR/NOT operators and parenthesized groups, matching the frontend condition builder's capabilities. Implementation uses a tokenizer + recursive descent parser: - Tokenizer splits on word-boundary AND/OR/NOT and parens, preserving comparison atoms (keywords inside values like ORLANDO are not split) - Parser implements precedence: NOT > AND > OR - Quick-path: simple expressions without operators skip tokenization - Never-raise contract preserved (all exceptions caught, return False) 29 new tests covering: AND/OR/NOT, precedence, parenthesized groups, nested parens, case-insensitive operators, keyword-in-value safety, edge cases (empty parens, malformed, trailing operators), complex real-world expressions, and backward compatibility. Ref #1060
Replace O(R*N) full scan in _find_execution_by_task() with a repository-level find_by_task_id() method. The SQLite implementation uses json_each() to search the node_executions JSON column, filtering by RUNNING status first (leverages existing idx_wfe_status index). - Add find_by_task_id to WorkflowExecutionRepository protocol - Add SQLite implementation using json_each + json_extract - Delegate execution_service._find_execution_by_task to repo method - Add structured log events for the new query path - Update all three FakeExecutionRepo implementations in tests Ref #1060
Decouple observer notification from the single-writer mutation pipeline by routing events through a dedicated background queue/dispatcher. The mutation pipeline now enqueues TaskStateChanged events via put_nowait() instead of awaiting observers inline. A dedicated _observer_dispatch_loop (mirroring the existing _processing_loop pattern) dequeues and delivers events to registered observers. Benefits: - Slow observers no longer block task state mutations - Event ordering preserved (FIFO queue) - Graceful shutdown drains the observer queue New test: test_slow_observer_does_not_block_mutations verifies that two mutations complete while a blocked observer holds an event gate. Existing tests updated with _flush_observers() helper for async dispatch. Ref #1060
Extend the YAML workflow schema so depends_on entries support both
plain string IDs and objects with explicit branch metadata:
depends_on:
- step_a # sequential (plain string)
- { id: check, branch: 'true' } # conditional (explicit branch)
Exporter (workflow-to-yaml.ts):
- Emits { id, branch } for conditional_true/conditional_false edges
- Plain strings for sequential edges (unchanged)
Importer (yaml-to-nodes.ts):
- Parses string | { id, branch? } union entries
- Explicit branch field takes precedence over counter-based inference
- Counter-based inference preserved as fallback for backward compat
This fixes the round-trip issue where reordering YAML steps could
flip which successor is the true vs false branch of a conditional.
10 new tests across 2 test files covering: plain string backward
compat, object with branch true/false, mixed entries, counter
fallback, invalid entries, empty id, and exporter branch emission.
Ref #1060
Add missing find_by_task_id to _FakeWorkflowExecutionRepository in test_protocol.py to match the updated WorkflowExecutionRepository protocol. Ref #1060
The _NOW fixture was set to 2026-04-03 which causes sessions to expire after that date, making 5 tests fail when run after April 3. Set _NOW to 2099-01-01 so session expiry is deterministic regardless of wall clock time.
Pre-reviewed by 6 agents, 17 findings addressed: - Fix WorkflowExecutionStatus runtime import in fakes_workflow.py - Add sessionStorage.clear() to 3 missed auth test files - Complete operations.md field table (windows, llm_sampling_model, collaboration_weights) - Add try/except to _observer_dispatch_loop for error resilience - Fix observer shutdown race with _observer_done event signal - Add queue_size to observer QueueFull log warning - Remove duplicate JSDoc block on inferDependsOnEdgeType - Warn on unrecognized branch values in YAML depends_on - Document operator-key-name limitation in condition evaluator - Update CLAUDE.md engine description (observer dispatch, compound) - Add unclosed-paren and double-NOT edge case tests - Trim task_engine.py docstrings to stay under 800-line limit
Main fixed the time-sensitive session store tests by wrapping affected assertions with _patch_now() context manager. Drop our _NOW=2099 approach in favor of main's more targeted fix.
The _observer_done asyncio.Event caused the observer dispatch loop to hang when stop() was not explicitly called (e.g. health tests using TestClient lifespan). The event was never set, so the loop condition 'not _observer_done.is_set()' was always True, preventing loop exit. Revert to the original '_running' flag condition which correctly terminates the loop when the engine shuts down via any path. Keep the try/except error resilience and queue_size log improvements.
…t, and Gemini - condition_eval: add logger + event constants, re-raise MemoryError/RecursionError, reject trailing tokens (malformed->False), fix bare-keyword key lookup, add token count cap, update docstrings, extract _evaluate_inner - task_engine: fix shutdown race with None sentinel on observer queue, extract _drain_processing/_drain_observer helpers (stop() under 50 lines), use remainder timeout for observer drain, add mutation_type to queue-full log, add event context to dispatch loop error log - sqlite/workflow_execution_repo: pass execution ID (not task_id) to _deserialize_row in find_by_task_id - workflow_execution_repo protocol: fix Raises docstring (QueryError) - config/schema: fix USD->base currency, OAuth->Bearer in field descriptions - docs/design/engine.md: update observer mechanism (async dispatch queue), architecture diagram, lifecycle section, condition evaluator (compound ops), YAML export depends_on format - docs/security.md: update JWT storage from localStorage to sessionStorage - yaml-to-nodes.ts: increment branch counter for explicit entries (mixed explicit+implicit fix), warn on explicit branch for non-conditional source - test fixes: _flush_observers fails on timeout, deepcopy in fake list_by_definition, idiomatic raise helper, precise regex, new tests (parallel_branch, unrecognized branch value)
- task_engine: use async put (not put_nowait) for shutdown sentinel to avoid QueueFull aborting stop(); remove early-exit check from observer timeout branch -- loop now exits only on None sentinel - condition_eval: _parse_atom_token raises ValueError for missing operands, unclosed parens, and bare operator tokens (malformed expressions correctly resolve to False via outer handler) - yaml-to-nodes: only advance branch counter for explicit 'true' (not 'false') so mixed explicit+implicit entries stay synchronized - security.md: add window.open() sessionStorage inheritance caveat with noopener recommendation - tests: update unclosed-paren expectation (False, not True), use object form in counter-inference test, add positive assertions for parallel_branch depends_on
- yaml-to-nodes: normalize obj.branch with String() to handle YAML boolean values (true/false parsed as booleans by CORE_SCHEMA) - test_condition_eval: parametrize TestCompoundConditions (AND, OR, NOT, precedence, case, keyword-in-value, edge cases, complex) - workflow-to-yaml tests: use parallel_split node type (not parallel_branch), parse YAML and assert on depends_on structure instead of fragile regex matching
4afb6e1 to
b8050ec
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (4)
tests/unit/engine/test_task_engine_observers.py (1)
18-36:⚠️ Potential issue | 🟠 Major
_flush_observers()still races the active callback.
engine._observer_queue.empty()becomes true as soon as the dispatcher dequeues an event, butsrc/synthorg/engine/task_engine.py:758-786awaits_notify_observers()after that dequeue. This helper can therefore return while the observer is still running, which makes every post-flush assertion scheduler-dependent. Wait on a completion signal (queue.join()paired withtask_done(), or equivalent) instead ofempty().As per coding guidelines,
tests/**/*.py: 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.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/engine/test_task_engine_observers.py` around lines 18 - 36, The helper _flush_observers currently races the active observer callback because it checks engine._observer_queue.empty(); change it to wait for a completion signal instead (use engine._observer_queue.join() or an equivalent awaitable) so the helper only returns after all dequeued events have been fully processed by TaskEngine._notify_observers(); if the dispatcher does not call task_done() for each processed event, update the dispatcher logic in TaskEngine (the dequeue/notify loop) to call engine._observer_queue.task_done() after finishing each notification so queue.join() can reliably await completion; keep the budget/timeout semantics by using asyncio.wait_for(join(), timeout=budget) to raise on timeout.src/synthorg/engine/workflow/condition_eval.py (3)
36-45:⚠️ Potential issue | 🟠 MajorImport
Mappingat runtime under the Python 3.14 baseline.
Mappingis referenced in lazy annotations throughout this module, but it only exists inside theTYPE_CHECKINGblock. Under PEP 649,typing.get_type_hints()onevaluate_condition()or the parser helpers will raiseNameErroronce those annotations are evaluated. Move the import to runtime scope.♻️ Proposed fix
import re -from typing import TYPE_CHECKING +from collections.abc import Mapping from synthorg.observability import get_logger from synthorg.observability.events.condition_eval import ( CONDITION_EVAL_PARSE_ERROR, ) - -if TYPE_CHECKING: - from collections.abc import Mapping logger = get_logger(__name__)As per coding guidelines,
**/*.py: Python: 3.14+ (PEP 649 native lazy annotations).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workflow/condition_eval.py` around lines 36 - 45, The module currently only imports Mapping inside the TYPE_CHECKING block which causes NameError when annotations are evaluated (PEP 649); move the import of Mapping out of the TYPE_CHECKING guard into runtime scope so it is available for evaluate_condition() and any parser helper type annotations referenced by typing.get_type_hints(), ensuring the symbol Mapping is imported alongside other top-level imports in condition_eval.py.
78-100:⚠️ Potential issue | 🟠 MajorKeep missing bare keys distinguishable from falsy values.
bool(context.get(expr))makes an absent context name indistinguishable from legitimate values likeFalse,0, or"". The production activation path insrc/synthorg/engine/workflow/execution_activation_helpers.py:175-196still relies onKeyErrorfrom bare-key lookups to surface a misconfigured workflow asWorkflowConditionEvalError, so this now silently takes the false branch instead of failing fast.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workflow/condition_eval.py` around lines 78 - 100, The current use of bool(context.get(expr)) hides missing keys; update _eval_atom to distinguish absent names from falsy values by checking membership: if expr is present in the provided context (use "if expr in context") return bool(context[expr]); otherwise raise a KeyError (so callers like execution_activation_helpers can detect a missing variable and surface WorkflowConditionEvalError) instead of returning False. Ensure this change is applied inside the _eval_atom function and remove reliance on context.get(expr) for the final lookup.
115-142:⚠️ Potential issue | 🟠 MajorComparison atoms are still split on operator words and parentheses.
_has_compound_operators()routes any standaloneAND/OR/NOT/ paren hit into_tokenize(), and_tokenize()then breaks comparison atoms apart instead of preserving them. Inputs likestatus == OR,title == Research AND Development, orlabel == Ready (Phase 1)now evaluateFalseeven though they were valid simple comparisons before this parser was added. Please recognize full comparison atoms before classifying logical operators, and add regression coverage for those cases.Also applies to: 229-231, 285-286
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/synthorg/engine/workflow/condition_eval.py` around lines 115 - 142, The tokenizer currently splits logical keywords/parentheses inside comparison operands; update _tokenize (and related logic in _has_compound_operators) to first detect and preserve full comparison atoms (i.e., sequences containing a comparison operator such as ==, !=, <, >, <=, >= plus their LHS and RHS) before applying _KEYWORD_RE so that expressions like "status == OR", "title == Research AND Development", and "label == Ready (Phase 1)" are treated as a single atom; adjust the matching order (or add a pre-scan using a comparison-operator regex) so comparison patterns are appended as one token rather than split, and add regression tests covering those three example cases to ensure they remain valid simple comparisons.
🤖 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/workflow/condition_eval.py`:
- Around line 263-273: The broad except in evaluate_condition (wrapping
_evaluate_inner) swallows ValueError/TypeError/KeyError (raised for malformed
syntax) and returns False; update the handler to mirror the activation helper by
re-raising ValueError, TypeError, and KeyError so callers like
evaluate_condition() and the activation path in execution_activation_helpers.py
can convert them into WorkflowConditionEvalError; keep the existing re-raise for
MemoryError and RecursionError, and only catch generic Exception for logging and
returning False for other errors (use expression=expr[:200], exc_info=True as
before).
In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts`:
- Around line 138-205: The property test uses raw "return false" to signal
failures which yields poor diagnostics; update the inner property function to
use Jest expect assertions (e.g. expect(obj.id).toBeDefined(),
expect(obj.branch).toMatch(/^(true|false)$/), expect(typeof dep).toBe('string'),
expect(yesStep).toBeDefined(),
expect(Array.isArray(step.depends_on)).toBe(true), etc.) instead of returning
false so failing cases from generateYamlPreview / yaml.load / steps are reported
with clear messages; keep the same property structure, use the same symbols
(generateYamlPreview, yaml.load, steps, yesStep, noStep, taskCountArb) and
preserve fc.assert(..., { numRuns: 20 }).
In `@web/src/api/endpoints/providers.ts`:
- Around line 184-191: In pullModel, the 401 branch manually clears
sessionStorage but doesn't update the Zustand auth state; modify the 401
handling inside pullModel to call useAuthStore.getState().logout() (matching the
client.ts pattern) so the auth store is cleared and the redirect/state update
occurs — remove or replace the manual sessionStorage.removeItem(...) calls with
the logout call to keep behavior consistent with client.ts.
---
Duplicate comments:
In `@src/synthorg/engine/workflow/condition_eval.py`:
- Around line 36-45: The module currently only imports Mapping inside the
TYPE_CHECKING block which causes NameError when annotations are evaluated (PEP
649); move the import of Mapping out of the TYPE_CHECKING guard into runtime
scope so it is available for evaluate_condition() and any parser helper type
annotations referenced by typing.get_type_hints(), ensuring the symbol Mapping
is imported alongside other top-level imports in condition_eval.py.
- Around line 78-100: The current use of bool(context.get(expr)) hides missing
keys; update _eval_atom to distinguish absent names from falsy values by
checking membership: if expr is present in the provided context (use "if expr in
context") return bool(context[expr]); otherwise raise a KeyError (so callers
like execution_activation_helpers can detect a missing variable and surface
WorkflowConditionEvalError) instead of returning False. Ensure this change is
applied inside the _eval_atom function and remove reliance on context.get(expr)
for the final lookup.
- Around line 115-142: The tokenizer currently splits logical
keywords/parentheses inside comparison operands; update _tokenize (and related
logic in _has_compound_operators) to first detect and preserve full comparison
atoms (i.e., sequences containing a comparison operator such as ==, !=, <, >,
<=, >= plus their LHS and RHS) before applying _KEYWORD_RE so that expressions
like "status == OR", "title == Research AND Development", and "label == Ready
(Phase 1)" are treated as a single atom; adjust the matching order (or add a
pre-scan using a comparison-operator regex) so comparison patterns are appended
as one token rather than split, and add regression tests covering those three
example cases to ensure they remain valid simple comparisons.
In `@tests/unit/engine/test_task_engine_observers.py`:
- Around line 18-36: The helper _flush_observers currently races the active
observer callback because it checks engine._observer_queue.empty(); change it to
wait for a completion signal instead (use engine._observer_queue.join() or an
equivalent awaitable) so the helper only returns after all dequeued events have
been fully processed by TaskEngine._notify_observers(); if the dispatcher does
not call task_done() for each processed event, update the dispatcher logic in
TaskEngine (the dequeue/notify loop) to call engine._observer_queue.task_done()
after finishing each notification so queue.join() can reliably await completion;
keep the budget/timeout semantics by using asyncio.wait_for(join(),
timeout=budget) to raise on timeout.
🪄 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: 508e5640-3b38-454c-b39b-46e4e8348891
📒 Files selected for processing (38)
CLAUDE.mddocs/design/engine.mddocs/design/operations.mddocs/security.mdsrc/synthorg/api/app.pysrc/synthorg/config/defaults.pysrc/synthorg/config/schema.pysrc/synthorg/engine/task_engine.pysrc/synthorg/engine/workflow/condition_eval.pysrc/synthorg/engine/workflow/execution_service.pysrc/synthorg/observability/events/condition_eval.pysrc/synthorg/observability/events/persistence.pysrc/synthorg/observability/events/task_engine.pysrc/synthorg/persistence/sqlite/workflow_execution_repo.pysrc/synthorg/persistence/workflow_execution_repo.pytests/unit/api/fakes_workflow.pytests/unit/config/conftest.pytests/unit/config/test_loader.pytests/unit/config/test_schema.pytests/unit/engine/test_task_engine_observers.pytests/unit/engine/workflow/test_condition_eval.pytests/unit/engine/workflow/test_execution_lifecycle.pytests/unit/engine/workflow/test_execution_service.pytests/unit/observability/test_events.pytests/unit/persistence/test_protocol.pyweb/src/__tests__/api/client-bypass.test.tsweb/src/__tests__/api/client.test.tsweb/src/__tests__/hooks/useAuth.test.tsweb/src/__tests__/hooks/useWebSocket.test.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/__tests__/pages/workflow-editor/yaml-to-nodes.test.tsweb/src/__tests__/router/guards.test.tsxweb/src/__tests__/stores/auth.test.tsweb/src/api/client.tsweb/src/api/endpoints/providers.tsweb/src/pages/workflow-editor/workflow-to-yaml.tsweb/src/pages/workflow-editor/yaml-to-nodes.tsweb/src/stores/auth.ts
| try: | ||
| return _evaluate_inner(expr, context) | ||
| except MemoryError, RecursionError: | ||
| raise | ||
| except Exception: | ||
| logger.warning( | ||
| CONDITION_EVAL_PARSE_ERROR, | ||
| expression=expr[:200], | ||
| exc_info=True, | ||
| ) | ||
| return False |
There was a problem hiding this comment.
Align this blanket handler with the activation helper.
Lines 200-218 now raise ValueError for malformed syntax, but this except Exception immediately collapses that into False. The activation path in src/synthorg/engine/workflow/execution_activation_helpers.py:175-196 still converts ValueError, TypeError, and KeyError from evaluate_condition() into WorkflowConditionEvalError, so malformed workflow definitions will silently take the false edge unless that caller is updated in the same PR.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/workflow/condition_eval.py` around lines 263 - 273, The
broad except in evaluate_condition (wrapping _evaluate_inner) swallows
ValueError/TypeError/KeyError (raised for malformed syntax) and returns False;
update the handler to mirror the activation helper by re-raising ValueError,
TypeError, and KeyError so callers like evaluate_condition() and the activation
path in execution_activation_helpers.py can convert them into
WorkflowConditionEvalError; keep the existing re-raise for MemoryError and
RecursionError, and only catch generic Exception for logging and returning False
for other errors (use expression=expr[:200], exc_info=True as before).
- property test: replace return-false with expect() assertions for clear failure diagnostics in fast-check property - providers.ts: call useAuthStore.getState().logout() on 401 in SSE pullModel handler (matches client.ts interceptor pattern) - task_engine: add task_done() calls in observer dispatch loop; _flush_observers now uses queue.join() for deterministic waiting
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/synthorg/engine/task_engine.py`:
- Around line 123-126: The observer queue (_observer_queue) currently reuses
self._config.max_queue_size; add a separate observer_queue_size field to
TaskEngineConfig (with a sensible default) and use it when constructing
_observer_queue (i.e., replace self._config.max_queue_size with
self._config.observer_queue_size in the TaskEngine initialization), so observer
throughput can be tuned independently from the mutation queue.
- Around line 185-192: Replace deprecated asyncio.get_event_loop() calls inside
stop() with asyncio.get_running_loop() to avoid DeprecationWarning;
specifically, use asyncio.get_running_loop().time() for computing deadline and
observer_budget (the two places currently calling
asyncio.get_event_loop().time()) so the timing logic around deadline, await
self._drain_processing(effective_timeout), and the subsequent await
self._observer_queue.put(None) remains unchanged.
In `@web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts`:
- Around line 72-73: Extract a small helper that centralizes yaml.load(output, {
schema: yaml.CORE_SCHEMA }) and returns the workflow_definition.steps array to
remove duplicated parsing and type assertions; e.g., add a function like
parseWorkflowSteps(output: string) that calls yaml.load with CORE_SCHEMA,
narrows the result to { workflow_definition: { steps: Array<Record<string,
unknown>> } } and returns workflow_definition.steps, then replace each
occurrence of the inline parsing (the `parsed` variable and the `steps`
extraction) in this test file with calls to parseWorkflowSteps(output) (update
call sites at the spots mentioned).
In `@web/src/api/endpoints/providers.ts`:
- Around line 184-198: The 401 SSE handling removes sessionStorage and attempts
to async-import the auth store but the catch only logs the error; mirror
client.ts by adding a fallback redirect in the catch so if importing
'@/stores/auth' fails you also redirect to '/login' (unless already on '/login'
or '/setup'); update the catch in the block that imports useAuthStore (the SSE
401 handling in providers.ts) to log the importErr and then check
window.location.pathname !== '/login' && !== '/setup' and set
window.location.href = '/login' as a fallback.
🪄 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: 95743b39-7cc4-4ec5-b781-4c56da6a8b75
📒 Files selected for processing (4)
src/synthorg/engine/task_engine.pytests/unit/engine/test_task_engine_observers.pyweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/api/endpoints/providers.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). (6)
- GitHub Check: Dashboard Test
- GitHub Check: Test (Python 3.14)
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (8)
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{tsx,ts}: Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions in web code. Use design tokens and@/lib/motionpresets.
Web dashboard: use React 19, TypeScript 6.0+, Tailwind CSS 4, Zustand, shadcn/ui, Radix UI, and other specified dependencies from web/package.json.
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx,js,jsx}: Always usecreateLoggerfrom@/lib/loggerinstead of bareconsole.warn,console.error, orconsole.debugin application code
Use variable namelogfor logger instances (e.g.,const log = createLogger('module-name'))
Uselog.debug()for dev-only logging (stripped in production),log.warn()for warnings, andlog.error()for errors
Pass dynamic/untrusted values as separate arguments to logger calls (not interpolated into the message string) so they go throughsanitizeArg
Wrap attacker-controlled fields inside structured objects withsanitizeForLog()before embedding in logs
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx,css}: Use Tailwind semantic color classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)) instead of hardcoded hex values
Usefont-sansorfont-monofor typography (maps to Geist tokens), never setfontFamilydirectly
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 instead of hardcoded values
Do NOT usergba()with hardcoded values -- use design token variables
A PostToolUse hook (scripts/check_web_design_system.py) runs automatically on every Edit/Write toweb/src/files and catches design system violations; fix all violations before proceeding
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx}: Do NOT hardcode Framer Motion transition durations -- use presets from@/lib/motion
CSS side-effect imports in TypeScript files should use type declarations (/// <reference types="vite/client" />covers this); TypeScript 6 defaultsnoUncheckedSideEffectImportsto true
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.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) for exception handling.
All public functions require type hints. Use mypy strict mode.
Docstrings must use Google style and are required on public classes and functions (enforced by ruff D rules).
Create new objects instead of mutating existing ones. For non-Pydantic internal collections, use copy.deepcopy() at construction and MappingProxyType wrapping for read-only enforcement.
Use frozen Pydantic models for config/identity. Use separate mutable-via-copy models for runtime state that evolves.
Use Pydantic v2 (BaseModel, model_validator, computed_field, ConfigDict). Use allow_inf_nan=False in all ConfigDict declarations.
Use NotBlankStr (from core.types) for all identifier/name fields in Pydantic models.
Use@computed_fieldfor derived values instead of storing and validating redundant fields.
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g., multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare create_task.
Functions must be less than 50 lines and files must be less than 800 lines.
Handle errors explicitly, never silently swallow them.
Validate at system boundaries (user input, external APIs, config files).
Line length: 88 characters (ruff).
Python: 3.14+ (PEP 649 native lazy annotations).
Files:
src/synthorg/engine/task_engine.pytests/unit/engine/test_task_engine_observers.py
src/synthorg/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/synthorg/**/*.py: Every module with business logic must have: from synthorg.observability import get_logger then logger = get_logger(name)
Never use import logging / logging.getLogger() / print() in application code. Exception: observability/setup.py, observability/sinks.py, observability/syslog_handler.py, and observability/http_handler.py may use stdlib logging and print for handler construction.
Logger variable name must always be 'logger' (not '_logger', not 'log').
Use constants from domain-specific modules under synthorg.observability.events for event names (e.g., API_REQUEST_STARTED, TOOL_INVOKE_START). Import directly from synthorg.observability.events..
Always use logger.info(EVENT, key=value) for structured logging. Never use logger.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.
DEBUG logging is used for object creation, internal flow, and entry/exit of key functions.
Never use real vendor names (Anthropic, OpenAI, Claude, GPT) in project-owned code, docstrings, comments, tests, or config examples. Use generic names: example-provider, example-large-001, example-medium-001, example-small-001.
Files:
src/synthorg/engine/task_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/task_engine.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Use@pytest.mark.unit,@pytest.mark.integration,@pytest.mark.e2e,@pytest.mark.slowfor test categorization.
Coverage minimum: 80% (enforced in CI).
Use asyncio_mode = 'auto' for async tests -- no manual@pytest.mark.asyncioneeded.
Prefer@pytest.mark.parametrizefor testing similar cases.
Property-based testing: use Hypothesis (@given+@settings) with profiles configured in tests/conftest.py (ci, dev, fuzz, extreme).
When Hypothesis finds a failure, fix the underlying bug and add an explicit@example(...) decorator to permanently cover the case in CI.
For timing-sensitive tests, mock time.monotonic() and asyncio.sleep() to make them deterministic instead of widening timing margins.
For tasks that must block indefinitely until cancelled, use asyncio.Event().wait() instead of asyncio.sleep(large_number).
Files:
tests/unit/engine/test_task_engine_observers.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_task_engine_observers.py
🧠 Learnings (31)
📚 Learning: 2026-03-27T12:44:29.466Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:44:29.466Z
Learning: Applies to web/src/stores/**/*.{ts,tsx} : Use Zustand stores in web dashboard for state management (auth, WebSocket, toast, analytics, domain shells)
Applied to files:
web/src/api/endpoints/providers.ts
📚 Learning: 2026-03-30T10:41:40.176Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:41:40.176Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use Zustand stores for state management in the web dashboard; each domain has its own store module (auth, WebSocket, toast, analytics, setup, company, agents, budget, tasks, settings, providers, theme, per-domain stores)
Applied to files:
web/src/api/endpoints/providers.ts
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/__tests__/**/*.{test,spec}.{ts,tsx} : Vitest unit tests must use coverage scoped to files changed vs origin/main branch
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 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 web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-30T10:20:08.544Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:20:08.544Z
Learning: Applies to web/**/*.test.{ts,tsx} : Web dashboard: Use React Hypothesis (fast-check) for property-based testing with fc.assert + fc.property
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-30T10:41:40.176Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:41:40.176Z
Learning: Applies to web/src/__tests__/**/*.test.{ts,tsx} : Use property-based testing with fast-check in React tests (`fc.assert` + `fc.property`)
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 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/task_engine.pytests/unit/engine/test_task_engine_observers.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/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:
src/synthorg/engine/task_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/task_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 : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Applied to files:
src/synthorg/engine/task_engine.pytests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to **/*.py : Use `except A, B:` (no parentheses) per PEP 758 exception syntax on Python 3.14
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use `except A, B:` syntax (without parentheses) per PEP 758 for exception handling in Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-04-04T17:42:47.768Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T17:42:47.768Z
Learning: Applies to **/*.py : PEP 758 except syntax: use `except A, B:` (no parentheses) for exception handling.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for exception handling — PEP 758 exception syntax enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Use PEP 758 except syntax with `except A, B:` (no parentheses) for multiple exceptions—ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Handle errors explicitly; never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Handle errors explicitly, never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) — enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Handle errors explicitly—never silently swallow exceptions.
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use PEP 758 except syntax: use `except A, B:` (no parentheses) — ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_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 tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : For tasks that must block indefinitely until cancelled (e.g. simulating a slow provider or stubborn coroutine), use `asyncio.Event().wait()` instead of `asyncio.sleep(large_number)` -- it is cancellation-safe
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-04-04T17:42:47.768Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T17:42:47.768Z
Learning: Applies to tests/**/*.py : For timing-sensitive tests, mock time.monotonic() and asyncio.sleep() to make them deterministic instead of widening timing margins.
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : Never skip, dismiss, or ignore flaky tests; fix them fully and fundamentally by mocking `time.monotonic()` and `asyncio.sleep()` for determinism or using `asyncio.Event().wait()` for indefinite blocking
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-04-04T17:42:47.768Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T17:42:47.768Z
Learning: Applies to tests/**/*.py : For tasks that must block indefinitely until cancelled, use asyncio.Event().wait() instead of asyncio.sleep(large_number).
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to tests/**/*.py : NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally; mock `time.monotonic()` and `asyncio.sleep()` for determinism; use `asyncio.Event().wait()` for indefinite blocking instead of `asyncio.sleep(large_number)`
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to tests/**/*.py : NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally. For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_task_engine_observers.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 tests/**/*.py : Flaky tests: NEVER skip, dismiss, or ignore flaky tests -- always fix them fully and fundamentally. For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-03-16T10:40:25.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T10:40:25.144Z
Learning: Applies to tests/**/*.py : Async testing: asyncio_mode = 'auto' — no manual pytest.mark.asyncio needed.
Applied to files:
tests/unit/engine/test_task_engine_observers.py
📚 Learning: 2026-04-04T17:42:47.768Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T17:42:47.768Z
Learning: Applies to tests/**/*.py : Use asyncio_mode = 'auto' for async tests -- no manual pytest.mark.asyncio needed.
Applied to files:
tests/unit/engine/test_task_engine_observers.py
🔇 Additional comments (10)
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts (3)
55-80: Strong structural assertion for conditionaldepends_onoutput.Parsing YAML and asserting exact
[{ id, branch }]values for bothyes_stepandno_stepis the right level of strictness for this contract.
82-109: Parallel split coverage now validates the correct export path.Great to see this test assert both
fork.branchesand that child steps keep plain-stringdepends_onwithout branch metadata.
138-206: Property-based invariant test is well targeted.This gives solid regression protection for conditional-object vs sequential-string
depends_onencoding across generated graphs.web/src/api/endpoints/providers.ts (1)
172-172: LGTM — sessionStorage migration for auth token retrieval.Correctly switches from
localStoragetosessionStorageas part of the auth token storage migration objective.src/synthorg/engine/task_engine.py (3)
758-789: LGTM - Observer dispatch loop is well-structured.The implementation correctly:
- Uses
task_done()for both sentinel (line 774) and regular events (line 789 in finally)- Re-raises
MemoryError/RecursionErrorper project conventions- Logs exceptions with relevant context without blocking the dispatch loop
197-246: LGTM - Two-phase drain with budget tracking is robust.The shutdown sequence correctly:
- Drains processing loop within budget
- Sends sentinel via
await put()(notput_nowait) per prior feedback- Calculates remaining budget for observer drain
- Handles timeout and cancellation gracefully
713-725: Task is properly frozen — no TOCTOU risk with async observer dispatch.Verification confirms that
Taskis a frozen Pydantic model (line 79 ofsrc/synthorg/core/task.py:model_config = ConfigDict(frozen=True, allow_inf_nan=False)), with all collection fields as immutable tuples. The reference captured inTaskStateChanged.taskcannot be mutated, so observers will see consistent state regardless of async processing timing.tests/unit/engine/test_task_engine_observers.py (3)
18-31: LGTM - Deterministic flush helper usingqueue.join().This correctly addresses the prior review feedback. Using
queue.join()waits until alltask_done()calls complete, ensuring events are fully processed before assertions. The timeout withAssertionErrorprovides clear test failure diagnostics.
257-296: LGTM - Excellent test for decoupled observer dispatch.This test correctly validates that:
- Mutations complete without waiting for slow observers (lines 272-293)
- Uses
asyncio.Event().wait()for cancellation-safe indefinite blocking (per guidelines)- Properly unblocks observer and flushes before teardown to avoid resource leaks
120-123: LGTM - Consistent flush pattern across observer tests.All tests that assert on observer-received events now correctly await
_flush_observers()before assertions, ensuring the background dispatcher has processed all events.Also applies to: 182-184, 210-211, 249-255
| self._observer_queue: asyncio.Queue[TaskStateChanged | None] = asyncio.Queue( | ||
| maxsize=self._config.max_queue_size, | ||
| ) | ||
| self._observer_task: asyncio.Task[None] | None = None |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Observer queue shares max_queue_size with mutation queue.
Both queues use self._config.max_queue_size (default 1000). Consider whether observers warrant a separate configuration parameter — observers are best-effort and may have different throughput characteristics than the mutation pipeline. Under sustained load, 1000 may be too small and cause frequent event drops, or conversely may be unnecessarily large for observer notifications.
This is optional; the current design is reasonable for initial implementation. You could defer adding observer_queue_size to TaskEngineConfig until operational metrics indicate a need.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/task_engine.py` around lines 123 - 126, The observer
queue (_observer_queue) currently reuses self._config.max_queue_size; add a
separate observer_queue_size field to TaskEngineConfig (with a sensible default)
and use it when constructing _observer_queue (i.e., replace
self._config.max_queue_size with self._config.observer_queue_size in the
TaskEngine initialization), so observer throughput can be tuned independently
from the mutation queue.
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
Outdated
Show resolved
Hide resolved
- task_engine: replace get_event_loop() with get_running_loop() in stop() - task_engine_config: add observer_queue_size field with fallback to max_queue_size via effective_observer_queue_size property - providers.ts: add fallback redirect to /login in SSE 401 catch block (mirrors client.ts interceptor pattern) - workflow-to-yaml tests: extract parseSteps() helper to deduplicate YAML parsing across 4 test cases
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/task_engine_config.py`:
- Around line 50-55: The computed property effective_observer_queue_size should
use Pydantic's `@computed_field` so it is included in serialization/schema; update
the decorator stack to have `@computed_field` above `@property` on the
effective_observer_queue_size method and add the repository's mypy ignore
comment (e.g., # type: ignore[override]) on the property to satisfy type
checking, leaving the implementation logic (checking self.observer_queue_size
and falling back to self.max_queue_size) unchanged.
In `@src/synthorg/engine/task_engine.py`:
- Around line 188-194: The shutdown path currently awaits
self._observer_queue.put(None) without bounding it by the remaining shutdown
time, so if the queue is full this can block past the deadline; change the code
in the shutdown sequence to wrap the sentinel enqueue in asyncio.wait_for using
the computed remaining budget (deadline - loop.time()) and catch
asyncio.TimeoutError to skip the put and let _drain_observer handle cancelling
the observer task; specifically modify the block that calls await
self._observer_queue.put(None) (in stop/ shutdown flow) to use
asyncio.wait_for(self._observer_queue.put(None), timeout=remaining_budget) and
handle timeout by not raising and proceeding to await
self._drain_observer(observer_budget).
🪄 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: e64f9aec-0f67-406a-ba92-e6e5958836c4
📒 Files selected for processing (4)
src/synthorg/engine/task_engine.pysrc/synthorg/engine/task_engine_config.pyweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.tsweb/src/api/endpoints/providers.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: Build Sandbox
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Test (Python 3.14)
- GitHub Check: Dashboard Test
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (7)
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{tsx,ts}: Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions in web code. Use design tokens and@/lib/motionpresets.
Web dashboard: use React 19, TypeScript 6.0+, Tailwind CSS 4, Zustand, shadcn/ui, Radix UI, and other specified dependencies from web/package.json.
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx,js,jsx}: Always usecreateLoggerfrom@/lib/loggerinstead of bareconsole.warn,console.error, orconsole.debugin application code
Use variable namelogfor logger instances (e.g.,const log = createLogger('module-name'))
Uselog.debug()for dev-only logging (stripped in production),log.warn()for warnings, andlog.error()for errors
Pass dynamic/untrusted values as separate arguments to logger calls (not interpolated into the message string) so they go throughsanitizeArg
Wrap attacker-controlled fields inside structured objects withsanitizeForLog()before embedding in logs
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx,css}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx,css}: Use Tailwind semantic color classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)) instead of hardcoded hex values
Usefont-sansorfont-monofor typography (maps to Geist tokens), never setfontFamilydirectly
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 instead of hardcoded values
Do NOT usergba()with hardcoded values -- use design token variables
A PostToolUse hook (scripts/check_web_design_system.py) runs automatically on every Edit/Write toweb/src/files and catches design system violations; fix all violations before proceeding
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (web/CLAUDE.md)
web/src/**/*.{ts,tsx}: Do NOT hardcode Framer Motion transition durations -- use presets from@/lib/motion
CSS side-effect imports in TypeScript files should use type declarations (/// <reference types="vite/client" />covers this); TypeScript 6 defaultsnoUncheckedSideEffectImportsto true
Files:
web/src/api/endpoints/providers.tsweb/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.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) for exception handling.
All public functions require type hints. Use mypy strict mode.
Docstrings must use Google style and are required on public classes and functions (enforced by ruff D rules).
Create new objects instead of mutating existing ones. For non-Pydantic internal collections, use copy.deepcopy() at construction and MappingProxyType wrapping for read-only enforcement.
Use frozen Pydantic models for config/identity. Use separate mutable-via-copy models for runtime state that evolves.
Use Pydantic v2 (BaseModel, model_validator, computed_field, ConfigDict). Use allow_inf_nan=False in all ConfigDict declarations.
Use NotBlankStr (from core.types) for all identifier/name fields in Pydantic models.
Use@computed_fieldfor derived values instead of storing and validating redundant fields.
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g., multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare create_task.
Functions must be less than 50 lines and files must be less than 800 lines.
Handle errors explicitly, never silently swallow them.
Validate at system boundaries (user input, external APIs, config files).
Line length: 88 characters (ruff).
Python: 3.14+ (PEP 649 native lazy annotations).
Files:
src/synthorg/engine/task_engine_config.pysrc/synthorg/engine/task_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_logger then logger = get_logger(name)
Never use import logging / logging.getLogger() / print() in application code. Exception: observability/setup.py, observability/sinks.py, observability/syslog_handler.py, and observability/http_handler.py may use stdlib logging and print for handler construction.
Logger variable name must always be 'logger' (not '_logger', not 'log').
Use constants from domain-specific modules under synthorg.observability.events for event names (e.g., API_REQUEST_STARTED, TOOL_INVOKE_START). Import directly from synthorg.observability.events..
Always use logger.info(EVENT, key=value) for structured logging. Never use logger.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.
DEBUG logging is used for object creation, internal flow, and entry/exit of key functions.
Never use real vendor names (Anthropic, OpenAI, Claude, GPT) in project-owned code, docstrings, comments, tests, or config examples. Use generic names: example-provider, example-large-001, example-medium-001, example-small-001.
Files:
src/synthorg/engine/task_engine_config.pysrc/synthorg/engine/task_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/task_engine_config.pysrc/synthorg/engine/task_engine.py
🧠 Learnings (24)
📓 Common learnings
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).
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...
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/__tests__/**/*.{test,spec}.{ts,tsx} : Vitest unit tests must use coverage scoped to files changed vs origin/main branch
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 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 web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-30T10:20:08.544Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:20:08.544Z
Learning: Applies to web/**/*.test.{ts,tsx} : Web dashboard: Use React Hypothesis (fast-check) for property-based testing with fc.assert + fc.property
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-04-02T12:21:16.739Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-02T12:21:16.739Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: Import from `storybook/test` instead of `storybook/test`
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-04-04T17:43:42.372Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-04T17:43:42.372Z
Learning: Applies to web/src/**/*.stories.{ts,tsx} : Use `storybook/test` instead of `storybook/test` and `storybook/actions` instead of `storybook/addon-actions` (Storybook 10 import path changes)
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/*.yml : Dependabot: daily updates for uv + github-actions + npm + pre-commit + docker + gomod, grouped minor/patch, no auto-merge. Use `/review-dep-pr` to review Dependabot PRs before merging.
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 Learning: 2026-03-30T10:41:40.176Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-30T10:41:40.176Z
Learning: Applies to web/src/__tests__/**/*.test.{ts,tsx} : Use property-based testing with fast-check in React tests (`fc.assert` + `fc.property`)
Applied to files:
web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts
📚 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/task_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/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:
src/synthorg/engine/task_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/task_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 : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-31T21:07:37.470Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T21:07:37.470Z
Learning: Applies to **/*.py : Use `except A, B:` (no parentheses) per PEP 758 exception syntax on Python 3.14
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use `except A, B:` syntax (without parentheses) per PEP 758 for exception handling in Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-04-04T17:42:47.768Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T17:42:47.768Z
Learning: Applies to **/*.py : PEP 758 except syntax: use `except A, B:` (no parentheses) for exception handling.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for exception handling — PEP 758 exception syntax enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Use PEP 758 except syntax with `except A, B:` (no parentheses) for multiple exceptions—ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Handle errors explicitly; never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Handle errors explicitly, never silently swallow exceptions
Applied to files:
src/synthorg/engine/task_engine.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 **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) — enforced by ruff on Python 3.14
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Handle errors explicitly—never silently swallow exceptions.
Applied to files:
src/synthorg/engine/task_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 **/*.py : Use PEP 758 except syntax: use `except A, B:` (no parentheses) — ruff enforces this on Python 3.14.
Applied to files:
src/synthorg/engine/task_engine.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 tests/**/*.py : For tasks that must block indefinitely until cancelled (e.g. simulating a slow provider or stubborn coroutine), use `asyncio.Event().wait()` instead of `asyncio.sleep(large_number)` -- it is cancellation-safe
Applied to files:
src/synthorg/engine/task_engine.py
📚 Learning: 2026-04-04T17:42:47.768Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-04T17:42:47.768Z
Learning: Applies to tests/**/*.py : For tasks that must block indefinitely until cancelled, use asyncio.Event().wait() instead of asyncio.sleep(large_number).
Applied to files:
src/synthorg/engine/task_engine.py
🔇 Additional comments (5)
web/src/api/endpoints/providers.ts (2)
172-172: LGTM!Token retrieval correctly migrated from
localStoragetosessionStorage, aligning with the auth token storage changes across the frontend.
186-198: LGTM! 401 handling now fully consistent withclient.ts.The implementation correctly:
- Clears the same three
sessionStoragekeys synchronously before async operations- Uses fire-and-forget dynamic import to avoid circular dependencies
- Includes the fallback redirect in the catch block (addressing the previous review feedback)
- Throws the error after cleanup so callers receive the failure
This matches the axios 401 interceptor pattern in
client.tsexactly.web/src/__tests__/pages/workflow-editor/workflow-to-yaml.test.ts (3)
10-40: Well-factored test helpers and YAML parsing utility.
makeNode,makeEdge, andparseStepsmake the suite easier to extend while keeping assertions focused on exporter behavior.
42-140: Scenario coverage is strong for all dependency modes.These tests clearly exercise sequential, conditional, parallel-split, and mixed graphs against the updated exporter contract.
142-207: Property-based invariant test is correctly implemented.Great use of randomized coverage to enforce conditional-vs-sequential
depends_oninvariants beyond fixed fixtures.
As per coding guidelines,web/src/__tests__/**/*.test.{ts,tsx}: “Use property-based testing with fast-check (fc.assert+fc.property).”
| @property | ||
| def effective_observer_queue_size(self) -> int: | ||
| """Resolved observer queue size (falls back to max_queue_size).""" | ||
| if self.observer_queue_size is not None: | ||
| return self.observer_queue_size | ||
| return self.max_queue_size |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Read the file to examine the complete context around the flagged property
head -70 src/synthorg/engine/task_engine_config.py | tail -40Repository: Aureliolo/synthorg
Length of output: 1432
🏁 Script executed:
# Also check the full file structure and imports
head -30 src/synthorg/engine/task_engine_config.pyRepository: Aureliolo/synthorg
Length of output: 1149
🏁 Script executed:
# Check if computed_field is already imported elsewhere in the file
rg "computed_field|@property" src/synthorg/engine/task_engine_config.py -nRepository: Aureliolo/synthorg
Length of output: 78
🏁 Script executed:
# Verify the Pydantic model class definition and ConfigDict
ast-grep --pattern $'class $NAME(BaseModel) {
$$$
}'Repository: Aureliolo/synthorg
Length of output: 44
🏁 Script executed:
# Check if computed_field is used elsewhere in the codebase to verify the pattern
rg "@computed_field" src/ --type py -A 2 | head -40Repository: Aureliolo/synthorg
Length of output: 2377
🏁 Script executed:
# Verify the file doesn't already import computed_field
grep "computed_field" src/synthorg/engine/task_engine_config.pyRepository: Aureliolo/synthorg
Length of output: 44
🏁 Script executed:
# Check Pydantic version in the project
rg "pydantic" pyproject.toml requirements.txt setup.py 2>/dev/null | head -5Repository: Aureliolo/synthorg
Length of output: 310
Switch to @computed_field with the codebase pattern.
The property effective_observer_queue_size is a derived value and should use Pydantic's @computed_field to be included in serialization and schema. Follow the established repo pattern: stack @computed_field with @property and add the mypy type-ignore comment.
♻️ Proposed fix
-from pydantic import BaseModel, ConfigDict, Field
+from pydantic import BaseModel, ConfigDict, Field, computed_field
...
+ `@computed_field` # type: ignore[prop-decorator]
+ `@property`
def effective_observer_queue_size(self) -> int:📝 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.
| @property | |
| def effective_observer_queue_size(self) -> int: | |
| """Resolved observer queue size (falls back to max_queue_size).""" | |
| if self.observer_queue_size is not None: | |
| return self.observer_queue_size | |
| return self.max_queue_size | |
| `@computed_field` # type: ignore[prop-decorator] | |
| `@property` | |
| def effective_observer_queue_size(self) -> int: | |
| """Resolved observer queue size (falls back to max_queue_size).""" | |
| if self.observer_queue_size is not None: | |
| return self.observer_queue_size | |
| return self.max_queue_size |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/synthorg/engine/task_engine_config.py` around lines 50 - 55, The computed
property effective_observer_queue_size should use Pydantic's `@computed_field` so
it is included in serialization/schema; update the decorator stack to have
`@computed_field` above `@property` on the effective_observer_queue_size method and
add the repository's mypy ignore comment (e.g., # type: ignore[override]) on the
property to satisfy type checking, leaving the implementation logic (checking
self.observer_queue_size and falling back to self.max_queue_size) unchanged.
🤖 I have created a release *beep* *boop* --- ## [0.6.2](v0.6.1...v0.6.2) (2026-04-06) ### Features * add issue analyzer script for priority/scope management ([#1084](#1084)) ([1ccba27](1ccba27)) * config fixes and deferred improvements from PR [#1058](#1058) review ([#1067](#1067)) ([2cac2d3](2cac2d3)), closes [#1061](#1061) [#1060](#1060) * cumulative risk-unit action budgets ([#806](#806)) and automated reporting ([#245](#245)) ([#1063](#1063)) ([4689816](4689816)) * fine-tuning pipeline + CompositeBackend + workflow lifecycle ([#1065](#1065)) ([85b05bc](85b05bc)), closes [#1001](#1001) [#850](#850) [#1058](#1058) * memory consolidation upgrades (LLM Merge, Search-and-Ask, diversity penalty, distillation capture) ([#1071](#1071)) ([174e2be](174e2be)), closes [#704](#704) * migrate web dashboard from Radix UI to Base UI, activate CSP nonce, rebuild org chart page, and fix agent routing ([#1083](#1083)) ([ebc6921](ebc6921)) * v0.7.0 engine foundations -- structured failure diagnosis + auditable decisions ([#1072](#1072)) ([d341d37](d341d37)) * workflow templates and versioning with diff and rollback ([#1069](#1069)) ([7af94de](7af94de)), closes [#1006](#1006) [#1008](#1008) ### Documentation * unify REST API docs under /docs/openapi/ and patch sitemap ([#1073](#1073)) ([af19382](af19382)) ### Maintenance * bump hypothesis from 6.151.10 to 6.151.11 in the all group ([#1086](#1086)) ([3176318](3176318)) * bump nginxinc/nginx-unprivileged from `f99cc61` to `601c823` in /docker/web in the all group ([#1085](#1085)) ([5eb99ac](5eb99ac)) * bump the all group in /web with 3 updates ([#1087](#1087)) ([8deae44](8deae44)) --- 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
Implements #1061 (PerformanceConfig in RootConfig) and all 5 items from #1060 (deferred improvements from PR #1058 review).
Changes
#1061: PerformanceConfig in RootConfig
performance: PerformanceConfigfield toRootConfigwith default factory"performance": {}todefault_config_dict()for YAML merge base layereffective_config.performanceinto_build_performance_trackerincreate_appload_config_from_string#1060.1: JWT localStorage to sessionStorage
localStoragetosessionStorage(tab-scoped)auth.ts,client.ts,providers.ts(SSE auth), and all test files#1060.2: Compound condition evaluator (AND/OR/NOT)
brand == ORLANDOworks correctly)#1060.3: O(1) execution lookup by task_id
find_by_task_idtoWorkflowExecutionRepositoryprotocoljson_each()+json_extract()with status indexexecution_service._find_execution_by_taskwith repo delegation#1060.4: Background observer dispatcher
_observer_queue+_observer_dispatch_loop(mirrors_processing_looppattern)put_nowait()instead of inlineawait _notify_observers()#1060.5: Explicit branch metadata in YAML depends_on
depends_onentries supportstring | { id, branch }union type{ id, branch: "true"|"false" }for conditional edgesAdditional fixes (from pre-PR review)
WorkflowExecutionStatusruntime import infakes_workflow.py(was underTYPE_CHECKING)sessionStorage.clear()to 3 missed auth test reset functionswindows,llm_sampling_model,collaboration_weights)_observer_dispatch_loopqueue_sizeto observerQueueFulllog warninginferDependsOnEdgeTypeTest plan
Closes #1061
Closes #1060