Skip to content

Bugfix/stabilize offline ci test suites - #154

Open
marlon-costa-dc wants to merge 2 commits into
mainfrom
bugfix/stabilize-offline-ci-test-suites
Open

Bugfix/stabilize offline ci test suites#154
marlon-costa-dc wants to merge 2 commits into
mainfrom
bugfix/stabilize-offline-ci-test-suites

Conversation

@marlon-costa-dc

Copy link
Copy Markdown
Collaborator

No description provided.

…eview feedback

Merge conflicts:
- Resolved 12 conflicts in test files after release/v0.2.1 test reorganization

Review comment fixes:
- Remove hardcoded api_key from config/smoke-test.toml (gemini + qodo)
- Replace eprintln! with tracing::warn! in instrumented_embedding_tests (gemini)
- Fix provider assertion: expect 'fastembed' not 'openai' in arch validation (qodo)
- Replace .expect() with Result propagation in test_fixtures setup (gemini)
- Replace hardcoded fallback paths with std::env::temp_dir() (qodo)
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@marlon-costa-dc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 87d8a50e-7400-4528-9689-20c998f513be

📥 Commits

Reviewing files that changed from the base of the PR and between a6d22a3 and a1aeead.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • Cargo.toml
  • config/smoke-test.toml
  • crates/mcb-application/tests/unit/decorators/instrumented_embedding_tests.rs
  • crates/mcb-application/tests/unit/registry_tests.rs
  • crates/mcb-application/tests/unit/use_cases/memory_service_tests.rs
  • crates/mcb-application/tests/unit/use_cases/search_tests.rs
  • crates/mcb-infrastructure/tests/integration/di/architecture_validation_tests.rs
  • crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs
  • crates/mcb-infrastructure/tests/integration/di/dispatch_tests.rs
  • crates/mcb-infrastructure/tests/unit/util_tests/file_hash_tests.rs
  • crates/mcb-infrastructure/tests/utils/real_providers.rs
  • crates/mcb-server/tests/utils/real_providers.rs
  • crates/mcb-server/tests/utils/test_fixtures.rs
  • crates/mcb/tests/integration/startup_smoke_integration.rs
  • crates/mcb/tests/integration/stdio_transport_integration.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/stabilize-offline-ci-test-suites

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Stabilize offline CI by making embedding-dependent tests deterministic/optional

🐞 Bug fix 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Make embedding-dependent test suites skip gracefully when FastEmbed models are unavailable.
• Add deterministic embedding fallback to keep server/integration tests runnable offline.
• Adjust embedding configuration and dependencies to avoid hardcoded secrets and improve
 portability.
Diagram

graph TD
  A["Test suites"] --> B["try_shared_app_context()"] --> C["init_app(config)"] --> D["AppContext"] --> E["Embedding handle"] --> F["FastEmbed provider"]
  B --> G["Fallback init_app()"] --> D
  G --> H["Deterministic embedding"] --> E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Ship/cache FastEmbed model artifacts in CI
  • ➕ Keeps testing the real FastEmbed code path everywhere
  • ➕ Avoids skip logic and reduces behavioral divergence between environments
  • ➖ Increases CI complexity and storage/caching concerns
  • ➖ Still brittle when runners disallow downloads or have filesystem constraints
2. Feature-gate provider-dependent tests (online vs offline suites)
  • ➕ Clear separation of concerns; offline CI can run a consistent subset
  • ➕ Avoids runtime skip branches inside tests
  • ➖ Requires CI matrix/config changes and discipline to keep coverage balanced
  • ➖ May hide regressions if the online suite isn’t run regularly
3. Centralize skipping/fallback via a test harness helper/macro
  • ➕ Removes repeated Option/skipping boilerplate across many tests
  • ➕ Makes skip reasons consistent (logging, error classification)
  • ➖ Still a bespoke harness layer to maintain
  • ➖ Refactor cost and churn across test modules

Recommendation: The chosen approach (best-effort shared context + deterministic embedding fallback) is a pragmatic way to keep offline CI green while preserving most behavioral coverage. As a follow-up, consider centralizing skip/fallback plumbing to reduce repetition and explicitly separating “real provider” coverage into a dedicated job when feasible.

Files changed (16) +447 / -171

Tests (13) +427 / -113
instrumented_embedding_tests.rsSkip instrumented embedding tests when shared context is unavailable +19/-11

Skip instrumented embedding tests when shared context is unavailable

• Updates fixtures to use try_shared_app_context() and return Option when the embedding provider can’t be initialized. Replaces stderr printing with tracing::warn! when skipping.

crates/mcb-application/tests/unit/decorators/instrumented_embedding_tests.rs

registry_tests.rsRelax FastEmbed availability assertion under constrained environments +5/-4

Relax FastEmbed availability assertion under constrained environments

• Replaces a hard assertion with a conditional skip-style message when embedding resolution fails. Keeps cache provider assertions intact.

crates/mcb-application/tests/unit/registry_tests.rs

memory_service_tests.rsMake MemoryService integration tests conditional on shared context +29/-13

Make MemoryService integration tests conditional on shared context

• Switches fixture construction to try_shared_app_context() and returns Option to allow skipping when embedding isn’t available. Adds skip messages to each embedding-dependent test.

crates/mcb-application/tests/unit/use_cases/memory_service_tests.rs

search_tests.rsGate SearchService tests behind optional shared context +52/-24

Gate SearchService tests behind optional shared context

• Converts the ContextService fixture to Option and skips tests when the shared AppContext cannot be created. Simplifies service initialization while keeping the same functional assertions when available.

crates/mcb-application/tests/unit/use_cases/search_tests.rs

architecture_validation_tests.rsMake DI architecture validation resilient to missing embedding assets +17/-5

Make DI architecture validation resilient to missing embedding assets

• Uses try_shared_app_context() and skips tests when the AppContext can’t be created. Maintains provider-name and handle-based DI assertions when the context is available.

crates/mcb-infrastructure/tests/integration/di/architecture_validation_tests.rs

catalog_tests.rsForce offline-safe embedding config for DI catalog tests +15/-2

Force offline-safe embedding config for DI catalog tests

• Introduces configure_offline_embedding() to rewrite config to an OpenAI-shaped embedding config with a test key. Ensures catalog build tests don’t depend on local FastEmbed model availability.

crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs

dispatch_tests.rsSwitch dispatch tests to OpenAI-shaped config and optional shared context +17/-8

Switch dispatch tests to OpenAI-shaped config and optional shared context

• Changes embedding config from fastembed to openai in provider selection tests and updates expected provider_name accordingly. Uses try_shared_app_context() for tests that rely on a shared AppContext and skips when unavailable.

crates/mcb-infrastructure/tests/integration/di/dispatch_tests.rs

file_hash_tests.rsSkip file-hash repository tests when shared context is unavailable +33/-15

Skip file-hash repository tests when shared context is unavailable

• Converts the repository fixture to Option and gates each test with a skip path. Keeps the functional file hash repository behavior unchanged when the context exists.

crates/mcb-infrastructure/tests/unit/util_tests/file_hash_tests.rs

real_providers.rsClassify FastEmbed init failures and skip real-provider tests +29/-10

Classify FastEmbed init failures and skip real-provider tests

• Adds a helper to detect FastEmbed model initialization failures and turns hard failures into skips for those cases. Keeps unexpected errors as panics to avoid masking real regressions.

crates/mcb-infrastructure/tests/utils/real_providers.rs

real_providers.rsPropagate shared-context unavailability as Result and skip integrations +53/-16

Propagate shared-context unavailability as Result and skip integrations

• Switches to try_shared_app_context() and returns a typed embedding error when the shared context is missing. Updates integration tests to treat provider unavailability as a skip condition instead of panicking.

crates/mcb-server/tests/utils/real_providers.rs

test_fixtures.rsAdd deterministic embedding fallback to shared test AppContext +154/-5

Add deterministic embedding fallback to shared test AppContext

• Implements a DeterministicEmbeddingProvider and a best-effort try_shared_app_context() initializer that can fall back when FastEmbed model files are missing. Replaces hardcoded fallback paths with std::env::temp_dir(), wires an isolated SQLite path, and keeps shared_app_context() for callers that still want a hard requirement.

crates/mcb-server/tests/utils/test_fixtures.rs

startup_smoke_integration.rsForce OpenAI-shaped embedding env vars in startup smoke test +2/-0

Force OpenAI-shaped embedding env vars in startup smoke test

• Adds embedding provider and API key environment variables when spawning the server. Helps the smoke test run in environments where FastEmbed model assets aren’t present.

crates/mcb/tests/integration/startup_smoke_integration.rs

stdio_transport_integration.rsInject offline-safe embedding env vars for stdio transport tests +2/-0

Inject offline-safe embedding env vars for stdio transport tests

• Adds embedding provider and API key environment variables to the spawned command. Aligns integration test configuration with the offline CI constraints.

crates/mcb/tests/integration/stdio_transport_integration.rs

Other (3) +20 / -58
Cargo.lockAlign dependency graph with updated embedding/runtime requirements +12/-55

Align dependency graph with updated embedding/runtime requirements

• Removes unused transitive crates (e.g., hmac-sha256, lzma-rust2, ureq 3.x entries) and adds libloading. Reflects dependency changes driven by embedding/ORT feature adjustments.

Cargo.lock

Cargo.tomlAdjust FastEmbed features for offline-friendly behavior +3/-1

Adjust FastEmbed features for offline-friendly behavior

• Replaces FastEmbed default feature usage with explicit features (hf-hub-native-tls, image-models, ort-load-dynamic). This reduces implicit dependency pulls and supports dynamic ORT loading.

Cargo.toml

smoke-test.tomlUpdate smoke-test embedding provider configuration +5/-2

Update smoke-test embedding provider configuration

• Switches embedding provider configuration to OpenAI and selects a concrete model. Removes the prior FastEmbed-specific model configuration from this file.

config/smoke-test.toml

@qodo-code-review

qodo-code-review Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (4) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 36 rules

Grey Divider


Action required

1. Dimension mismatch config 🐞 Bug ≡ Correctness ⭐ New
Description
config/smoke-test.toml switches embeddings to OpenAI text-embedding-3-small (1536 dimensions) but
leaves EdgeVec dimensions unspecified, which defaults to 384; any vector insertion/indexing will
then fail at runtime. This makes the smoke-test configuration internally inconsistent and fragile
for any end-to-end flow that actually embeds and stores vectors.
Code

config/smoke-test.toml[R14-22]

+[providers.embedding]
+provider = "openai"
+
[providers.embedding.configs.default]
-provider = "fastembed"
-model = "AllMiniLML6V2"
+provider = "openai"
+model = "text-embedding-3-small"

[providers.vector_store.configs.default]
provider = "edgevec"
Evidence
OpenAI’s provider dimensions are determined by model (1536 for text-embedding-3-small), while
EdgeVec defaults to 384 dimensions when unspecified; EdgeVec constructs its index using that
dimension and inserts vectors directly, so mismatched vector lengths will produce runtime errors.

config/smoke-test.toml[14-23]
crates/mcb-domain/src/constants/embedding.rs[1-10]
crates/mcb-providers/src/embedding/openai.rs[92-100]
crates/mcb-providers/src/vector_store/edgevec.rs[832-843]
crates/mcb-providers/src/vector_store/edgevec.rs[435-453]
crates/mcb-providers/src/vector_store/edgevec.rs[496-524]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Smoke-test/offline config selects OpenAI `text-embedding-3-small` embeddings (1536-d), but the EdgeVec vector store config does not set `dimensions`, and the provider factory defaults omitted dimensions to `384`. This creates a guaranteed dimension mismatch once embeddings are inserted into EdgeVec.

### Issue Context
- OpenAI `text-embedding-3-small` is 1536 dimensions.
- EdgeVec index is constructed with its configured `dimensions` and inserts raw embedding vectors.

### Fix Focus Areas
- config/smoke-test.toml[14-23]
- crates/mcb-providers/src/vector_store/edgevec.rs[832-843]

### Suggested change
- In `config/smoke-test.toml`, set:
 - `[providers.vector_store.configs.default] dimensions = 1536` (to match `text-embedding-3-small`).
- Also audit the other test-only OpenAI configurations introduced in this PR (e.g., `configure_offline_embedding(...)` and dispatch tests) and ensure their vector store dimensions are updated to 1536 when OpenAI is selected, or switch those scenarios to a 384-d embedding provider if EdgeVec is kept at 384.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Init errors silently skipped 🐞 Bug ☼ Reliability
Description
In crates/mcb-server/tests/utils/test_fixtures.rs, try_shared_app_context turns any init_app error
into None, so tests treating None as “skip” can pass even when bootstrap is genuinely broken (bad
config/DB/provider resolution). This can make CI green while core initialization regresses.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R283-288]

+            match result {
+                Ok(ctx) => Some(ctx),
+                Err(err) => {
+                    tracing::warn!("shared init_app failed: {err}");
+                    None
+                }
Evidence
The new helper unconditionally maps any init_app failure to None, while the shared-context macro
used elsewhere only returns None for the FastEmbed/model-missing case and panics on other init
failures.

crates/mcb-server/tests/utils/test_fixtures.rs[283-289]
crates/mcb-infrastructure/src/macros.rs[132-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`try_shared_app_context()` currently logs and returns `None` for *any* `init_app` failure. Callers then return early and the test passes, masking genuine regressions.

### Issue Context
Other test suites use `define_shared_test_context!`, which only returns `None` for the known “FastEmbed model missing” case and otherwise panics.

### Fix Focus Areas
- Update error handling to only return `None` for explicitly recognized “FastEmbed unavailable” (or other intentional skip) errors; for all other errors, fail fast (panic or propagate an error so tests fail).

- crates/mcb-server/tests/utils/test_fixtures.rs[283-289]
- crates/mcb-infrastructure/src/macros.rs[132-143]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Provider actors lose runtime 🐞 Bug ☼ Reliability
Description
try_shared_app_context initializes AppContext inside a temporary Tokio runtime and drops that
runtime when the init thread exits; FastEmbed and EdgeVec providers spawn long-lived actor tasks via
tokio::spawn during construction, so dropping the runtime aborts those tasks and can break provider
behavior later in the test process.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R219-290]

+    CTX.get_or_init(|| {
+        std::thread::spawn(|| -> Option<AppContext> {
+            let rt = match tokio::runtime::Runtime::new() {
+                Ok(rt) => rt,
+                Err(err) => {
+                    tracing::warn!("failed to create runtime for shared app context: {err}");
+                    return None;
+                }
+            };
+            let result = rt.block_on(async {
+                let temp_dir = tempfile::tempdir().map_err(|err| {
+                    mcb_domain::error::Error::config(format!("create temp dir: {err}"))
+                })?;
+                let temp_root = temp_dir.keep();
+                let temp_path = temp_root.join("mcb-fixtures-shared.db");
+
+                let mut config = ConfigLoader::new().load()?;
+                config.providers.database.configs.insert(
+                    "default".to_owned(),
+                    DatabaseConfig {
+                        provider: "sqlite".to_owned(),
+                        path: Some(temp_path),
+                    },
+                );
+                config.providers.embedding.cache_dir = Some(shared_fastembed_test_cache_dir());
+
+                match init_app(config).await {
+                    Ok(ctx) => Ok(ctx),
+                    Err(err) => {
+                        let msg = err.to_string();
+                        if msg.contains("model.onnx")
+                            || msg.contains("Failed to initialize FastEmbed")
+                        {
+                            let mut fallback = ConfigLoader::new().load()?;
+                            let fallback_db_path = std::env::temp_dir()
+                                .join(format!("mcb-fixtures-fallback-{}.db", std::process::id()));
+                            fallback.providers.database.configs.insert(
+                                "default".to_owned(),
+                                DatabaseConfig {
+                                    provider: "sqlite".to_owned(),
+                                    path: Some(fallback_db_path),
+                                },
+                            );
+                            fallback.providers.embedding.provider = Some("openai".to_owned());
+                            fallback.providers.embedding.api_key = Some("test-key".to_owned());
+                            if let Some(cfg) =
+                                fallback.providers.embedding.configs.get_mut("default")
+                            {
+                                cfg.provider = "openai".to_owned();
+                                cfg.model = "text-embedding-3-small".to_owned();
+                                cfg.api_key = Some("test-key".to_owned());
+                            }
+
+                            let ctx = init_app(fallback).await?;
+                            ctx.embedding_handle()
+                                .set(Arc::new(DeterministicEmbeddingProvider));
+                            Ok(ctx)
+                        } else {
+                            Err(err)
+                        }
+                    }
+                }
+            });
+
+            match result {
+                Ok(ctx) => Some(ctx),
+                Err(err) => {
+                    tracing::warn!("shared init_app failed: {err}");
+                    None
+                }
+            }
+        })
Evidence
FastEmbed and EdgeVec spawn their internal actors using tokio::spawn during provider construction,
and the shared-context macro explicitly avoids dropping the init runtime; the new test_fixtures
implementation does not retain the runtime, so those actor tasks can be aborted.

crates/mcb-providers/src/embedding/fastembed.rs[66-80]
crates/mcb-providers/src/vector_store/edgevec.rs[219-233]
crates/mcb-infrastructure/src/macros.rs[113-131]
crates/mcb-server/tests/utils/test_fixtures.rs[219-290]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`try_shared_app_context()` creates providers on a dedicated Tokio runtime and then drops that runtime at the end of initialization. Providers like FastEmbed and EdgeVec spawn actor tasks with `tokio::spawn` during construction; those tasks are tied to the runtime and are aborted when the runtime is dropped.

### Issue Context
The shared test-context macro intentionally prevents dropping the init runtime (via `ManuallyDrop`) to keep spawned tasks alive for the process lifetime.

### Fix Focus Areas
- Retain the initialization runtime for the lifetime of the static `AppContext` (e.g., leak it via `ManuallyDrop` like the macro, or store it in a static alongside the context).
- Prefer reusing `mcb_infrastructure::define_shared_test_context!` + a deterministic-fallback layer rather than re-implementing the shared-context logic.

- crates/mcb-server/tests/utils/test_fixtures.rs[219-290]
- crates/mcb-providers/src/embedding/fastembed.rs[66-80]
- crates/mcb-providers/src/vector_store/edgevec.rs[219-233]
- crates/mcb-infrastructure/src/macros.rs[113-131]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Wrong error variant 🐞 Bug ≡ Correctness ⭐ New
Description
create_real_vector_store() returns Error::embedding when the shared AppContext is unavailable, even
though the failing component is vector-store access; this misclassifies failures and makes
diagnostics misleading. The error message also incorrectly attributes the failure to FastEmbed.
Code

crates/mcb-server/tests/utils/real_providers.rs[R21-25]

+    let Some(ctx) = try_shared_app_context() else {
+        return Err(Error::embedding(
+            "Shared AppContext unavailable — FastEmbed model may be missing",
+        ));
+    };
Evidence
The helper is returning an embedding-specific error for a vector-store helper, despite the domain
error type having distinct variants for embedding vs vector DB failures.

crates/mcb-server/tests/utils/real_providers.rs[19-27]
crates/mcb-domain/src/error/types.rs[72-85]
crates/mcb-domain/src/error/types.rs[247-259]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`create_real_vector_store()` reports `Error::embedding(...)` when `try_shared_app_context()` is `None`, even though the function is retrieving a `VectorStoreProvider`. This mislabels the failure and produces misleading messages.

### Issue Context
This is a test utility; callers may log or branch on error variants.

### Fix Focus Areas
- crates/mcb-server/tests/utils/real_providers.rs[19-27]
- crates/mcb-domain/src/error/types.rs[72-85]

### Suggested change
- Replace `Error::embedding("Shared AppContext unavailable — FastEmbed model may be missing")` with a more accurate variant/message, e.g. `Error::vector_db("Shared AppContext unavailable; cannot create vector store")` (or `Error::config(...)` / `Error::internal(...)` depending on intended semantics).
- Update the message to not mention FastEmbed for the vector-store path.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Duplicated embedding config literals 📘 Rule violation ⚙ Maintainability
Description
The PR repeats configuration-like literals (e.g., openai, text-embedding-3-small, test-key)
directly in multiple files instead of defining a shared constant/helper/config source. This
increases drift risk when the offline test embedding configuration changes again.
Code

crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs[R14-21]

+fn configure_offline_embedding(config: &mut mcb_infrastructure::config::AppConfig) {
+    config.providers.embedding.provider = Some("openai".to_owned());
+    config.providers.embedding.api_key = Some("test-key".to_owned());
+    if let Some(default_cfg) = config.providers.embedding.configs.get_mut("default") {
+        default_cfg.provider = "openai".to_owned();
+        default_cfg.model = "text-embedding-3-small".to_owned();
+        default_cfg.api_key = Some("test-key".to_owned());
+    }
Evidence
The rule requires configuration-like values (provider names/models/keys) to be centralized rather
than repeated. The same literals are present in multiple changed locations (test DI config helper,
shared test AppContext fallback config, and smoke-test config).

Rule 1206977: Centralize configuration values and reuse them instead of duplicating literals
crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs[14-21]
crates/mcb-server/tests/utils/test_fixtures.rs[262-270]
config/smoke-test.toml[14-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Embedding-provider configuration literals are duplicated across multiple changed files.

## Issue Context
Compliance requires centralizing configuration-like values and reusing shared definitions instead of duplicating literals.

## Fix Focus Areas
- crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs[14-21]
- crates/mcb-server/tests/utils/test_fixtures.rs[262-270]
- config/smoke-test.toml[14-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. tempfile import order wrong 📘 Rule violation ⚙ Maintainability
Description
crates/mcb-server/tests/utils/test_fixtures.rs places the external crate import `use
tempfile::TempDir; after mcb_*` imports, breaking the required grouped import ordering. This can
cause inconsistent style and churn in diffs across the codebase.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R9-24]

use std::path::{Path, PathBuf};
use std::sync::Arc;

+use async_trait::async_trait;
+
+use mcb_domain::error::Result;
+use mcb_domain::ports::EmbeddingProvider;
+use mcb_domain::ports::IndexingResult;
+use mcb_domain::registry::database::{DatabaseProviderConfig, resolve_database_provider};
+use mcb_domain::value_objects::Embedding;
+use mcb_infrastructure::config::{ConfigLoader, DatabaseConfig};
+use mcb_infrastructure::di::bootstrap::{AppContext, init_app};
+use mcb_infrastructure::di::modules::domain_services::DomainServicesFactory;
use mcb_server::McpServerBuilder;
use mcb_server::mcp_server::McpServer;
use tempfile::TempDir;
Evidence
The import order rule requires grouping std first, then external crates, then mcb_* crates;
however tempfile (external) is placed after mcb_domain/mcb_infrastructure/mcb_server
imports.

Rule 1207880: Enforce grouped and ordered Rust imports: std, external crates, mcb_*, then local modules
crates/mcb-server/tests/utils/test_fixtures.rs[9-24]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`use` imports are not grouped/ordered as required: `tempfile` (external crate) appears after `mcb_*` imports.

## Issue Context
Compliance requires grouped and ordered Rust imports: `std`, then external crates, then `mcb_*`, then local modules.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[9-24]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
7. try_shared_app_context uses fallback config 📘 Rule violation ☼ Reliability
Description
When init_app(config) fails (e.g., missing FastEmbed model), try_shared_app_context()
substitutes a fallback configuration and overrides the embedding provider with a deterministic
implementation instead of failing initialization. This violates the requirement to fail fast when
required external configuration/resources are missing at startup.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R245-276]

+                match init_app(config).await {
+                    Ok(ctx) => Ok(ctx),
+                    Err(err) => {
+                        let msg = err.to_string();
+                        if msg.contains("model.onnx")
+                            || msg.contains("Failed to initialize FastEmbed")
+                        {
+                            let mut fallback = ConfigLoader::new().load()?;
+                            let fallback_db_path = std::env::temp_dir()
+                                .join(format!("mcb-fixtures-fallback-{}.db", std::process::id()));
+                            fallback.providers.database.configs.insert(
+                                "default".to_owned(),
+                                DatabaseConfig {
+                                    provider: "sqlite".to_owned(),
+                                    path: Some(fallback_db_path),
+                                },
+                            );
+                            fallback.providers.embedding.provider = Some("openai".to_owned());
+                            fallback.providers.embedding.api_key = Some("test-key".to_owned());
+                            if let Some(cfg) =
+                                fallback.providers.embedding.configs.get_mut("default")
+                            {
+                                cfg.provider = "openai".to_owned();
+                                cfg.model = "text-embedding-3-small".to_owned();
+                                cfg.api_key = Some("test-key".to_owned());
+                            }
+
+                            let ctx = init_app(fallback).await?;
+                            ctx.embedding_handle()
+                                .set(Arc::new(DeterministicEmbeddingProvider));
+                            Ok(ctx)
+                        } else {
Evidence
The rule requires missing required external configuration/resources to cause an explicit startup
failure. Here, the code catches init_app failure and proceeds by loading a new config
(fallback), forcing openai provider settings, and then swapping in
DeterministicEmbeddingProvider, allowing initialization to proceed despite the missing model.

Rule 1206783: Fail fast when required external configuration is missing at startup
crates/mcb-server/tests/utils/test_fixtures.rs[245-276]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Startup/config initialization falls back to an alternate configuration when required resources are missing, instead of failing fast.

## Issue Context
Compliance requires explicit startup failure when required external configuration or resources are unavailable; fallback behavior should be avoided or explicitly gated by a documented test-only flag.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[245-276]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. test_fixtures.rs too long 📘 Rule violation ⚙ Maintainability
Description
crates/mcb-server/tests/utils/test_fixtures.rs is at least 308 lines long after this change (line
numbers reach 308+), exceeding the ~200 line guideline. This makes the test fixture module harder to
navigate and maintain.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R300-308]

+pub fn shared_app_context() -> &'static AppContext {
+    try_shared_app_context().unwrap_or_else(|| {
+        tracing::error!("shared AppContext init failed");
+        panic!("shared AppContext init failed");
+    })
+}

// ---------------------------------------------------------------------------
// create_test_mcp_server
Evidence
The checklist requires keeping modified source files under ~200 lines; the diff shows content and
line numbers extending past 300 in this file, indicating it exceeds the threshold.

Rule 1208563: Source files must not exceed ~200 lines
crates/mcb-server/tests/utils/test_fixtures.rs[300-308]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The modified Rust source file exceeds the ~200 line limit and should be split.

## Issue Context
Large fixture modules become hard to maintain; splitting into focused submodules keeps responsibilities clearer.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[159-308]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit a1aeead ⚖️ Balanced

Results up to commit a1aeead ⚖️ Balanced


🐞 Bugs (2) 📘 Rule violations (4) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Init errors silently skipped 🐞 Bug ☼ Reliability
Description
In crates/mcb-server/tests/utils/test_fixtures.rs, try_shared_app_context turns any init_app error
into None, so tests treating None as “skip” can pass even when bootstrap is genuinely broken (bad
config/DB/provider resolution). This can make CI green while core initialization regresses.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R283-288]

+            match result {
+                Ok(ctx) => Some(ctx),
+                Err(err) => {
+                    tracing::warn!("shared init_app failed: {err}");
+                    None
+                }
Evidence
The new helper unconditionally maps any init_app failure to None, while the shared-context macro
used elsewhere only returns None for the FastEmbed/model-missing case and panics on other init
failures.

crates/mcb-server/tests/utils/test_fixtures.rs[283-289]
crates/mcb-infrastructure/src/macros.rs[132-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`try_shared_app_context()` currently logs and returns `None` for *any* `init_app` failure. Callers then return early and the test passes, masking genuine regressions.

### Issue Context
Other test suites use `define_shared_test_context!`, which only returns `None` for the known “FastEmbed model missing” case and otherwise panics.

### Fix Focus Areas
- Update error handling to only return `None` for explicitly recognized “FastEmbed unavailable” (or other intentional skip) errors; for all other errors, fail fast (panic or propagate an error so tests fail).

- crates/mcb-server/tests/utils/test_fixtures.rs[283-289]
- crates/mcb-infrastructure/src/macros.rs[132-143]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Provider actors lose runtime 🐞 Bug ☼ Reliability
Description
try_shared_app_context initializes AppContext inside a temporary Tokio runtime and drops that
runtime when the init thread exits; FastEmbed and EdgeVec providers spawn long-lived actor tasks via
tokio::spawn during construction, so dropping the runtime aborts those tasks and can break provider
behavior later in the test process.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R219-290]

+    CTX.get_or_init(|| {
+        std::thread::spawn(|| -> Option<AppContext> {
+            let rt = match tokio::runtime::Runtime::new() {
+                Ok(rt) => rt,
+                Err(err) => {
+                    tracing::warn!("failed to create runtime for shared app context: {err}");
+                    return None;
+                }
+            };
+            let result = rt.block_on(async {
+                let temp_dir = tempfile::tempdir().map_err(|err| {
+                    mcb_domain::error::Error::config(format!("create temp dir: {err}"))
+                })?;
+                let temp_root = temp_dir.keep();
+                let temp_path = temp_root.join("mcb-fixtures-shared.db");
+
+                let mut config = ConfigLoader::new().load()?;
+                config.providers.database.configs.insert(
+                    "default".to_owned(),
+                    DatabaseConfig {
+                        provider: "sqlite".to_owned(),
+                        path: Some(temp_path),
+                    },
+                );
+                config.providers.embedding.cache_dir = Some(shared_fastembed_test_cache_dir());
+
+                match init_app(config).await {
+                    Ok(ctx) => Ok(ctx),
+                    Err(err) => {
+                        let msg = err.to_string();
+                        if msg.contains("model.onnx")
+                            || msg.contains("Failed to initialize FastEmbed")
+                        {
+                            let mut fallback = ConfigLoader::new().load()?;
+                            let fallback_db_path = std::env::temp_dir()
+                                .join(format!("mcb-fixtures-fallback-{}.db", std::process::id()));
+                            fallback.providers.database.configs.insert(
+                                "default".to_owned(),
+                                DatabaseConfig {
+                                    provider: "sqlite".to_owned(),
+                                    path: Some(fallback_db_path),
+                                },
+                            );
+                            fallback.providers.embedding.provider = Some("openai".to_owned());
+                            fallback.providers.embedding.api_key = Some("test-key".to_owned());
+                            if let Some(cfg) =
+                                fallback.providers.embedding.configs.get_mut("default")
+                            {
+                                cfg.provider = "openai".to_owned();
+                                cfg.model = "text-embedding-3-small".to_owned();
+                                cfg.api_key = Some("test-key".to_owned());
+                            }
+
+                            let ctx = init_app(fallback).await?;
+                            ctx.embedding_handle()
+                                .set(Arc::new(DeterministicEmbeddingProvider));
+                            Ok(ctx)
+                        } else {
+                            Err(err)
+                        }
+                    }
+                }
+            });
+
+            match result {
+                Ok(ctx) => Some(ctx),
+                Err(err) => {
+                    tracing::warn!("shared init_app failed: {err}");
+                    None
+                }
+            }
+        })
Evidence
FastEmbed and EdgeVec spawn their internal actors using tokio::spawn during provider construction,
and the shared-context macro explicitly avoids dropping the init runtime; the new test_fixtures
implementation does not retain the runtime, so those actor tasks can be aborted.

crates/mcb-providers/src/embedding/fastembed.rs[66-80]
crates/mcb-providers/src/vector_store/edgevec.rs[219-233]
crates/mcb-infrastructure/src/macros.rs[113-131]
crates/mcb-server/tests/utils/test_fixtures.rs[219-290]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`try_shared_app_context()` creates providers on a dedicated Tokio runtime and then drops that runtime at the end of initialization. Providers like FastEmbed and EdgeVec spawn actor tasks with `tokio::spawn` during construction; those tasks are tied to the runtime and are aborted when the runtime is dropped.

### Issue Context
The shared test-context macro intentionally prevents dropping the init runtime (via `ManuallyDrop`) to keep spawned tasks alive for the process lifetime.

### Fix Focus Areas
- Retain the initialization runtime for the lifetime of the static `AppContext` (e.g., leak it via `ManuallyDrop` like the macro, or store it in a static alongside the context).
- Prefer reusing `mcb_infrastructure::define_shared_test_context!` + a deterministic-fallback layer rather than re-implementing the shared-context logic.

- crates/mcb-server/tests/utils/test_fixtures.rs[219-290]
- crates/mcb-providers/src/embedding/fastembed.rs[66-80]
- crates/mcb-providers/src/vector_store/edgevec.rs[219-233]
- crates/mcb-infrastructure/src/macros.rs[113-131]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
3. tempfile import order wrong 📘 Rule violation ⚙ Maintainability
Description
crates/mcb-server/tests/utils/test_fixtures.rs places the external crate import `use
tempfile::TempDir; after mcb_*` imports, breaking the required grouped import ordering. This can
cause inconsistent style and churn in diffs across the codebase.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R9-24]

use std::path::{Path, PathBuf};
use std::sync::Arc;

+use async_trait::async_trait;
+
+use mcb_domain::error::Result;
+use mcb_domain::ports::EmbeddingProvider;
+use mcb_domain::ports::IndexingResult;
+use mcb_domain::registry::database::{DatabaseProviderConfig, resolve_database_provider};
+use mcb_domain::value_objects::Embedding;
+use mcb_infrastructure::config::{ConfigLoader, DatabaseConfig};
+use mcb_infrastructure::di::bootstrap::{AppContext, init_app};
+use mcb_infrastructure::di::modules::domain_services::DomainServicesFactory;
use mcb_server::McpServerBuilder;
use mcb_server::mcp_server::McpServer;
use tempfile::TempDir;
Evidence
The import order rule requires grouping std first, then external crates, then mcb_* crates;
however tempfile (external) is placed after mcb_domain/mcb_infrastructure/mcb_server
imports.

Rule 1207880: Enforce grouped and ordered Rust imports: std, external crates, mcb_*, then local modules
crates/mcb-server/tests/utils/test_fixtures.rs[9-24]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`use` imports are not grouped/ordered as required: `tempfile` (external crate) appears after `mcb_*` imports.

## Issue Context
Compliance requires grouped and ordered Rust imports: `std`, then external crates, then `mcb_*`, then local modules.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[9-24]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. test_fixtures.rs too long 📘 Rule violation ⚙ Maintainability
Description
crates/mcb-server/tests/utils/test_fixtures.rs is at least 308 lines long after this change (line
numbers reach 308+), exceeding the ~200 line guideline. This makes the test fixture module harder to
navigate and maintain.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R300-308]

+pub fn shared_app_context() -> &'static AppContext {
+    try_shared_app_context().unwrap_or_else(|| {
+        tracing::error!("shared AppContext init failed");
+        panic!("shared AppContext init failed");
+    })
+}

// ---------------------------------------------------------------------------
// create_test_mcp_server
Evidence
The checklist requires keeping modified source files under ~200 lines; the diff shows content and
line numbers extending past 300 in this file, indicating it exceeds the threshold.

Rule 1208563: Source files must not exceed ~200 lines
crates/mcb-server/tests/utils/test_fixtures.rs[300-308]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The modified Rust source file exceeds the ~200 line limit and should be split.

## Issue Context
Large fixture modules become hard to maintain; splitting into focused submodules keeps responsibilities clearer.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[159-308]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. try_shared_app_context uses fallback config 📘 Rule violation ☼ Reliability
Description
When init_app(config) fails (e.g., missing FastEmbed model), try_shared_app_context()
substitutes a fallback configuration and overrides the embedding provider with a deterministic
implementation instead of failing initialization. This violates the requirement to fail fast when
required external configuration/resources are missing at startup.
Code

crates/mcb-server/tests/utils/test_fixtures.rs[R245-276]

+                match init_app(config).await {
+                    Ok(ctx) => Ok(ctx),
+                    Err(err) => {
+                        let msg = err.to_string();
+                        if msg.contains("model.onnx")
+                            || msg.contains("Failed to initialize FastEmbed")
+                        {
+                            let mut fallback = ConfigLoader::new().load()?;
+                            let fallback_db_path = std::env::temp_dir()
+                                .join(format!("mcb-fixtures-fallback-{}.db", std::process::id()));
+                            fallback.providers.database.configs.insert(
+                                "default".to_owned(),
+                                DatabaseConfig {
+                                    provider: "sqlite".to_owned(),
+                                    path: Some(fallback_db_path),
+                                },
+                            );
+                            fallback.providers.embedding.provider = Some("openai".to_owned());
+                            fallback.providers.embedding.api_key = Some("test-key".to_owned());
+                            if let Some(cfg) =
+                                fallback.providers.embedding.configs.get_mut("default")
+                            {
+                                cfg.provider = "openai".to_owned();
+                                cfg.model = "text-embedding-3-small".to_owned();
+                                cfg.api_key = Some("test-key".to_owned());
+                            }
+
+                            let ctx = init_app(fallback).await?;
+                            ctx.embedding_handle()
+                                .set(Arc::new(DeterministicEmbeddingProvider));
+                            Ok(ctx)
+                        } else {
Evidence
The rule requires missing required external configuration/resources to cause an explicit startup
failure. Here, the code catches init_app failure and proceeds by loading a new config
(fallback), forcing openai provider settings, and then swapping in
DeterministicEmbeddingProvider, allowing initialization to proceed despite the missing model.

Rule 1206783: Fail fast when required external configuration is missing at startup
crates/mcb-server/tests/utils/test_fixtures.rs[245-276]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Startup/config initialization falls back to an alternate configuration when required resources are missing, instead of failing fast.

## Issue Context
Compliance requires explicit startup failure when required external configuration or resources are unavailable; fallback behavior should be avoided or explicitly gated by a documented test-only flag.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[245-276]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
6. Duplicated embedding config literals 📘 Rule violation ⚙ Maintainability
Description
The PR repeats configuration-like literals (e.g., openai, text-embedding-3-small, test-key)
directly in multiple files instead of defining a shared constant/helper/config source. This
increases drift risk when the offline test embedding configuration changes again.
Code

crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs[R14-21]

+fn configure_offline_embedding(config: &mut mcb_infrastructure::config::AppConfig) {
+    config.providers.embedding.provider = Some("openai".to_owned());
+    config.providers.embedding.api_key = Some("test-key".to_owned());
+    if let Some(default_cfg) = config.providers.embedding.configs.get_mut("default") {
+        default_cfg.provider = "openai".to_owned();
+        default_cfg.model = "text-embedding-3-small".to_owned();
+        default_cfg.api_key = Some("test-key".to_owned());
+    }
Evidence
The rule requires configuration-like values (provider names/models/keys) to be centralized rather
than repeated. The same literals are present in multiple changed locations (test DI config helper,
shared test AppContext fallback config, and smoke-test config).

Rule 1206977: Centralize configuration values and reuse them instead of duplicating literals
crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs[14-21]
crates/mcb-server/tests/utils/test_fixtures.rs[262-270]
config/smoke-test.toml[14-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Embedding-provider configuration literals are duplicated across multiple changed files.

## Issue Context
Compliance requires centralizing configuration-like values and reusing shared definitions instead of duplicating literals.

## Fix Focus Areas
- crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs[14-21]
- crates/mcb-server/tests/utils/test_fixtures.rs[262-270]
- config/smoke-test.toml[14-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment on lines 9 to 24
use std::path::{Path, PathBuf};
use std::sync::Arc;

use async_trait::async_trait;

use mcb_domain::error::Result;
use mcb_domain::ports::EmbeddingProvider;
use mcb_domain::ports::IndexingResult;
use mcb_domain::registry::database::{DatabaseProviderConfig, resolve_database_provider};
use mcb_domain::value_objects::Embedding;
use mcb_infrastructure::config::{ConfigLoader, DatabaseConfig};
use mcb_infrastructure::di::bootstrap::{AppContext, init_app};
use mcb_infrastructure::di::modules::domain_services::DomainServicesFactory;
use mcb_server::McpServerBuilder;
use mcb_server::mcp_server::McpServer;
use tempfile::TempDir;

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.

Remediation recommended

1. tempfile import order wrong 📘 Rule violation ⚙ Maintainability

crates/mcb-server/tests/utils/test_fixtures.rs places the external crate import `use
tempfile::TempDir; after mcb_*` imports, breaking the required grouped import ordering. This can
cause inconsistent style and churn in diffs across the codebase.
Agent Prompt
## Issue description
`use` imports are not grouped/ordered as required: `tempfile` (external crate) appears after `mcb_*` imports.

## Issue Context
Compliance requires grouped and ordered Rust imports: `std`, then external crates, then `mcb_*`, then local modules.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[9-24]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +300 to 308
pub fn shared_app_context() -> &'static AppContext {
try_shared_app_context().unwrap_or_else(|| {
tracing::error!("shared AppContext init failed");
panic!("shared AppContext init failed");
})
}

// ---------------------------------------------------------------------------
// create_test_mcp_server

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.

Remediation recommended

2. test_fixtures.rs too long 📘 Rule violation ⚙ Maintainability

crates/mcb-server/tests/utils/test_fixtures.rs is at least 308 lines long after this change (line
numbers reach 308+), exceeding the ~200 line guideline. This makes the test fixture module harder to
navigate and maintain.
Agent Prompt
## Issue description
The modified Rust source file exceeds the ~200 line limit and should be split.

## Issue Context
Large fixture modules become hard to maintain; splitting into focused submodules keeps responsibilities clearer.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[159-308]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +245 to +276
match init_app(config).await {
Ok(ctx) => Ok(ctx),
Err(err) => {
let msg = err.to_string();
if msg.contains("model.onnx")
|| msg.contains("Failed to initialize FastEmbed")
{
let mut fallback = ConfigLoader::new().load()?;
let fallback_db_path = std::env::temp_dir()
.join(format!("mcb-fixtures-fallback-{}.db", std::process::id()));
fallback.providers.database.configs.insert(
"default".to_owned(),
DatabaseConfig {
provider: "sqlite".to_owned(),
path: Some(fallback_db_path),
},
);
fallback.providers.embedding.provider = Some("openai".to_owned());
fallback.providers.embedding.api_key = Some("test-key".to_owned());
if let Some(cfg) =
fallback.providers.embedding.configs.get_mut("default")
{
cfg.provider = "openai".to_owned();
cfg.model = "text-embedding-3-small".to_owned();
cfg.api_key = Some("test-key".to_owned());
}

let ctx = init_app(fallback).await?;
ctx.embedding_handle()
.set(Arc::new(DeterministicEmbeddingProvider));
Ok(ctx)
} else {

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.

Remediation recommended

3. try_shared_app_context uses fallback config 📘 Rule violation ☼ Reliability

When init_app(config) fails (e.g., missing FastEmbed model), try_shared_app_context()
substitutes a fallback configuration and overrides the embedding provider with a deterministic
implementation instead of failing initialization. This violates the requirement to fail fast when
required external configuration/resources are missing at startup.
Agent Prompt
## Issue description
Startup/config initialization falls back to an alternate configuration when required resources are missing, instead of failing fast.

## Issue Context
Compliance requires explicit startup failure when required external configuration or resources are unavailable; fallback behavior should be avoided or explicitly gated by a documented test-only flag.

## Fix Focus Areas
- crates/mcb-server/tests/utils/test_fixtures.rs[245-276]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +14 to +21
fn configure_offline_embedding(config: &mut mcb_infrastructure::config::AppConfig) {
config.providers.embedding.provider = Some("openai".to_owned());
config.providers.embedding.api_key = Some("test-key".to_owned());
if let Some(default_cfg) = config.providers.embedding.configs.get_mut("default") {
default_cfg.provider = "openai".to_owned();
default_cfg.model = "text-embedding-3-small".to_owned();
default_cfg.api_key = Some("test-key".to_owned());
}

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.

Remediation recommended

4. Duplicated embedding config literals 📘 Rule violation ⚙ Maintainability

The PR repeats configuration-like literals (e.g., openai, text-embedding-3-small, test-key)
directly in multiple files instead of defining a shared constant/helper/config source. This
increases drift risk when the offline test embedding configuration changes again.
Agent Prompt
## Issue description
Embedding-provider configuration literals are duplicated across multiple changed files.

## Issue Context
Compliance requires centralizing configuration-like values and reusing shared definitions instead of duplicating literals.

## Fix Focus Areas
- crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs[14-21]
- crates/mcb-server/tests/utils/test_fixtures.rs[262-270]
- config/smoke-test.toml[14-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +283 to +288
match result {
Ok(ctx) => Some(ctx),
Err(err) => {
tracing::warn!("shared init_app failed: {err}");
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.

Action required

5. Init errors silently skipped 🐞 Bug ☼ Reliability

In crates/mcb-server/tests/utils/test_fixtures.rs, try_shared_app_context turns any init_app error
into None, so tests treating None as “skip” can pass even when bootstrap is genuinely broken (bad
config/DB/provider resolution). This can make CI green while core initialization regresses.
Agent Prompt
### Issue description
`try_shared_app_context()` currently logs and returns `None` for *any* `init_app` failure. Callers then return early and the test passes, masking genuine regressions.

### Issue Context
Other test suites use `define_shared_test_context!`, which only returns `None` for the known “FastEmbed model missing” case and otherwise panics.

### Fix Focus Areas
- Update error handling to only return `None` for explicitly recognized “FastEmbed unavailable” (or other intentional skip) errors; for all other errors, fail fast (panic or propagate an error so tests fail).

- crates/mcb-server/tests/utils/test_fixtures.rs[283-289]
- crates/mcb-infrastructure/src/macros.rs[132-143]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +219 to +290
CTX.get_or_init(|| {
std::thread::spawn(|| -> Option<AppContext> {
let rt = match tokio::runtime::Runtime::new() {
Ok(rt) => rt,
Err(err) => {
tracing::warn!("failed to create runtime for shared app context: {err}");
return None;
}
};
let result = rt.block_on(async {
let temp_dir = tempfile::tempdir().map_err(|err| {
mcb_domain::error::Error::config(format!("create temp dir: {err}"))
})?;
let temp_root = temp_dir.keep();
let temp_path = temp_root.join("mcb-fixtures-shared.db");

let mut config = ConfigLoader::new().load()?;
config.providers.database.configs.insert(
"default".to_owned(),
DatabaseConfig {
provider: "sqlite".to_owned(),
path: Some(temp_path),
},
);
config.providers.embedding.cache_dir = Some(shared_fastembed_test_cache_dir());

match init_app(config).await {
Ok(ctx) => Ok(ctx),
Err(err) => {
let msg = err.to_string();
if msg.contains("model.onnx")
|| msg.contains("Failed to initialize FastEmbed")
{
let mut fallback = ConfigLoader::new().load()?;
let fallback_db_path = std::env::temp_dir()
.join(format!("mcb-fixtures-fallback-{}.db", std::process::id()));
fallback.providers.database.configs.insert(
"default".to_owned(),
DatabaseConfig {
provider: "sqlite".to_owned(),
path: Some(fallback_db_path),
},
);
fallback.providers.embedding.provider = Some("openai".to_owned());
fallback.providers.embedding.api_key = Some("test-key".to_owned());
if let Some(cfg) =
fallback.providers.embedding.configs.get_mut("default")
{
cfg.provider = "openai".to_owned();
cfg.model = "text-embedding-3-small".to_owned();
cfg.api_key = Some("test-key".to_owned());
}

let ctx = init_app(fallback).await?;
ctx.embedding_handle()
.set(Arc::new(DeterministicEmbeddingProvider));
Ok(ctx)
} else {
Err(err)
}
}
}
});

match result {
Ok(ctx) => Some(ctx),
Err(err) => {
tracing::warn!("shared init_app failed: {err}");
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.

Action required

6. Provider actors lose runtime 🐞 Bug ☼ Reliability

try_shared_app_context initializes AppContext inside a temporary Tokio runtime and drops that
runtime when the init thread exits; FastEmbed and EdgeVec providers spawn long-lived actor tasks via
tokio::spawn during construction, so dropping the runtime aborts those tasks and can break provider
behavior later in the test process.
Agent Prompt
### Issue description
`try_shared_app_context()` creates providers on a dedicated Tokio runtime and then drops that runtime at the end of initialization. Providers like FastEmbed and EdgeVec spawn actor tasks with `tokio::spawn` during construction; those tasks are tied to the runtime and are aborted when the runtime is dropped.

### Issue Context
The shared test-context macro intentionally prevents dropping the init runtime (via `ManuallyDrop`) to keep spawned tasks alive for the process lifetime.

### Fix Focus Areas
- Retain the initialization runtime for the lifetime of the static `AppContext` (e.g., leak it via `ManuallyDrop` like the macro, or store it in a static alongside the context).
- Prefer reusing `mcb_infrastructure::define_shared_test_context!` + a deterministic-fallback layer rather than re-implementing the shared-context logic.

- crates/mcb-server/tests/utils/test_fixtures.rs[219-290]
- crates/mcb-providers/src/embedding/fastembed.rs[66-80]
- crates/mcb-providers/src/vector_store/edgevec.rs[219-233]
- crates/mcb-infrastructure/src/macros.rs[113-131]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +21 to +25
let Some(ctx) = try_shared_app_context() else {
return Err(Error::embedding(
"Shared AppContext unavailable — FastEmbed model may be missing",
));
};

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.

Remediation recommended

1. Wrong error variant 🐞 Bug ≡ Correctness

create_real_vector_store() returns Error::embedding when the shared AppContext is unavailable, even
though the failing component is vector-store access; this misclassifies failures and makes
diagnostics misleading. The error message also incorrectly attributes the failure to FastEmbed.
Agent Prompt
### Issue description
`create_real_vector_store()` reports `Error::embedding(...)` when `try_shared_app_context()` is `None`, even though the function is retrieving a `VectorStoreProvider`. This mislabels the failure and produces misleading messages.

### Issue Context
This is a test utility; callers may log or branch on error variants.

### Fix Focus Areas
- crates/mcb-server/tests/utils/real_providers.rs[19-27]
- crates/mcb-domain/src/error/types.rs[72-85]

### Suggested change
- Replace `Error::embedding("Shared AppContext unavailable — FastEmbed model may be missing")` with a more accurate variant/message, e.g. `Error::vector_db("Shared AppContext unavailable; cannot create vector store")` (or `Error::config(...)` / `Error::internal(...)` depending on intended semantics).
- Update the message to not mention FastEmbed for the vector-store path.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread config/smoke-test.toml
Comment on lines +14 to 22
[providers.embedding]
provider = "openai"

[providers.embedding.configs.default]
provider = "fastembed"
model = "AllMiniLML6V2"
provider = "openai"
model = "text-embedding-3-small"

[providers.vector_store.configs.default]
provider = "edgevec"

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.

Action required

2. Dimension mismatch config 🐞 Bug ≡ Correctness

config/smoke-test.toml switches embeddings to OpenAI text-embedding-3-small (1536 dimensions) but
leaves EdgeVec dimensions unspecified, which defaults to 384; any vector insertion/indexing will
then fail at runtime. This makes the smoke-test configuration internally inconsistent and fragile
for any end-to-end flow that actually embeds and stores vectors.
Agent Prompt
### Issue description
Smoke-test/offline config selects OpenAI `text-embedding-3-small` embeddings (1536-d), but the EdgeVec vector store config does not set `dimensions`, and the provider factory defaults omitted dimensions to `384`. This creates a guaranteed dimension mismatch once embeddings are inserted into EdgeVec.

### Issue Context
- OpenAI `text-embedding-3-small` is 1536 dimensions.
- EdgeVec index is constructed with its configured `dimensions` and inserts raw embedding vectors.

### Fix Focus Areas
- config/smoke-test.toml[14-23]
- crates/mcb-providers/src/vector_store/edgevec.rs[832-843]

### Suggested change
- In `config/smoke-test.toml`, set:
  - `[providers.vector_store.configs.default] dimensions = 1536` (to match `text-embedding-3-small`).
- Also audit the other test-only OpenAI configurations introduced in this PR (e.g., `configure_offline_embedding(...)` and dispatch tests) and ensure their vector store dimensions are updated to 1536 when OpenAI is selected, or switch those scenarios to a 384-d embedding provider if EdgeVec is kept at 384.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit a1aeead

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

7 issues found across 16 files

Confidence score: 2/5

  • Cargo.toml switches FastEmbed to ort-load-dynamic, which can panic on clean CI and standalone installs when ONNX Runtime is missing, creating a concrete runtime break for embedding initialization—either package the shared library with releases or revert to a loading mode that works out of the box.
  • crates/mcb-infrastructure/tests/integration/di/dispatch_tests.rs and crates/mcb-server/tests/utils/test_fixtures.rs now make provider assertions brittle and can treat real initialization failures as skips, so regressions in config/DI/provider wiring may pass unnoticed—tighten the assertions and only skip on explicit, narrow offline conditions.
  • crates/mcb-server/tests/utils/test_fixtures.rs reports the fallback as FastEmbed, so tests intended to validate the real ONNX path can accidentally exercise the stub and still appear correct—give fallback and real providers distinct identities and assert on them directly.
  • crates/mcb-infrastructure/tests/unit/util_tests/file_hash_tests.rs, crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs, and config/smoke-test.toml reduce coverage signal (unnecessary offline skips, duplicated catalog behavior, ignored model setting), which increases the chance of config regressions slipping through—decouple non-embedding tests from AppContext embedding init and restore a true custom-config path in smoke/integration tests.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="config/smoke-test.toml">

<violation number="1" location="config/smoke-test.toml:15">
P3: The configured `text-embedding-3-small` value is ignored because setting the direct `providers.embedding.provider` makes the resolver bypass `configs.default`. Keeping `model` in the direct section would make this smoke configuration effective rather than relying on OpenAI's coincidentally matching factory default.</violation>
</file>

<file name="Cargo.toml">

<violation number="1" location="Cargo.toml:253">
P0: FastEmbed initialization now panics on clean CI hosts and standalone release installs because `ort-load-dynamic` requires an external ONNX Runtime shared library that is neither installed nor packaged. Keeping the prior download-binaries backend, or adding explicit cross-platform dylib installation/packaging and `ORT_DYLIB_PATH`, preserves the default local embedding provider.</violation>
</file>

<file name="crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs">

<violation number="1" location="crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs:29">
P3: `test_catalog_builds_with_custom_embedding_config` is now behaviorally identical to `test_catalog_builds_with_default_config`, so the custom-config coverage has been lost while the suite still appears to test it. Consider giving this case a distinct override (and asserting the selected provider/config), or removing/renaming the duplicate test.</violation>
</file>

<file name="crates/mcb-infrastructure/tests/integration/di/dispatch_tests.rs">

<violation number="1" location="crates/mcb-infrastructure/tests/integration/di/dispatch_tests.rs:68">
P1: This test still resolves FastEmbed, so the new `"openai"` assertion fails whenever initialization succeeds (and offline initialization may fail before the assertion). `test_config()` retains the direct `providers.embedding.provider = "fastembed"` value from `config/default.toml`, and the resolver gives that field precedence over `configs["default"]`. The test setup should also set the direct provider and API key to OpenAI, as the catalog tests now do, or clear the direct provider so the named config is exercised.</violation>
</file>

<file name="crates/mcb-infrastructure/tests/unit/util_tests/file_hash_tests.rs">

<violation number="1" location="crates/mcb-infrastructure/tests/unit/util_tests/file_hash_tests.rs:26">
P2: Offline CI now silently skips the file-hash repository tests even though these cases do not need embeddings. Their fixture couples `FileHashRepository` to an AppContext whose creation can return `None` solely because the ONNX model is unavailable, and each test then returns as a passing test. A SQLite-backed file-hash fixture initialized independently of FastEmbed would retain this coverage in the offline suite; only the final full indexing test needs the complete context.</violation>
</file>

<file name="crates/mcb-server/tests/utils/test_fixtures.rs">

<violation number="1" location="crates/mcb-server/tests/utils/test_fixtures.rs:193">
P2: The fallback identifies itself as FastEmbed, so `create_real_embedding_provider` and the real-provider tests cannot distinguish the length-based stub from the actual ONNX provider. In an offline run, tests named and documented as exercising real FastEmbed therefore report success without loading or invoking FastEmbed. Giving the fallback its own provider name (and having real-provider fixtures reject/skip that name) would keep generic server tests offline-capable without producing a false real-provider signal.</violation>

<violation number="2" location="crates/mcb-server/tests/utils/test_fixtures.rs:223">
P1: Unexpected AppContext initialization regressions are now converted into a successful skip in the real-provider tests. The `result` can contain config, SQLite, DI, fallback-provider, and other failures, but this branch collapses all of them to `None`, which `real_providers.rs` treats as “provider unavailable.” Since the known missing-model case is already handled by the deterministic fallback above, unexpected errors here should remain test failures rather than being silently cached in the `OnceLock`.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.
Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread Cargo.toml
"default",
"hf-hub-native-tls",
"image-models",
"ort-load-dynamic",

@cubic-dev-ai cubic-dev-ai Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P0: FastEmbed initialization now panics on clean CI hosts and standalone release installs because ort-load-dynamic requires an external ONNX Runtime shared library that is neither installed nor packaged. Keeping the prior download-binaries backend, or adding explicit cross-platform dylib installation/packaging and ORT_DYLIB_PATH, preserves the default local embedding provider.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Cargo.toml, line 253:

<comment>FastEmbed initialization now panics on clean CI hosts and standalone release installs because `ort-load-dynamic` requires an external ONNX Runtime shared library that is neither installed nor packaged. Keeping the prior download-binaries backend, or adding explicit cross-platform dylib installation/packaging and `ORT_DYLIB_PATH`, preserves the default local embedding provider.</comment>

<file context>
@@ -248,7 +248,9 @@ async-nats = "0.46"
-    "default",
+    "hf-hub-native-tls",
+    "image-models",
+    "ort-load-dynamic",
 ] }
 
</file context>
Suggested change
"ort-load-dynamic",
"ort-download-binaries-native-tls",
Fix with cubic

provider: "fastembed".to_owned(),
model: "test".to_owned(),
api_key: None,
provider: "openai".to_owned(),

@cubic-dev-ai cubic-dev-ai Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: This test still resolves FastEmbed, so the new "openai" assertion fails whenever initialization succeeds (and offline initialization may fail before the assertion). test_config() retains the direct providers.embedding.provider = "fastembed" value from config/default.toml, and the resolver gives that field precedence over configs["default"]. The test setup should also set the direct provider and API key to OpenAI, as the catalog tests now do, or clear the direct provider so the named config is exercised.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/mcb-infrastructure/tests/integration/di/dispatch_tests.rs, line 68:

<comment>This test still resolves FastEmbed, so the new `"openai"` assertion fails whenever initialization succeeds (and offline initialization may fail before the assertion). `test_config()` retains the direct `providers.embedding.provider = "fastembed"` value from `config/default.toml`, and the resolver gives that field precedence over `configs["default"]`. The test setup should also set the direct provider and API key to OpenAI, as the catalog tests now do, or clear the direct provider so the named config is exercised.</comment>

<file context>
@@ -65,9 +65,9 @@ async fn test_provider_selection_from_config() -> Result<(), Box<dyn std::error:
-            provider: "fastembed".to_owned(),
-            model: "test".to_owned(),
-            api_key: None,
+            provider: "openai".to_owned(),
+            model: "text-embedding-3-small".to_owned(),
+            api_key: Some("test-key".to_owned()),
</file context>
Fix with cubic

std::thread::spawn(|| -> Option<AppContext> {
let rt = match tokio::runtime::Runtime::new() {
Ok(rt) => rt,
Err(err) => {

@cubic-dev-ai cubic-dev-ai Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Unexpected AppContext initialization regressions are now converted into a successful skip in the real-provider tests. The result can contain config, SQLite, DI, fallback-provider, and other failures, but this branch collapses all of them to None, which real_providers.rs treats as “provider unavailable.” Since the known missing-model case is already handled by the deterministic fallback above, unexpected errors here should remain test failures rather than being silently cached in the OnceLock.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/mcb-server/tests/utils/test_fixtures.rs, line 223:

<comment>Unexpected AppContext initialization regressions are now converted into a successful skip in the real-provider tests. The `result` can contain config, SQLite, DI, fallback-provider, and other failures, but this branch collapses all of them to `None`, which `real_providers.rs` treats as “provider unavailable.” Since the known missing-model case is already handled by the deterministic fallback above, unexpected errors here should remain test failures rather than being silently cached in the `OnceLock`.</comment>

<file context>
@@ -150,10 +157,152 @@ pub fn create_test_indexing_result(
+        std::thread::spawn(|| -> Option<AppContext> {
+            let rt = match tokio::runtime::Runtime::new() {
+                Ok(rt) => rt,
+                Err(err) => {
+                    tracing::warn!("failed to create runtime for shared app context: {err}");
+                    return None;
</file context>
Fix with cubic

async fn test_has_changed(file_hash_repo: Arc<dyn FileHashRepository>) {
let repo = file_hash_repo;
async fn test_has_changed(file_hash_repo: Option<Arc<dyn FileHashRepository>>) {
let Some(repo) = file_hash_repo else {

@cubic-dev-ai cubic-dev-ai Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Offline CI now silently skips the file-hash repository tests even though these cases do not need embeddings. Their fixture couples FileHashRepository to an AppContext whose creation can return None solely because the ONNX model is unavailable, and each test then returns as a passing test. A SQLite-backed file-hash fixture initialized independently of FastEmbed would retain this coverage in the offline suite; only the final full indexing test needs the complete context.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/mcb-infrastructure/tests/unit/util_tests/file_hash_tests.rs, line 26:

<comment>Offline CI now silently skips the file-hash repository tests even though these cases do not need embeddings. Their fixture couples `FileHashRepository` to an AppContext whose creation can return `None` solely because the ONNX model is unavailable, and each test then returns as a passing test. A SQLite-backed file-hash fixture initialized independently of FastEmbed would retain this coverage in the offline suite; only the final full indexing test needs the complete context.</comment>

<file context>
@@ -9,21 +9,24 @@ use std::time::Duration;
-async fn test_has_changed(file_hash_repo: Arc<dyn FileHashRepository>) {
-    let repo = file_hash_repo;
+async fn test_has_changed(file_hash_repo: Option<Arc<dyn FileHashRepository>>) {
+    let Some(repo) = file_hash_repo else {
+        eprintln!("skipping: shared AppContext unavailable (FastEmbed model missing)");
+        return;
</file context>
Fix with cubic

}

fn provider_name(&self) -> &str {
"fastembed"

@cubic-dev-ai cubic-dev-ai Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The fallback identifies itself as FastEmbed, so create_real_embedding_provider and the real-provider tests cannot distinguish the length-based stub from the actual ONNX provider. In an offline run, tests named and documented as exercising real FastEmbed therefore report success without loading or invoking FastEmbed. Giving the fallback its own provider name (and having real-provider fixtures reject/skip that name) would keep generic server tests offline-capable without producing a false real-provider signal.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/mcb-server/tests/utils/test_fixtures.rs, line 193:

<comment>The fallback identifies itself as FastEmbed, so `create_real_embedding_provider` and the real-provider tests cannot distinguish the length-based stub from the actual ONNX provider. In an offline run, tests named and documented as exercising real FastEmbed therefore report success without loading or invoking FastEmbed. Giving the fallback its own provider name (and having real-provider fixtures reject/skip that name) would keep generic server tests offline-capable without producing a false real-provider signal.</comment>

<file context>
@@ -150,10 +157,152 @@ pub fn create_test_indexing_result(
+    }
+
+    fn provider_name(&self) -> &str {
+        "fastembed"
+    }
+}
</file context>
Fix with cubic

Comment thread config/smoke-test.toml
port = 18080

[providers.embedding]
provider = "openai"

@cubic-dev-ai cubic-dev-ai Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The configured text-embedding-3-small value is ignored because setting the direct providers.embedding.provider makes the resolver bypass configs.default. Keeping model in the direct section would make this smoke configuration effective rather than relying on OpenAI's coincidentally matching factory default.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At config/smoke-test.toml, line 15:

<comment>The configured `text-embedding-3-small` value is ignored because setting the direct `providers.embedding.provider` makes the resolver bypass `configs.default`. Keeping `model` in the direct section would make this smoke configuration effective rather than relying on OpenAI's coincidentally matching factory default.</comment>

<file context>
@@ -11,9 +11,12 @@ transport_mode = "stdio"
 port = 18080
 
+[providers.embedding]
+provider = "openai"
+
 [providers.embedding.configs.default]
</file context>
Suggested change
provider = "openai"
provider = "openai"
model = "text-embedding-3-small"
Fix with cubic

async fn test_catalog_builds_with_default_config() {
let config = ConfigLoader::new().load().expect("load config");
let mut config = ConfigLoader::new().load().expect("load config");
configure_offline_embedding(&mut config);

@cubic-dev-ai cubic-dev-ai Bot Jul 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: test_catalog_builds_with_custom_embedding_config is now behaviorally identical to test_catalog_builds_with_default_config, so the custom-config coverage has been lost while the suite still appears to test it. Consider giving this case a distinct override (and asserting the selected provider/config), or removing/renaming the duplicate test.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/mcb-infrastructure/tests/integration/di/catalog_tests.rs, line 29:

<comment>`test_catalog_builds_with_custom_embedding_config` is now behaviorally identical to `test_catalog_builds_with_default_config`, so the custom-config coverage has been lost while the suite still appears to test it. Consider giving this case a distinct override (and asserting the selected provider/config), or removing/renaming the duplicate test.</comment>

<file context>
@@ -11,11 +11,22 @@ use serial_test::serial;
 async fn test_catalog_builds_with_default_config() {
-    let config = ConfigLoader::new().load().expect("load config");
+    let mut config = ConfigLoader::new().load().expect("load config");
+    configure_offline_embedding(&mut config);
     let result = build_catalog(config).await;
 
</file context>
Fix with cubic

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.

2 participants