Skip to content

refactor(settings): collapse precedence to three categories; drop YAML tier (closes #1890)#1910

Merged
Aureliolo merged 30 commits into
mainfrom
refactor/config-precedence-three-category
May 14, 2026
Merged

refactor(settings): collapse precedence to three categories; drop YAML tier (closes #1890)#1910
Aureliolo merged 30 commits into
mainfrom
refactor/config-precedence-three-category

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Closes #1890.

Summary

Resolves the four-tier DB > env > YAML > default lie that the docs had advertised for a long time. The codebase actually exhibits three categories:

  • Category 1: Standard mutableDB > env > default via SettingsService / ConfigResolver.
  • Category 2: Read-only post-initenv > default only; DB is bypassed (read_only_post_init=True). Examples: api.server_port, communication.nats_url, workers.count.
  • Category 3: Bootstrap secret — pure env at the boot site, no registry entry. Examples: SYNTHORG_DATABASE_URL, SYNTHORG_JWT_SECRET, SYNTHORG_CONFIG_PATH, SYNTHORG_DB_PATH.

What changes

  • src/synthorg/settings/bootstrap_resolver.py (new): canonical pre-init resolver for Cat-2 reads. Returns BootstrapResolvedValue[T] with source ∈ {ENVIRONMENT, DEFAULT}.
  • src/synthorg/settings/mirrors.py (new): MirrorField dataclass + apply_settings_mirrors Pydantic validator helper, plus typed parsers (parse_bool, parse_int, parse_float, parse_str_tuple_json). Applied across 15+ config families (ApiConfig, AuthConfig, RateLimitConfig, BudgetConfig, AutonomyConfig, CoordinationSectionConfig, CeremonyPolicyConfig, ConsolidationConfig, MeetingsConfig, OAuthConfig, WebhooksConfig, etc.) to eliminate duplicate env reads while keeping Pydantic-tier defaults in sync with the registry.
  • SettingSource.YAML removed; SettingDefinition.yaml_path removed (221 call sites cleaned). YAML is now a company-template ingestion format, not a precedence tier.
  • ServerConfig / CorsConfig mirror fields stripped; values flow through bootstrap_resolver.resolve_init_value at boot.
  • SYNTHORG_WORKER_COUNT renamed to SYNTHORG_WORKERS (Python + Go CLI).
  • docs/reference/configuration-precedence.md rewritten to document the three categories with examples and rationale. CLAUDE.md MANDATORY one-liner updated.
  • New gate: scripts/check_setting_to_startup_trace.py (ghost-wiring detector, mirrors the persistence-boundary gate pattern).

Test plan

  • uv run ruff check src/ tests/ clean.
  • uv run mypy src/ tests/ clean (3791 files).
  • Full Python test suite: 26068 passed / 10 skipped (one unrelated xdist worker crash in test_heartbeat_repository[sqlite] which passes in isolation; no code overlap with this PR).
  • Focused suites green: tests/unit/settings/ (627 tests), tests/unit/api/test_app.py, tests/unit/api/test_app_bootstrap_resolvers.py (new), tests/unit/api/test_config.py (with new TestRateLimitConfigMirrors), tests/unit/workers/test_main.py.
  • Web: lint, type-check, 3141 unit tests pass.
  • CLI: go -C cli vet ./... + go -C cli test ./cmd/... clean.

Review coverage

Pre-reviewed by 20 local agents (full roster plus 5 mini-pass audit agents). Triage filed at _audit/pre-pr-review/triage.md. All 16 actionable findings (3 CRITICAL / 9 MAJOR / 4 MEDIUM) addressed in this PR; security / persistence / async-concurrency / logging / conventions / mini-pass agents reported clean.

Highlights of fixes applied during the pre-PR pass:

  • CLI SYNTHORG_WORKER_COUNT rename was missed; now matches Python backend.
  • web/src/api/types/settings.ts still declared yaml_path after the backend dropped it; stripped from the type and from 10 test/story/mock fixtures.
  • _resolve_api_int / a2a_client_timeout / _resolve_api_str_tuple passed bare int/float/_parse_str_tuple_json to resolve_init_value; bad env input would have crashed app construction with ValueError. Switched to the typed parsers in settings.mirrors so invalid env values fall through to the registered default.
  • Dedup: dropped duplicate _parse_bool_token / _parse_str_tuple_json helpers from api/app.py in favour of the canonical helpers in settings.mirrors.
  • Stripped three RFC #1890 in-code back-references (mirrors module docstring + two test docstrings).
  • Stale "env / YAML" / "YAML layer" wording removed from settings/models.py docstring, docs/reference/environment-variables.md, and docs/reference/configuration-precedence.md.
  • New direct unit tests: TestRateLimitConfigMirrors (6 cases) + test_app_bootstrap_resolvers.py (11 cases) covering env-set / env-unset / env-invalid for each resolver.

Run /aurelio-review-pr after external reviewers (CodeRabbit) provide feedback.

Aureliolo added 27 commits May 14, 2026 20:25
- CLI: rename SYNTHORG_WORKER_COUNT to SYNTHORG_WORKERS in worker
  start command to match the Python backend rename.
- web/types/settings: drop yaml_path from SettingDefinition and 10
  test/story/mock fixtures; derive SettingSource from a const tuple
  so the SourceBadge exhaustive-coverage test stays in lockstep.
- settings/models: drop "env / YAML" wording from the
  read_only_post_init docstring and field description.
- docs/reference/environment-variables: drop two stale "YAML layer"
  references in the override precedence wording.
- docs/reference/configuration-precedence: replace stale service.py
  line citations with a code-shape reference.
- mirrors / conftest / workers test: drop three RFC #1890 in-code
  back-references.
- api/app: switch _resolve_api_int, _resolve_api_str_tuple,
  _resolve_rate_limiter_enabled, and the inline a2a_client_timeout
  resolve_init_value site to the typed parsers in settings.mirrors
  (parse_int, parse_float, parse_bool, parse_str_tuple_json) so a
  bad env value falls through to the registered default instead of
  crashing app construction with ValueError.
- api/app: drop the duplicate _parse_str_tuple_json and
  _parse_bool_token helpers; reuse the canonical helpers from
  settings.mirrors.
- auth/config, coordination/section_config, workflow/ceremony_policy:
  drop redundant only_if_env_set=True inline comments now that
  MirrorField docstring covers the three sentinel meanings.
- New tests: TestRateLimitConfigMirrors (6 cases) for the
  RateLimitConfig._apply_mirrors path, and a dedicated
  test_app_bootstrap_resolvers module (11 cases) covering
  env-set / env-unset / env-invalid for each api.* resolver.

Pre-reviewed by 20 agents; 16/16 findings addressed.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

Dependency Review

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

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

Review Change Stack

Warning

Rate limit exceeded

@Aureliolo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 53 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b14b639b-1b7b-4863-aa13-3e4345d7dbb4

📥 Commits

Reviewing files that changed from the base of the PR and between 1c94d92 and e614346.

📒 Files selected for processing (1)
  • src/synthorg/settings/bootstrap_resolver.py

Walkthrough

Removes YAML from the settings precedence chain, formalizing DB > env > default. Introduces a bootstrap resolver and a mirrors mechanism, then applies mirrors across many configuration models. Rewires API/server/middleware and provider management to resolve settings at boot via the resolver. Updates observability setup to use the resolver. Adjusts tooling to use setting_key instead of yaml_path. Renames the workers env var to SYNTHORG_WORKERS. Updates docs, types, stories, and extensive unit/integration tests to the new contracts.

Suggested labels

autorelease: tagged

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 14, 2026 19:45 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the configuration system to a three-tier precedence model (DB > env > code default), removing the YAML layer and introducing centralized bootstrap_resolver and mirroring utilities. The review feedback identifies several opportunities to improve consistency and safety by replacing local parsing logic and direct environment reads with the new shared helpers, as well as flagging an unsafe integer cast that could lead to application crashes during startup.

Comment thread src/synthorg/api/server.py Outdated
return tuple(item for item in parsed if isinstance(item, str))

host = str(resolve_init_value(SettingNamespace.API, "server_host").value)
port = int(resolve_init_value(SettingNamespace.API, "server_port", parse=int).value)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Using the bare int constructor as a parser is unsafe here. If the environment variable SYNTHORG_API_SERVER_PORT contains an invalid integer (e.g., a typo), int() will raise a ValueError and crash the application during startup. You should use parse_int from synthorg.settings.mirrors, which catches the error and allows the resolver to gracefully fall back to the registered default.

Suggested change
port = int(resolve_init_value(SettingNamespace.API, "server_port", parse=int).value)
port = int(resolve_init_value(SettingNamespace.API, "server_port", parse=parse_int).value)

default = _extract_string(kwargs.get("default"))
read_only = _extract_bool(kwargs.get("read_only_post_init")) is True
yaml_path = _extract_string(kwargs.get("yaml_path")) or f"{namespace}.{key}"
setting_key = _extract_string(kwargs.get("setting_key")) or f"{namespace}.{key}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The attempt to extract setting_key from kwargs appears to be a logic error or leftover from the yaml_path refactoring. setting_key is not a valid field on the SettingDefinition model in src/synthorg/settings/models.py, so it will never be present in the registration calls. Since the system now uses the dotted namespace.key as the unique identifier, this can be simplified to always use the default.

Suggested change
setting_key = _extract_string(kwargs.get("setting_key")) or f"{namespace}.{key}"
setting_key = f"{namespace}.{key}"

Comment thread src/synthorg/api/app_builders.py Outdated
Comment on lines +283 to +290
def _parse_telemetry_enabled_token(raw: str) -> bool | None:
"""Parse a telemetry-enabled env token. Returns ``None`` on unknown values."""
token = normalize_ascii_lowercase(raw)
if token in _TELEMETRY_ENV_TRUE:
return True
if token in _TELEMETRY_ENV_FALSE:
return False
return None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This helper function duplicates the logic of parse_bool now available in synthorg.settings.mirrors. It should be removed in favor of the shared helper to reduce code duplication and ensure consistent boolean parsing across the application.

Comment thread src/synthorg/api/middleware_factory.py Outdated
Comment on lines +261 to +273
def _parse_str_tuple_json(raw: str) -> tuple[str, ...] | None:
"""Parse a JSON-encoded list of strings into a tuple."""
import json # noqa: PLC0415

try:
parsed = json.loads(raw)
except json.JSONDecodeError:
return None
if not isinstance(parsed, list):
return None
if not all(isinstance(item, str) for item in parsed):
return None
return tuple(parsed)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This function is an exact duplicate of parse_str_tuple_json in synthorg.settings.mirrors. It should be removed and the shared helper should be imported instead to maintain consistency.

Comment thread src/synthorg/api/server.py Outdated
Comment on lines +47 to +59
def _str_tuple(key: str) -> tuple[str, ...]:
import json # noqa: PLC0415

resolved = resolve_init_value(SettingNamespace.API, key)
if resolved.source == SettingSource.DEFAULT and not str(resolved.value):
return ()
try:
parsed = json.loads(str(resolved.value))
except json.JSONDecodeError:
return ()
if not isinstance(parsed, list):
return ()
return tuple(item for item in parsed if isinstance(item, str))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This helper duplicates logic that is now centralized in synthorg.settings.mirrors.parse_str_tuple_json. Additionally, its filtering behavior (item for item in parsed if isinstance(item, str)) differs from the canonical parser which rejects the entire input if it contains non-string elements. It is better to use the shared helper for consistency.

Comment thread src/synthorg/workers/__main__.py Outdated
return explicit
env_value = os.environ.get("SYNTHORG_WORKER_COUNT")
env_value = os.environ.get("SYNTHORG_WORKERS")
if env_value is None:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Directly reading os.environ here bypasses the new bootstrap_resolver pattern. To ensure consistency with the project's configuration precedence rules and to centralize the knowledge of environment variable names and defaults, this should use resolve_init_value(SettingNamespace.WORKERS, "count").

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 14, 2026

Merging this PR will not alter performance

✅ 54 untouched benchmarks


Comparing refactor/config-precedence-three-category (e614346) with main (d8ebf55)

Open in CodSpeed

@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

❌ Patch coverage is 94.79554% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.06%. Comparing base (d8ebf55) to head (e614346).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/synthorg/settings/bootstrap_resolver.py 89.74% 3 Missing and 1 partial ⚠️
src/synthorg/api/app_builders.py 78.57% 2 Missing and 1 partial ⚠️
src/synthorg/api/app.py 87.50% 2 Missing ⚠️
src/synthorg/settings/mirrors.py 93.54% 2 Missing ⚠️
src/synthorg/workers/__main__.py 81.81% 1 Missing and 1 partial ⚠️
src/synthorg/api/middleware_factory.py 88.88% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1910      +/-   ##
==========================================
+ Coverage   85.01%   85.06%   +0.05%     
==========================================
  Files        1833     1834       +1     
  Lines      106984   107087     +103     
  Branches     9253     9237      -16     
==========================================
+ Hits        90951    91098     +147     
+ Misses      13799    13758      -41     
+ Partials     2234     2231       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

Repository owner deleted a comment from coderabbitai Bot May 14, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/synthorg/api/config.py (2)

255-280: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update ServerConfig attribute docs to match the actual model.

The docstring still lists host, port, TLS, and trusted_proxies, but those fields are no longer defined on ServerConfig. This creates operator-facing drift and misleading generated documentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/synthorg/api/config.py` around lines 255 - 280, The ServerConfig
docstring lists attributes (host, port, ssl_certfile, ssl_keyfile, ssl_ca_certs,
trusted_proxies, etc.) that no longer exist on the ServerConfig model; update
the docstring in src/synthorg/api/config.py for the ServerConfig class to
reflect the actual attributes defined on ServerConfig (remove obsolete
host/port/TLS/trusted_proxies entries and add any current fields such as
compression_minimum_size_bytes and request_max_body_size_bytes), ensuring the
attribute names and brief descriptions match the model properties used by the
code and generated docs.

316-321: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove YAML-tier wording from rate_limiter_enabled docs.

The current text describes fallback to a “YAML field,” which reads like a precedence tier and conflicts with the three-category model introduced in this PR. Please reword to “configured/default value” language to avoid reintroducing four-tier semantics.

As per coding guidelines, “Configuration precedence: DB > env > code default via SettingsService/ConfigResolver (Cat-1) or env > code default (Cat-2, read_only_post_init); Cat-3 bootstrap secrets are pure env.”

Also applies to: 363-367

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/synthorg/api/config.py` around lines 316 - 321, Update the docstring for
the rate_limiter_enabled registry entry in src/synthorg/api/config.py (the
docblocks around the rate_limiter_enabled description at the current sections
~316 and ~363) to remove any mention of a “YAML field” and instead refer to a
“configured/default value” or similar wording; ensure the text states the
configuration precedence using the three-category model (DB > env > code default
via SettingsService/ConfigResolver for Cat-1, or env > code default for Cat-2
read_only_post_init; Cat-3 bootstrap secrets are pure env) so the docs no longer
imply a four-tier YAML precedence.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/synthorg/settings/bootstrap_resolver.py`:
- Around line 108-117: The current code can return the raw string `default` when
a `parse` function was provided but parsing failed; instead, when `parse` is not
None and `parsed_default` is None, return a BootstrapResolvedValue with
`value=None` (or the appropriate sentinel for "no valid value") rather than the
raw `default` string so callers expecting T don't receive an invalid str; update
the branch in the resolver that handles `parse`/`parsed_default` to return
BootstrapResolvedValue(value=None, source=SettingSource.DEFAULT) (using the
existing BootstrapResolvedValue and SettingSource symbols) instead of falling
through to return the raw `default`.

In `@tests/unit/api/test_app_bootstrap_resolvers.py`:
- Around line 96-109: The test test_invalid_int_falls_through_to_default is too
loose (assert > 0); update it to assert the exact fallback value returned by
_resolve_api_int when SYNTHORG_API_COMPRESSION_MINIMUM_SIZE_BYTES is invalid by
comparing to the module's canonical default (e.g.,
DEFAULT_COMPRESSION_MINIMUM_SIZE_BYTES) instead of > 0; import that constant
from the same module that defines _resolve_api_int and replace the assertion
with equality to that constant so the test fails if the fallback default drifts.

---

Outside diff comments:
In `@src/synthorg/api/config.py`:
- Around line 255-280: The ServerConfig docstring lists attributes (host, port,
ssl_certfile, ssl_keyfile, ssl_ca_certs, trusted_proxies, etc.) that no longer
exist on the ServerConfig model; update the docstring in
src/synthorg/api/config.py for the ServerConfig class to reflect the actual
attributes defined on ServerConfig (remove obsolete
host/port/TLS/trusted_proxies entries and add any current fields such as
compression_minimum_size_bytes and request_max_body_size_bytes), ensuring the
attribute names and brief descriptions match the model properties used by the
code and generated docs.
- Around line 316-321: Update the docstring for the rate_limiter_enabled
registry entry in src/synthorg/api/config.py (the docblocks around the
rate_limiter_enabled description at the current sections ~316 and ~363) to
remove any mention of a “YAML field” and instead refer to a “configured/default
value” or similar wording; ensure the text states the configuration precedence
using the three-category model (DB > env > code default via
SettingsService/ConfigResolver for Cat-1, or env > code default for Cat-2
read_only_post_init; Cat-3 bootstrap secrets are pure env) so the docs no longer
imply a four-tier YAML precedence.
🪄 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: 1c3891f1-a350-4f54-94d9-594180bbf9dd

📥 Commits

Reviewing files that changed from the base of the PR and between d8ebf55 and 78402d9.

📒 Files selected for processing (127)
  • CLAUDE.md
  • cli/cmd/worker_start.go
  • docs/design/providers.md
  • docs/guides/deployment.md
  • docs/guides/human-interaction.md
  • docs/reference/claude-reference.md
  • docs/reference/configuration-precedence.md
  • docs/reference/environment-variables.md
  • scripts/_setting_to_startup_trace_ghosts.py
  • scripts/_setting_to_startup_trace_loader.py
  • scripts/_setting_to_startup_trace_models.py
  • scripts/_setting_to_startup_trace_violations.py
  • scripts/check_setting_to_startup_trace.py
  • src/synthorg/a2a/config.py
  • src/synthorg/api/app.py
  • src/synthorg/api/app_builders.py
  • src/synthorg/api/auto_wire.py
  • src/synthorg/api/config.py
  • src/synthorg/api/middleware_factory.py
  • src/synthorg/api/server.py
  • src/synthorg/budget/config.py
  • src/synthorg/communication/config.py
  • src/synthorg/config/rate_limits.py
  • src/synthorg/config/schema.py
  • src/synthorg/core/auth/config.py
  • src/synthorg/engine/coordination/section_config.py
  • src/synthorg/engine/evolution/config.py
  • src/synthorg/engine/workflow/ceremony_policy.py
  • src/synthorg/integrations/config.py
  • src/synthorg/memory/config.py
  • src/synthorg/memory/consolidation/config.py
  • src/synthorg/observability/events/settings.py
  • src/synthorg/observability/setup.py
  • src/synthorg/providers/management/service.py
  • src/synthorg/security/autonomy/models.py
  • src/synthorg/security/config.py
  • src/synthorg/settings/bootstrap_resolver.py
  • src/synthorg/settings/config_bridge.py
  • src/synthorg/settings/definitions/a2a.py
  • src/synthorg/settings/definitions/api.py
  • src/synthorg/settings/definitions/budget.py
  • src/synthorg/settings/definitions/client.py
  • src/synthorg/settings/definitions/communication.py
  • src/synthorg/settings/definitions/company.py
  • src/synthorg/settings/definitions/coordination.py
  • src/synthorg/settings/definitions/engine.py
  • src/synthorg/settings/definitions/hr.py
  • src/synthorg/settings/definitions/integrations.py
  • src/synthorg/settings/definitions/memory.py
  • src/synthorg/settings/definitions/meta.py
  • src/synthorg/settings/definitions/notifications.py
  • src/synthorg/settings/definitions/observability.py
  • src/synthorg/settings/definitions/providers.py
  • src/synthorg/settings/definitions/security.py
  • src/synthorg/settings/definitions/settings_ns.py
  • src/synthorg/settings/definitions/simulations.py
  • src/synthorg/settings/definitions/telemetry.py
  • src/synthorg/settings/definitions/tools.py
  • src/synthorg/settings/definitions/workers.py
  • src/synthorg/settings/enums.py
  • src/synthorg/settings/mirrors.py
  • src/synthorg/settings/models.py
  • src/synthorg/settings/service.py
  • src/synthorg/workers/__main__.py
  • tests/integration/api/controllers/test_providers.py
  • tests/integration/api/test_first_run_flow.py
  • tests/integration/api/test_per_op_rate_limit_concurrent.py
  • tests/integration/engine/test_coordination_wiring.py
  • tests/integration/settings/test_settings_integration.py
  • tests/unit/a2a/test_client.py
  • tests/unit/api/conftest.py
  • tests/unit/api/controllers/test_activities.py
  • tests/unit/api/controllers/test_agents.py
  • tests/unit/api/controllers/test_analytics.py
  • tests/unit/api/controllers/test_company.py
  • tests/unit/api/controllers/test_coordination.py
  • tests/unit/api/controllers/test_departments.py
  • tests/unit/api/controllers/test_departments_health.py
  • tests/unit/api/controllers/test_provider_health.py
  • tests/unit/api/services/test_org_mutations.py
  • tests/unit/api/services/test_org_mutations_atomic.py
  • tests/unit/api/services/test_org_mutations_toctou.py
  • tests/unit/api/test_app.py
  • tests/unit/api/test_app_bootstrap_resolvers.py
  • tests/unit/api/test_config.py
  • tests/unit/api/test_server.py
  • tests/unit/memory/test_config.py
  • tests/unit/providers/management/conftest.py
  • tests/unit/providers/management/test_service_discovery.py
  • tests/unit/scripts/_setting_to_startup_trace_helpers.py
  • tests/unit/scripts/test_check_setting_to_startup_trace.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_baseline.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_ghosts.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_pattern_a.py
  • tests/unit/settings/test_bootstrap_only_api_entries.py
  • tests/unit/settings/test_bootstrap_resolver.py
  • tests/unit/settings/test_ceremony_settings.py
  • tests/unit/settings/test_config_bridge.py
  • tests/unit/settings/test_definitions_config_bridge.py
  • tests/unit/settings/test_engine_settings.py
  • tests/unit/settings/test_mirrors.py
  • tests/unit/settings/test_models.py
  • tests/unit/settings/test_new_registry_entries.py
  • tests/unit/settings/test_precedence_chain.py
  • tests/unit/settings/test_readonly_init_settings.py
  • tests/unit/settings/test_resolver.py
  • tests/unit/settings/test_service.py
  • tests/unit/settings/test_service_set_many.py
  • tests/unit/settings/test_service_versioned_pipeline.py
  • tests/unit/settings/test_source_resolution_log.py
  • tests/unit/settings/test_subsystem_timeout_entries.py
  • tests/unit/settings/test_url_port_entries.py
  • tests/unit/workers/test_main.py
  • web/src/__tests__/hooks/useSettingsData.test.ts
  • web/src/__tests__/pages/SettingsPage.test.tsx
  • web/src/__tests__/pages/settings/CodeEditorPanel.test.tsx
  • web/src/__tests__/pages/settings/SettingRow.test.tsx
  • web/src/__tests__/pages/settings/SourceBadge.test.tsx
  • web/src/__tests__/pages/settings/code-editor-utils.test.ts
  • web/src/__tests__/pages/settings/editor-autocomplete.test.ts
  • web/src/__tests__/pages/settings/editor-linter.test.ts
  • web/src/api/types/settings.ts
  • web/src/mocks/handlers/settings.ts
  • web/src/pages/settings/CodeEditorPanel.stories.tsx
  • web/src/pages/settings/SettingRow.stories.tsx
  • web/src/pages/settings/SourceBadge.stories.tsx
  • web/src/pages/settings/SourceBadge.tsx
💤 Files with no reviewable changes (62)
  • tests/unit/settings/test_config_bridge.py
  • web/src/tests/pages/settings/code-editor-utils.test.ts
  • tests/unit/settings/test_models.py
  • web/src/tests/pages/settings/CodeEditorPanel.test.tsx
  • tests/unit/providers/management/conftest.py
  • src/synthorg/settings/definitions/telemetry.py
  • tests/unit/settings/test_subsystem_timeout_entries.py
  • tests/integration/api/test_per_op_rate_limit_concurrent.py
  • src/synthorg/settings/definitions/workers.py
  • tests/unit/api/controllers/test_provider_health.py
  • web/src/tests/pages/settings/editor-linter.test.ts
  • src/synthorg/observability/events/settings.py
  • tests/unit/settings/test_service_set_many.py
  • src/synthorg/settings/definitions/company.py
  • src/synthorg/settings/definitions/simulations.py
  • tests/integration/api/controllers/test_providers.py
  • web/src/tests/pages/settings/editor-autocomplete.test.ts
  • tests/unit/settings/test_new_registry_entries.py
  • src/synthorg/settings/config_bridge.py
  • tests/unit/api/controllers/test_company.py
  • tests/unit/settings/test_definitions_config_bridge.py
  • tests/unit/api/controllers/test_agents.py
  • tests/integration/engine/test_coordination_wiring.py
  • src/synthorg/settings/definitions/providers.py
  • tests/unit/api/controllers/test_analytics.py
  • tests/unit/settings/test_url_port_entries.py
  • web/src/mocks/handlers/settings.ts
  • src/synthorg/settings/definitions/client.py
  • tests/unit/settings/test_bootstrap_only_api_entries.py
  • web/src/pages/settings/SourceBadge.tsx
  • tests/unit/api/services/test_org_mutations_toctou.py
  • tests/unit/settings/test_resolver.py
  • tests/unit/api/controllers/test_departments_health.py
  • src/synthorg/settings/definitions/a2a.py
  • web/src/pages/settings/CodeEditorPanel.stories.tsx
  • src/synthorg/settings/definitions/integrations.py
  • tests/integration/settings/test_settings_integration.py
  • src/synthorg/settings/definitions/meta.py
  • tests/integration/api/test_first_run_flow.py
  • tests/unit/settings/test_engine_settings.py
  • tests/unit/api/services/test_org_mutations_atomic.py
  • src/synthorg/a2a/config.py
  • tests/unit/api/services/test_org_mutations.py
  • tests/unit/api/controllers/test_coordination.py
  • tests/unit/settings/test_readonly_init_settings.py
  • tests/unit/api/controllers/test_activities.py
  • tests/unit/settings/test_ceremony_settings.py
  • src/synthorg/settings/definitions/hr.py
  • tests/unit/settings/test_service_versioned_pipeline.py
  • tests/unit/api/test_app.py
  • src/synthorg/settings/definitions/budget.py
  • src/synthorg/settings/definitions/tools.py
  • src/synthorg/settings/definitions/security.py
  • src/synthorg/settings/definitions/notifications.py
  • src/synthorg/settings/definitions/observability.py
  • src/synthorg/settings/definitions/settings_ns.py
  • src/synthorg/settings/definitions/communication.py
  • src/synthorg/settings/definitions/memory.py
  • tests/unit/api/controllers/test_departments.py
  • src/synthorg/settings/definitions/api.py
  • src/synthorg/settings/definitions/engine.py
  • src/synthorg/api/auto_wire.py
👮 Files not reviewed due to content moderation or server errors (8)
  • src/synthorg/settings/service.py
  • src/synthorg/api/app_builders.py
  • src/synthorg/api/app.py
  • docs/reference/configuration-precedence.md
  • tests/unit/api/test_config.py
  • tests/unit/settings/test_precedence_chain.py
  • tests/unit/settings/test_source_resolution_log.py
  • tests/unit/settings/test_service.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (13)
docs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

D2 for architecture/nested containers (theme 200 Dark Mauve, CLI v0.7.1 pinned in CI); mermaid for flowcharts/sequence/pipelines; markdown tables for tabular data

Files:

  • docs/guides/deployment.md
  • docs/design/providers.md
  • docs/guides/human-interaction.md
  • docs/reference/environment-variables.md
  • docs/reference/claude-reference.md
  • docs/reference/configuration-precedence.md
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Test markers: use @pytest.mark.{unit,integration,e2e,slow}. Async auto. Timeout 30s global. Coverage 80% min

Windows unit tests: use WindowsSelectorEventLoopPolicy (Python 3.14 IOCP teardown race); subprocess tests override back

Test doubles: use FakeClock for Clock seam, mock_ofT for typed-boundary substitutions, SimpleNamespace for attribute-bags. Bare MagicMock at typed boundaries is blocked by scripts/check_mock_spec.py (zero-tolerance). FakeClock and mock_of import from tests._shared

Hypothesis: 10 deterministic CI examples; failures are real bugs (fix + add @example(...))

Flaky tests: NEVER skip/xfail; fix fundamentally. Use asyncio.Event().wait() instead of sleep(large)

Files:

  • tests/unit/settings/test_mirrors.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_pattern_a.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_ghosts.py
  • tests/unit/api/test_server.py
  • tests/unit/workers/test_main.py
  • tests/unit/memory/test_config.py
  • tests/unit/api/conftest.py
  • tests/unit/scripts/test_check_setting_to_startup_trace.py
  • tests/unit/settings/test_bootstrap_resolver.py
  • tests/unit/scripts/_setting_to_startup_trace_helpers.py
  • tests/unit/a2a/test_client.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_baseline.py
  • tests/unit/api/test_app_bootstrap_resolvers.py
  • tests/unit/providers/management/test_service_discovery.py
  • tests/unit/api/test_config.py
  • tests/unit/settings/test_precedence_chain.py
  • tests/unit/settings/test_source_resolution_log.py
  • tests/unit/settings/test_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/settings/test_mirrors.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_pattern_a.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_ghosts.py
  • tests/unit/api/test_server.py
  • tests/unit/workers/test_main.py
  • tests/unit/memory/test_config.py
  • tests/unit/api/conftest.py
  • tests/unit/scripts/test_check_setting_to_startup_trace.py
  • tests/unit/settings/test_bootstrap_resolver.py
  • tests/unit/scripts/_setting_to_startup_trace_helpers.py
  • tests/unit/a2a/test_client.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_baseline.py
  • tests/unit/api/test_app_bootstrap_resolvers.py
  • tests/unit/providers/management/test_service_discovery.py
  • tests/unit/api/test_config.py
  • tests/unit/settings/test_precedence_chain.py
  • tests/unit/settings/test_source_resolution_log.py
  • tests/unit/settings/test_service.py
cli/**/*.go

📄 CodeRabbit inference engine (cli/CLAUDE.md)

Use the appropriate hint tier based on intent: HintError for error recovery (always visible unless quiet), HintNextStep for natural next action or destructive-action feedback, HintTip for config automation suggestions (deduplicates within session), and HintGuidance for flag/feature discovery (invisible in default auto mode)

Files:

  • cli/cmd/worker_start.go
cli/cmd/**/*.go

📄 CodeRabbit inference engine (cli/CLAUDE.md)

Exit codes: 0 = success, 1 = runtime error, 2 = usage error, 3 = unhealthy (backend/containers), 4 = unreachable (Docker), 10 = updates available (--check)

Files:

  • cli/cmd/worker_start.go
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{ts,tsx}: Always use createLogger from @/lib/logger; never bare console.warn/console.error/console.debug in application code
Use variable name log for logger instances (e.g. const log = createLogger('module-name'))
Use log levels: log.debug() (DEV-only, stripped in production), log.warn(), log.error()
Pass dynamic/untrusted values as separate args to logger methods (not interpolated into the message string) so they go through sanitizeArg
Wrap attacker-controlled fields inside structured objects with sanitizeForLog() before embedding in logs
Callers MUST NOT wrap store mutation calls in try / catch; the store owns the error UX
Use display counts from data.length; the wire envelope no longer carries total
Any new caller of health/readiness endpoints must handle the 503 path explicitly
Use sanitizeWsString() and sanitizeWsEnum() from web/src/utils/ws-sanitize.ts (pure helpers, re-exported from @/stores/notifications) for all WebSocket payload handling
sanitizeWsString() clamps every WS-supplied string (strips C0 controls + bidi-overrides + caps length); sanitizeWsEnum<T>(value, allowlist, fallback, { field }) validates enum values and emits ws.enum.unknown warning on unknown values
Any new WS payload handler must route through sanitizeWsString() or sanitizeWsEnum(); raw (sanitizeWsString(x, n) ?? '') as EnumType casts are forbidden
Write-path features (chat, settings actions) surface a Connection limited toast and direct operator to reload after fixing proxy; only read surfaces are covered by SSE fallback
Import ErrorCode and ErrorCategory from @/api/types/errors (re-exported from generated web/src/api/types/error-codes.gen.ts); discriminate on ErrorCode.<NAME>, never on raw integer literals
NEVER hardcode hex colors, font-family declarations, pixel spacing, Motion transition durations, BCP 47 locale literals ('en-US'), or currency symbols / codes; use design tokens, @/lib/motion presets...

Files:

  • web/src/__tests__/pages/settings/SourceBadge.test.tsx
  • web/src/pages/settings/SourceBadge.stories.tsx
  • web/src/__tests__/pages/settings/SettingRow.test.tsx
  • web/src/__tests__/hooks/useSettingsData.test.ts
  • web/src/api/types/settings.ts
  • web/src/__tests__/pages/SettingsPage.test.tsx
  • web/src/pages/settings/SettingRow.stories.tsx
web/src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{test,spec}.{ts,tsx}: test-setup.tsx boots with onUnhandledRequest: 'error'; tests override per-case via server.use(...), never vi.mock('@/api/endpoints/*')
Every unit test runs under web/test-infra/active-handle-tracker.ts, which fails any test that leaks an event-loop-holding resource attributable to a web/src/ frame; zero tolerance, no ceiling, no buffer

Files:

  • web/src/__tests__/pages/settings/SourceBadge.test.tsx
  • web/src/__tests__/pages/settings/SettingRow.test.tsx
  • web/src/__tests__/hooks/useSettingsData.test.ts
  • web/src/__tests__/pages/SettingsPage.test.tsx
web/src/**/*.tsx

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.tsx: Use useViewportSize() from @/hooks/useViewportSize (useSyncExternalStore over window resize) for viewport-size reads; never read window.innerWidth / window.innerHeight directly inside render or useMemo
Enable @eslint-react/no-leaked-conditional-rendering to catch the {count && <Foo />} bug where 0 renders verbatim; for ReactNode | undefined props use {value != null && value !== false && <jsx>}; for compound truthiness use Boolean(...)
Enable @eslint-react/globals to restrict window / document / localStorage / etc. inside render; hoist offenders into a useCallback event handler, a useEffect, or a useSyncExternalStore-backed hook

Files:

  • web/src/__tests__/pages/settings/SourceBadge.test.tsx
  • web/src/pages/settings/SourceBadge.stories.tsx
  • web/src/__tests__/pages/settings/SettingRow.test.tsx
  • web/src/__tests__/pages/SettingsPage.test.tsx
  • web/src/pages/settings/SettingRow.stories.tsx
web/**/*.{ts,tsx,jsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Reuse Web Dashboard Design System components from web/src/components/ui/ with design tokens only (see web/CLAUDE.md)

Web: reference web/CLAUDE.md for Design System details

Files:

  • web/src/__tests__/pages/settings/SourceBadge.test.tsx
  • web/src/pages/settings/SourceBadge.stories.tsx
  • web/src/__tests__/pages/settings/SettingRow.test.tsx
  • web/src/__tests__/hooks/useSettingsData.test.ts
  • web/src/api/types/settings.ts
  • web/src/__tests__/pages/SettingsPage.test.tsx
  • web/src/pages/settings/SettingRow.stories.tsx
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Only src/synthorg/persistence/ may import sqlite/psycopg or emit raw SQL (see docs/reference/persistence-boundary.md)

Configuration precedence: DB > env > code default via SettingsService/ConfigResolver (Cat-1) or env > code default (Cat-2, read_only_post_init); Cat-3 bootstrap secrets are pure env. No os.environ.get outside startup; pre-init Cat-2 reads use settings.bootstrap_resolver.resolve_init_value (see docs/reference/configuration-precedence.md)

No hardcoded numeric values; numerics live in settings/definitions/. Allowlist only: 0, 1, -1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants (NAME: int|float|Final|Final[int]|Final[float] = literal). Enforced by scripts/check_no_magic_numbers.py

Use Comments for WHY only; never include reviewer citations, issue back-references, or migration framing. Enforced by check_no_review_origin_in_code.py + check_no_migration_framing.py

Do not use from __future__ import annotations (Python 3.14 has PEP 649). Use PEP 758 except: except A, B: syntax must use parentheses when binding

Type hints required on public functions; strict mypy; Google-style docstrings; line length 88; functions <50 lines; files <800 lines

Error classes: use <Domain><Condition>Error pattern inheriting from DomainError; never inherit directly from Exception/RuntimeError/etc. Enforced by check_domain_error_hierarchy.py

Pydantic v2: use frozen + extra='forbid' on API DTOs (Request/Response/Snapshot/Result/Envelope/Status/Info/Summary suffixes); use @computed_field for derived; use NotBlankStr for identifiers

Args models required at every system boundary; use parse_typed() for every external dict ingestion. Enforced by check_boundary_typed.py

Immutability: use model_copy(update=...) or copy.deepcopy(); deepcopy at system boundaries

Async patterns: use asyncio.TaskGroup for fan-out/fan-in; helpers catch Exception and re-raise MemoryError/RecursionError

Clock seam: inject clock: Clock | None = None parameter...

Files:

  • src/synthorg/workers/__main__.py
  • src/synthorg/api/server.py
  • src/synthorg/settings/mirrors.py
  • src/synthorg/security/config.py
  • src/synthorg/config/schema.py
  • src/synthorg/communication/config.py
  • src/synthorg/settings/models.py
  • src/synthorg/settings/bootstrap_resolver.py
  • src/synthorg/memory/config.py
  • src/synthorg/providers/management/service.py
  • src/synthorg/engine/coordination/section_config.py
  • src/synthorg/observability/setup.py
  • src/synthorg/settings/enums.py
  • src/synthorg/engine/evolution/config.py
  • src/synthorg/integrations/config.py
  • src/synthorg/core/auth/config.py
  • src/synthorg/config/rate_limits.py
  • src/synthorg/engine/workflow/ceremony_policy.py
  • src/synthorg/budget/config.py
  • src/synthorg/security/autonomy/models.py
  • src/synthorg/settings/definitions/coordination.py
  • src/synthorg/api/middleware_factory.py
  • src/synthorg/memory/consolidation/config.py
  • src/synthorg/settings/service.py
  • src/synthorg/api/app_builders.py
  • src/synthorg/api/app.py
  • src/synthorg/api/config.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/workers/__main__.py
  • src/synthorg/api/server.py
  • src/synthorg/settings/mirrors.py
  • src/synthorg/security/config.py
  • src/synthorg/config/schema.py
  • src/synthorg/communication/config.py
  • src/synthorg/settings/models.py
  • src/synthorg/settings/bootstrap_resolver.py
  • src/synthorg/memory/config.py
  • src/synthorg/providers/management/service.py
  • src/synthorg/engine/coordination/section_config.py
  • src/synthorg/observability/setup.py
  • src/synthorg/settings/enums.py
  • src/synthorg/engine/evolution/config.py
  • src/synthorg/integrations/config.py
  • src/synthorg/core/auth/config.py
  • src/synthorg/config/rate_limits.py
  • src/synthorg/engine/workflow/ceremony_policy.py
  • src/synthorg/budget/config.py
  • src/synthorg/security/autonomy/models.py
  • src/synthorg/settings/definitions/coordination.py
  • src/synthorg/api/middleware_factory.py
  • src/synthorg/memory/consolidation/config.py
  • src/synthorg/settings/service.py
  • src/synthorg/api/app_builders.py
  • src/synthorg/api/app.py
  • src/synthorg/api/config.py
web/src/pages/**/*.tsx

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/pages/**/*.tsx: List-page primitives must use <ListHeader> / <SearchFilterSort> / <Pagination> / <BulkActionBar> / <MetadataGrid> / <Breadcrumbs> / <Collapsible>
Page root container should use space-y-section-gap (flex flex-col gap-section-gap is equivalent but discouraged); <ErrorBanner> lands immediately after <ListHeader>, before any filter / pagination row
Pages with a one-line mission statement should pass it via <ListHeader description="..." />
Use Kanban grouping for status-flow domains where each row's column conveys lifecycle phase (Tasks, Requests); use flat scrollable list for queues without explicit phase semantics (Escalations, Approvals)
Aim for 2 or 3 breadcrumb levels max in visible trails; the dashboard's information architecture is flat (every primary domain is one sidebar click away); a 4+ level trail reflects a routing mistake
Use useEmptyStateProps({ filteredCount, totalCount, filterActive, empty, filtered }) from @/hooks/use-empty-state-props to return EmptyStateProps | null instead of duplicating "no data ever" / "no data after filter" discriminators

Files:

  • web/src/pages/settings/SourceBadge.stories.tsx
  • web/src/pages/settings/SettingRow.stories.tsx
web/src/**/*.stories.tsx

📄 CodeRabbit inference engine (web/CLAUDE.md)

Storybook 10 gotchas: ESM-only; essentials are built into core, but @storybook/addon-docs is now separate; imports moved to storybook/test and storybook/actions

Files:

  • web/src/pages/settings/SourceBadge.stories.tsx
  • web/src/pages/settings/SettingRow.stories.tsx
web/src/**/*.ts

📄 CodeRabbit inference engine (web/CLAUDE.md)

Bump the WS protocol version on both client and server together for breaking payload changes; drift is enforced at pre-commit / pre-push by scripts/check_ws_protocol_version_in_sync.py

Files:

  • web/src/__tests__/hooks/useSettingsData.test.ts
  • web/src/api/types/settings.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: Read design specification from `docs/design/` before implementing; deviations require approval (see DESIGN_SPEC.md)
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: Present every plan for accept/deny before coding
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: No region/locale privileged; use metric units and British English (see docs/reference/regional-defaults.md)
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: Every convention PR must ship its enforcement gate (see docs/reference/convention-gates.md)
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: After issue completion: branch + commit + push (no auto-PR); use `/pre-pr-review` command. After PR: use `/aurelio-review-pr` for external feedback. Fix ALL valid issues; no deferring
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: Git commits: <type>: <description> format (feat/fix/refactor/docs/test/chore/perf/ci); commitizen-enforced
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: Signed commits required on protected refs (GPG/SSH or GitHub App via synthorg-repo-bot)
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: Branches: <type>/<slug> naming from main
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: Squash merge with PR body as commit; trailers (Release-As, Closes `#N`) must be in PR body
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: GitHub queries: use 'gh issue list' via Bash, NOT MCP list_issues
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: After every squash merge: run /post-merge-cleanup
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: CLI is Docker-only (init/start/stop/status); features go in dashboard + REST API
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:14:36.839Z
Learning: CLI: reference cli/CLAUDE.md; use 'go -C cli' (never 'cd cli')
📚 Learning: 2026-05-05T09:04:46.195Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1760
File: scripts/_dual_backend_parity_lib.py:215-216
Timestamp: 2026-05-05T09:04:46.195Z
Learning: This repository targets Python 3.14+ and follows PEP 758. Therefore, reviewer tooling should NOT treat unparenthesized multi-exception `except` clauses written without an `as` clause (e.g., `except MemoryError, RecursionError:`) as syntax errors. Only flag `except`-clause problems when they are genuinely invalid for Python 3.14+.

Applied to files:

  • tests/unit/settings/test_mirrors.py
  • src/synthorg/workers/__main__.py
  • scripts/check_setting_to_startup_trace.py
  • src/synthorg/api/server.py
  • src/synthorg/settings/mirrors.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_pattern_a.py
  • src/synthorg/security/config.py
  • src/synthorg/config/schema.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_ghosts.py
  • tests/unit/api/test_server.py
  • src/synthorg/communication/config.py
  • tests/unit/workers/test_main.py
  • src/synthorg/settings/models.py
  • src/synthorg/settings/bootstrap_resolver.py
  • src/synthorg/memory/config.py
  • src/synthorg/providers/management/service.py
  • src/synthorg/engine/coordination/section_config.py
  • scripts/_setting_to_startup_trace_loader.py
  • tests/unit/memory/test_config.py
  • tests/unit/api/conftest.py
  • tests/unit/scripts/test_check_setting_to_startup_trace.py
  • src/synthorg/observability/setup.py
  • tests/unit/settings/test_bootstrap_resolver.py
  • scripts/_setting_to_startup_trace_ghosts.py
  • tests/unit/scripts/_setting_to_startup_trace_helpers.py
  • src/synthorg/settings/enums.py
  • src/synthorg/engine/evolution/config.py
  • src/synthorg/integrations/config.py
  • src/synthorg/core/auth/config.py
  • src/synthorg/config/rate_limits.py
  • tests/unit/a2a/test_client.py
  • src/synthorg/engine/workflow/ceremony_policy.py
  • tests/unit/scripts/test_check_setting_to_startup_trace_baseline.py
  • src/synthorg/budget/config.py
  • tests/unit/api/test_app_bootstrap_resolvers.py
  • src/synthorg/security/autonomy/models.py
  • scripts/_setting_to_startup_trace_violations.py
  • src/synthorg/settings/definitions/coordination.py
  • scripts/_setting_to_startup_trace_models.py
  • tests/unit/providers/management/test_service_discovery.py
  • src/synthorg/api/middleware_factory.py
  • src/synthorg/memory/consolidation/config.py
  • src/synthorg/settings/service.py
  • src/synthorg/api/app_builders.py
  • src/synthorg/api/app.py
  • tests/unit/api/test_config.py
  • tests/unit/settings/test_precedence_chain.py
  • tests/unit/settings/test_source_resolution_log.py
  • tests/unit/settings/test_service.py
  • src/synthorg/api/config.py
🔇 Additional comments (56)
docs/guides/deployment.md (1)

102-102: LGTM!

docs/design/providers.md (1)

123-123: LGTM!

tests/unit/settings/test_mirrors.py (1)

1-101: LGTM!

cli/cmd/worker_start.go (1)

133-133: LGTM!

Also applies to: 141-141

docs/guides/human-interaction.md (1)

212-212: LGTM!

web/src/__tests__/pages/settings/SourceBadge.test.tsx (1)

2-2: LGTM!

Also applies to: 40-43

docs/reference/environment-variables.md (1)

6-7: LGTM!

Also applies to: 82-82, 113-115

CLAUDE.md (1)

15-15: LGTM!

src/synthorg/workers/__main__.py (1)

64-65: LGTM!

Also applies to: 83-84, 90-90, 107-107

scripts/check_setting_to_startup_trace.py (1)

147-148: LGTM!

docs/reference/claude-reference.md (1)

59-59: LGTM!

src/synthorg/api/server.py (1)

19-21: LGTM!

Also applies to: 42-67, 70-72, 83-87, 90-90, 94-96, 114-115

src/synthorg/settings/mirrors.py (1)

1-152: LGTM!

tests/unit/scripts/test_check_setting_to_startup_trace_pattern_a.py (1)

121-123: LGTM!

Also applies to: 167-170, 262-263

src/synthorg/security/config.py (1)

9-9: LGTM!

Also applies to: 22-29, 318-360, 423-427

src/synthorg/config/schema.py (1)

49-51: LGTM!

Also applies to: 139-145, 160-163

tests/unit/scripts/test_check_setting_to_startup_trace_ghosts.py (1)

228-228: LGTM!

Also applies to: 283-283, 336-336

tests/unit/api/test_server.py (1)

55-60: LGTM!

Also applies to: 66-70, 80-87

src/synthorg/communication/config.py (1)

23-28: LGTM!

Also applies to: 349-367

tests/unit/workers/test_main.py (1)

1-55: LGTM!

src/synthorg/settings/models.py (1)

52-58: LGTM!

Also applies to: 91-93

web/src/pages/settings/SourceBadge.stories.tsx (1)

15-25: LGTM!

src/synthorg/memory/config.py (1)

225-237: LGTM!

Also applies to: 285-288

src/synthorg/providers/management/service.py (1)

230-249: LGTM!

Also applies to: 719-720

web/src/__tests__/pages/settings/SettingRow.test.tsx (1)

13-13: LGTM!

src/synthorg/engine/coordination/section_config.py (1)

7-21: LGTM!

Also applies to: 40-65, 93-97

scripts/_setting_to_startup_trace_loader.py (1)

119-119: LGTM!

Also applies to: 127-127

tests/unit/memory/test_config.py (1)

230-232: LGTM!

web/src/__tests__/hooks/useSettingsData.test.ts (1)

8-9: LGTM!

web/src/api/types/settings.ts (1)

34-35: LGTM!

tests/unit/api/conftest.py (1)

96-103: LGTM!

Also applies to: 106-119, 424-427

tests/unit/scripts/test_check_setting_to_startup_trace.py (1)

60-61: LGTM!

Also applies to: 89-90, 98-99, 106-106, 189-189

src/synthorg/observability/setup.py (1)

313-315: LGTM!

Also applies to: 323-340

tests/unit/settings/test_bootstrap_resolver.py (1)

1-201: LGTM!

scripts/_setting_to_startup_trace_ghosts.py (1)

597-597: LGTM!

tests/unit/scripts/_setting_to_startup_trace_helpers.py (1)

99-100: LGTM!

Also applies to: 115-116

src/synthorg/settings/enums.py (1)

66-69: LGTM!

src/synthorg/engine/evolution/config.py (1)

8-8: LGTM!

Also applies to: 26-29, 245-252, 265-268

src/synthorg/integrations/config.py (1)

7-7: LGTM!

Also applies to: 12-17, 135-143, 151-154, 170-178, 185-188

src/synthorg/core/auth/config.py (1)

3-14: LGTM!

Also applies to: 73-93, 222-225

src/synthorg/config/rate_limits.py (1)

10-22: LGTM!

Also applies to: 74-91, 171-193

tests/unit/a2a/test_client.py (1)

12-14: LGTM!

Also applies to: 428-430

src/synthorg/engine/workflow/ceremony_policy.py (1)

11-12: LGTM!

Also applies to: 21-27, 112-139, 164-167

tests/unit/scripts/test_check_setting_to_startup_trace_baseline.py (1)

128-128: LGTM!

Also applies to: 208-209, 340-345, 357-357

web/src/__tests__/pages/SettingsPage.test.tsx (1)

81-82: LGTM!

src/synthorg/budget/config.py (1)

9-23: LGTM!

Also applies to: 40-87, 120-155, 228-259, 314-317

tests/unit/api/test_app_bootstrap_resolvers.py (1)

1-95: LGTM!

Also applies to: 111-126

src/synthorg/security/autonomy/models.py (1)

4-4: LGTM!

Also applies to: 10-11, 140-147, 163-167

web/src/pages/settings/SettingRow.stories.tsx (1)

16-16: LGTM!

scripts/_setting_to_startup_trace_violations.py (1)

209-209: LGTM!

Also applies to: 258-258, 306-306, 391-391, 419-419, 448-448

src/synthorg/settings/definitions/coordination.py (1)

162-162: LGTM!

scripts/_setting_to_startup_trace_models.py (1)

34-35: LGTM!

Also applies to: 58-58, 112-113, 121-121, 130-132, 139-139

tests/unit/providers/management/test_service_discovery.py (1)

18-19: LGTM!

src/synthorg/api/middleware_factory.py (1)

27-29: LGTM!

Also applies to: 261-274, 276-286, 448-457

src/synthorg/memory/consolidation/config.py (1)

9-9: LGTM!

Also applies to: 18-23, 323-331, 365-369

src/synthorg/api/config.py (1)

9-25: LGTM!

Also applies to: 125-155, 234-238, 334-347, 395-398

Comment thread src/synthorg/settings/bootstrap_resolver.py
Comment thread tests/unit/api/test_app_bootstrap_resolvers.py
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 14, 2026 20:33 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/synthorg/api/server.py`:
- Around line 43-46: The helper _str_or_none currently calls str(resolved.value)
which converts None to the string "None" and returns a truthy value; update
_str_or_none to check resolved.value for None first and return None if so,
otherwise convert to str and strip; reference the function _str_or_none and the
value resolved.value (from resolve_init_value(SettingNamespace.API, key)) so
TLS-related kwargs only become truthy when an actual non-None, non-empty string
path is present.
🪄 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: fc92508b-8400-42f6-b3b3-dcd483a30371

📥 Commits

Reviewing files that changed from the base of the PR and between 78402d9 and c43e5a7.

📒 Files selected for processing (5)
  • scripts/_setting_to_startup_trace_loader.py
  • src/synthorg/api/app_builders.py
  • src/synthorg/api/middleware_factory.py
  • src/synthorg/api/server.py
  • src/synthorg/workers/__main__.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test (Python 3.14)
🧰 Additional context used
📓 Path-based instructions (2)
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Only src/synthorg/persistence/ may import sqlite/psycopg or emit raw SQL; see docs/reference/persistence-boundary.md

Configuration precedence: DB > env > code default via SettingsService/ConfigResolver (Cat-1) or env > code default (Cat-2, read_only_post_init); Cat-3 bootstrap secrets pure env. Use settings.bootstrap_resolver.resolve_init_value for pre-init Cat-2 reads. No os.environ.get outside startup. YAML is template ingestion format only; see docs/reference/configuration-precedence.md

No hardcoded numeric values; numerics must live in settings/definitions/. Allowlist: 0/1/-1, HTTP codes, hex masks, powers-of-2, module-level annotated constants (NAME: int|float|Final|Final[int]|Final[float] = literal). Enforced by scripts/check_no_magic_numbers.py

Comments should explain WHY only; no reviewer citations / issue back-refs / migration framing. Enforced by check_no_review_origin_in_code.py + check_no_migration_framing.py

No from __future__ import annotations (Python 3.14+ has PEP 649). PEP 758 except: except A, B: no parens unless binding

Type hints required on public functions; mypy strict. Google-style docstrings. Line length 88; functions <50 lines; files <800 lines

Errors must follow <Domain><Condition>Error pattern and inherit from DomainError, never directly from Exception/RuntimeError/etc. Enforced by check_domain_error_hierarchy.py

Pydantic v2: use frozen + extra="forbid" on API DTOs (Request/Response/Snapshot/Result/Envelope/Status/Info/Summary suffixes); @computed_field for derived; NotBlankStr for identifiers

Args models required at every system boundary; use parse_typed() for every external dict ingestion. Enforced by check_boundary_typed.py

Immutability: use model_copy(update=...) or copy.deepcopy(); deepcopy at system boundaries

Async: use asyncio.TaskGroup for fan-out/fan-in; helpers catch Exception (re-raise MemoryError/RecursionError)

Clock seam: inject clock: Clock | None = None; ...

Files:

  • src/synthorg/api/middleware_factory.py
  • src/synthorg/api/server.py
  • src/synthorg/workers/__main__.py
  • src/synthorg/api/app_builders.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/api/middleware_factory.py
  • src/synthorg/api/server.py
  • src/synthorg/workers/__main__.py
  • src/synthorg/api/app_builders.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Read `docs/design/` page before implementing; deviations need approval per DESIGN_SPEC.md
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Present every plan for accept/deny before coding
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: No region/currency/locale privileged; use metric units and British English; see docs/reference/regional-defaults.md
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Every convention PR must ship its enforcement gate; see docs/reference/convention-gates.md
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Never edit `tests/baselines/unit_timing.json` or any `scripts/*_baseline.{txt,json}` / `scripts/_*_baseline.py`; timeout/slow failures indicate source-code regression. PreToolUse-blocked. Per-invocation bypass: `ALLOW_BASELINE_GROWTH=1 git commit ...` requires explicit user approval
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: After issue: branch + commit + push (no auto-PR); use `/pre-pr-review`. After PR: use `/aurelio-review-pr` for external feedback. Fix everything valid; no deferring
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: xdist: apply `-n 8 --dist=loadfile` auto via pyproject addopts (`loadfile` prevents 3.14+Windows ProactorEventLoop leak)
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Git commits: `<type>: <description>` format (feat/fix/refactor/docs/test/chore/perf/ci); commitizen-enforced
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Signed commits required on protected refs (GPG/SSH or GitHub App via `synthorg-repo-bot`)
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Branches: `<type>/<slug>` from main
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Pre-commit/pre-push hooks: use `.pre-commit-config.yaml`. Hookify rules: `.claude/hookify.*.md`
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Squash merge. PR body becomes squash commit; trailers (`Release-As`, `Closes `#N``) must be in PR body
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: GitHub queries: use `gh issue list` via Bash, NOT MCP `list_issues`
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: After every squash merge → run `/post-merge-cleanup`
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: CLI is Docker-only (init/start/stop/status); features go in dashboard + REST API
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:36:39.050Z
Learning: Web: see `web/CLAUDE.md`. CLI: see `cli/CLAUDE.md` (use `go -C cli`, never `cd cli`). Shell: see `~/.claude/rules/common/bash.md`
📚 Learning: 2026-05-05T09:04:46.195Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1760
File: scripts/_dual_backend_parity_lib.py:215-216
Timestamp: 2026-05-05T09:04:46.195Z
Learning: This repository targets Python 3.14+ and follows PEP 758. Therefore, reviewer tooling should NOT treat unparenthesized multi-exception `except` clauses written without an `as` clause (e.g., `except MemoryError, RecursionError:`) as syntax errors. Only flag `except`-clause problems when they are genuinely invalid for Python 3.14+.

Applied to files:

  • scripts/_setting_to_startup_trace_loader.py
  • src/synthorg/api/middleware_factory.py
  • src/synthorg/api/server.py
  • src/synthorg/workers/__main__.py
  • src/synthorg/api/app_builders.py
🔇 Additional comments (4)
src/synthorg/workers/__main__.py (1)

27-29: LGTM!

Also applies to: 52-57, 71-71, 90-107, 118-118

src/synthorg/api/middleware_factory.py (1)

27-30: LGTM!

Also applies to: 262-265, 271-272, 434-443

scripts/_setting_to_startup_trace_loader.py (1)

119-120: LGTM!

Also applies to: 127-127

src/synthorg/api/app_builders.py (1)

20-23: LGTM!

Also applies to: 56-59, 63-67, 280-287, 293-327

Comment on lines +43 to +46
def _str_or_none(key: str) -> str | None:
resolved = resolve_init_value(SettingNamespace.API, key)
raw = str(resolved.value).strip()
return raw or None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle None in _str_or_none before string conversion.

On Line 45, str(resolved.value) turns None into "None", which is truthy and can incorrectly enable TLS kwargs with invalid paths.

Proposed fix
 def _str_or_none(key: str) -> str | None:
     resolved = resolve_init_value(SettingNamespace.API, key)
-    raw = str(resolved.value).strip()
+    if resolved.value is None:
+        return None
+    raw = str(resolved.value).strip()
     return raw or None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/synthorg/api/server.py` around lines 43 - 46, The helper _str_or_none
currently calls str(resolved.value) which converts None to the string "None" and
returns a truthy value; update _str_or_none to check resolved.value for None
first and return None if so, otherwise convert to str and strip; reference the
function _str_or_none and the value resolved.value (from
resolve_init_value(SettingNamespace.API, key)) so TLS-related kwargs only become
truthy when an actual non-None, non-empty string path is present.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 14, 2026 20:54 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/synthorg/settings/bootstrap_resolver.py`:
- Around line 83-85: The code raises SettingNotFoundError (in the block checking
"if definition is None") and other bootstrap exceptions later (lines 111-122)
without logging; before each raise, call the module's logger (e.g.
logger.warning or logger.error) to emit a structured message that includes the
namespace and key (and any relevant registry/default info) and include exception
context (e.g. exc_info=True or the error details) so startup diagnostics are
preserved; update the code paths that raise SettingNotFoundError and the other
bootstrap exception raises in this module to log with appropriate level and
context immediately before raising.
🪄 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: 1a9a7337-91be-483f-b66d-6fa1d83a3fbf

📥 Commits

Reviewing files that changed from the base of the PR and between c43e5a7 and 1c94d92.

📒 Files selected for processing (3)
  • src/synthorg/api/config.py
  • src/synthorg/settings/bootstrap_resolver.py
  • tests/unit/api/test_app_bootstrap_resolvers.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Build Backend
  • GitHub Check: CLI Bench Regression
  • GitHub Check: CLI Test (windows-latest)
  • GitHub Check: Dashboard Test
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Lighthouse Dashboard
  • GitHub Check: Lighthouse Site
  • GitHub Check: Build Web Assets (melange)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (4)
src/synthorg/!(persistence)/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Only src/synthorg/persistence/ may import sqlite/psycopg or emit raw SQL; all other modules must use abstraction boundary

Files:

  • src/synthorg/settings/bootstrap_resolver.py
  • src/synthorg/api/config.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use configuration precedence: DB > env > code default via SettingsService/ConfigResolver (Cat-1), or env > code default (Cat-2 with read_only_post_init); Cat-3 bootstrap secrets use pure env at boot site. YAML is company-template ingestion only, not a precedence tier. Never use os.environ.get outside startup; pre-init Cat-2 reads use settings.bootstrap_resolver.resolve_init_value

No hardcoded numeric values; store numerics in settings/definitions/. Allow only: 0, 1, -1, HTTP codes, hex masks, powers-of-2, and module-level annotated named constants (NAME: int|float|Final|Final[int]|Final[float] = literal). Enforced by scripts/check_no_magic_numbers.py

Code comments must explain WHY only; never include reviewer citations, issue back-references, or migration framing. Enforced by check_no_review_origin_in_code.py and check_no_migration_framing.py

Do not use from __future__ import annotations (Python 3.14 has PEP 649). Use PEP 758 except: except A, B: without parens unless binding

Add type hints to all public functions; use mypy strict mode. Use Google-style docstrings. Maximum line length 88; functions <50 lines; files <800 lines

Define errors as <Domain><Condition>Error inheriting from DomainError, never directly from Exception/RuntimeError/etc. Enforced by check_domain_error_hierarchy.py

Use Pydantic v2 with frozen=True and extra='forbid' on API DTOs (Request/Response/Snapshot/Result/Envelope/Status/Info/Summary suffixes); use @computed_field for derived values; use NotBlankStr for identifiers

Use args models at every system boundary; apply parse_typed() for every external dict ingestion. Enforced by check_boundary_typed.py

Enforce immutability: use model_copy(update=...) or copy.deepcopy(); apply deepcopy at system boundaries

Use asyncio.TaskGroup for async fan-out/fan-in operations; helper functions must catch Exception and re-raise MemoryError/RecursionError

Implement Clock seam as `clock: Clock | None = N...

Files:

  • src/synthorg/settings/bootstrap_resolver.py
  • src/synthorg/api/config.py
src/**/*.py

⚙️ CodeRabbit configuration file

This project uses Python 3.14+ with PEP 758 except syntax: "except A, B:" (comma-separated, no parentheses) is correct and mandatory -- do NOT flag it as a typo or suggest parenthesized form. The "except builtins.MemoryError, RecursionError: raise" pattern is intentional project convention for system-error propagation. When evaluating the 50-line function limit, count only the function body excluding the signature lines, decorators, and docstring. Functions 1-5 lines over due to docstrings or multi-line signatures should not be flagged. Do not suggest extracting single-use helper functions called exactly once -- this reduces readability without improving maintainability.

Files:

  • src/synthorg/settings/bootstrap_resolver.py
  • src/synthorg/api/config.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Mark tests with @pytest.mark.{unit,integration,e2e,slow}. Use async auto. Global timeout 30s. Coverage minimum 80%. xdist applies -n 8 --dist=loadfile via pyproject addopts (loadfile prevents 3.14+ Windows ProactorEventLoop leak)

Windows test policy: unit tests use WindowsSelectorEventLoopPolicy (3.14 IOCP teardown race); subprocess tests override back

Test doubles ladder (in order): FakeClock for Clock seam, mock_of[T](**overrides) for typed-boundary substitutions, SimpleNamespace for attribute-bags. Never bare MagicMock at typed boundaries (constructor/fn arg/annotated local/typed fixture return). Blocked by scripts/check_mock_spec.py with zero tolerance. Import FakeClock and mock_of from tests._shared

Hypothesis: 10 deterministic CI examples; failures are real bugs (fix + add @example(...))

Never skip or xfail flaky tests; fix fundamentally. Use asyncio.Event().wait() instead of sleep(large)

Files:

  • tests/unit/api/test_app_bootstrap_resolvers.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/api/test_app_bootstrap_resolvers.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: Read design specification from `docs/design/` page before implementing; deviations require approval. See DESIGN_SPEC.md
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: Present every plan for accept/deny before coding
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: No region/currency/locale privileged; use metric units; use British English in documentation and code comments
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: Every convention PR must ship its enforcement gate
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: Timeout/slow test failures indicate source-code regression; never edit `tests/baselines/unit_timing.json`, `scripts/*_baseline.{txt,json}`, or `scripts/_*_baseline.py`. Both families are PreToolUse-blocked. Per-invocation bypass requires `ALLOW_BASELINE_GROWTH=1 git commit ...` with explicit user approval
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: After issue completion: create branch, commit, and push (no auto-PR); use `/pre-pr-review` command. After PR creation: use `/aurelio-review-pr` for external feedback. Fix everything valid from reviews; do not defer
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: Git commits use format `<type>: <description>` (feat/fix/refactor/docs/test/chore/perf/ci); enforced by commitizen. Branches use format `<type>/<slug>` from main. Signed commits required on protected refs. Squash merge with PR body as squash commit message; trailers (`Release-As`, `Closes `#N``) must be in PR body
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: Pre-commit/pre-push hooks defined in `.pre-commit-config.yaml`. Hookify rules in `.claude/hookify.*.md`
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: After every squash merge, run `/post-merge-cleanup`
Learnt from: CR
Repo: Aureliolo/synthorg

Timestamp: 2026-05-14T20:54:12.670Z
Learning: CLI features are Docker-only (init/start/stop/status); new features go in dashboard and REST API, not CLI
📚 Learning: 2026-05-05T09:04:46.195Z
Learnt from: Aureliolo
Repo: Aureliolo/synthorg PR: 1760
File: scripts/_dual_backend_parity_lib.py:215-216
Timestamp: 2026-05-05T09:04:46.195Z
Learning: This repository targets Python 3.14+ and follows PEP 758. Therefore, reviewer tooling should NOT treat unparenthesized multi-exception `except` clauses written without an `as` clause (e.g., `except MemoryError, RecursionError:`) as syntax errors. Only flag `except`-clause problems when they are genuinely invalid for Python 3.14+.

Applied to files:

  • src/synthorg/settings/bootstrap_resolver.py
  • tests/unit/api/test_app_bootstrap_resolvers.py
  • src/synthorg/api/config.py
🔇 Additional comments (5)
src/synthorg/api/config.py (4)

9-9: LGTM!

Also applies to: 18-25


125-155: LGTM!

Also applies to: 234-238


255-260: LGTM!


307-308: LGTM!

Also applies to: 321-334, 353-354, 382-385

tests/unit/api/test_app_bootstrap_resolvers.py (1)

20-132: LGTM!

Comment thread src/synthorg/settings/bootstrap_resolver.py
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 14, 2026 21:10 — with GitHub Actions Inactive
@Aureliolo Aureliolo merged commit efd54c9 into main May 14, 2026
91 checks passed
@Aureliolo Aureliolo deleted the refactor/config-precedence-three-category branch May 14, 2026 21:14
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview May 14, 2026 21:14 — with GitHub Actions Inactive
Aureliolo pushed a commit that referenced this pull request May 17, 2026
<!-- HIGHLIGHTS_START -->
## Highlights

> _AI-generated summary (model: `openai/gpt-4.1-mini` via GitHub
Models). Commit-based changelog below._

### What you'll notice
- Frontend WP-6 update with UX polish improves user interface and
workflow.
- Dashboard and training endpoint improvements enhance observability and
dispatch behavior.
- Web storybook now supports change detection for more responsive UI
interactions.
- Git hooks now isolated per worktree for cleaner repository management.
- Providers automatically detect native streaming support in Litellm
models.

### What's new
- Added a new pipeline to convert Pydantic DTOs to TypeScript for better
front-end compatibility.

### Under the hood
- Refactored settings to three precedence categories, removing YAML tier
for simpler configuration.
- Completed RootConfig mirror coverage for enhanced configuration
consistency.
- Adopted API conventions with better query performance and forbidden
extra fields for stricter validation.
- Improved persistence, layer discipline, and restart safety in core
work packages.
- CI updated with split test jobs and tightened coverage gates for
better test quality.
- Switched to direct Trivy binary for security scans, removing previous
Trivy action dependency.
- Enhanced memory management with per-call processing options and better
observability during speech-to-text encoding.
- Various dependency updates for Python, infrastructure, and lock files
maintain security and stability.
- Removed TypeScript DTO type-tightening overlays to simplify type
management.
- Codebase audit tightened skill sets to prevent false positivity in
class detection by 2026.

<!-- HIGHLIGHTS_END -->

:robot: I have created a release *beep* *boop*
---


##
[0.8.5](v0.8.4...v0.8.5)
(2026-05-17)


### Features

* **codegen:** pydantic-to-typescript DTO pipeline + parity gate (closes
[#1889](#1889))
([#1909](#1909))
([0265ef5](0265ef5))
* **storybook:** enable changeDetection + trim web/CLAUDE.md
([#1939](#1939))
([3b1f4c0](3b1f4c0))
* **web,setup:** WP-6 frontend + UX polish
([#1941](#1941))
([d9ca76d](d9ca76d))


### Bug Fixes

* correct invalid git for-each-ref syntax in post-merge-cleanup skill
([#1946](#1946))
([69a1649](69a1649))
* dashboard polish, training endpoint dispatch, and observability
cleanup ([#1911](#1911))
([b61e9e8](b61e9e8))
* per-worktree git-hook isolation + hookify gate migration + MSW drift
fix ([#1949](#1949))
([e3f8495](e3f8495))
* **providers:** read supports_native_streaming from litellm model info
([#1942](#1942))
([60364ca](60364ca))
* security and audit coverage (closes
[#1883](#1883))
([#1904](#1904))
([d8ebf55](d8ebf55))


### Performance

* **ci:** mypy --num-workers=4 + enable ruff TID255
([#1944](#1944))
([484c1d3](484c1d3))


### Refactoring

* **ci:** drop aquasecurity/trivy-action, use direct trivy binary
([#1940](#1940))
([df1f946](df1f946))
* **memory:** per-call processing_kwargs + observability for ST encode
([#1943](#1943))
([3aa9d20](3aa9d20))
* Phase 7 follow-up — complete RootConfig mirror coverage (closes
[#1907](#1907))
([#1914](#1914))
([605500b](605500b))
* **settings:** collapse precedence to three categories; drop YAML tier
(closes [#1890](#1890))
([#1910](#1910))
([efd54c9](efd54c9))
* WP-3 API conventions + query performance + project-wide extra=forbid
([#1953](#1953))
([504d579](504d579)),
closes [#1918](#1918)
* WP-4 settings + cross-cutting (clock seam, contextvars, dispatch,
plugin surfaces)
([#1954](#1954))
([7207d92](7207d92))
* **wp1:** persistence + layer discipline + restart safety
([#1945](#1945))
([57586fb](57586fb))


### Documentation

* **wp5:** public-facing truth refresh
([#1924](#1924))
([afb5cc5](afb5cc5))


### CI/CD

* split test job by marker with airtight aggregate coverage gate
([#1948](#1948))
([0b818d5](0b818d5)),
closes [#1938](#1938)
[#1937](#1937)


### Maintenance

* **codebase-audit:** tighten skill to prevent 2026-05-15 FP classes
([#1923](#1923))
([9317ed1](9317ed1))
* Lock file maintenance
([#1913](#1913))
([c08a355](c08a355))
* Lock file maintenance
([#1950](#1950))
([8940ab1](8940ab1))
* remove TS DTO type-tightening overlays
([#1915](#1915))
([d296214](d296214)),
closes [#1906](#1906)
* Update Infrastructure dependencies
([#1928](#1928))
([d19fae5](d19fae5))
* Update Python dependencies
([#1929](#1929))
([75cc2c8](75cc2c8))
* **wp7:** hygiene, stubs, test/CI/tooling, doc gaps, boundary patterns
doc ([#1926](#1926))
([c29eb32](c29eb32))

---
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: synthorg-repo-bot[bot] <279117679+synthorg-repo-bot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RFC: three-category configuration precedence. Decide AND directly implement

1 participant