Skip to content

Move simulator from examples/ to domains/ - #568

Draft
erensh27 wants to merge 1 commit into
rapidsai:mainfrom
erensh27:fix/move-simulator-to-domains
Draft

Move simulator from examples/ to domains/#568
erensh27 wants to merge 1 commit into
rapidsai:mainfrom
erensh27:fix/move-simulator-to-domains

Conversation

@erensh27

Copy link
Copy Markdown

Fixes #102

The simulator is a query engine simulator rather than an example, so it now lives under domains/simulator/ alongside domains/query_engine/. Updated workspace members and default members in the root Cargo.toml, Cargo path dependencies (crates/codegen, domains/query_engine/server, domains/query_engine/tests/fixed), README/docs references, pre-commit exclude patterns, and CI base-branch paths in .github/workflows/ui.yml.

The simulator is a query engine simulator, not an example, so it belongs
under domains/ next to query_engine. Updated workspace members, Cargo
path dependencies, docs, pre-commit exclusions, and CI base-branch
paths.

Fixes rapidsai#102
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: dc4edfb3-1980-4e49-b572-9d3c258e58f3

📥 Commits

Reviewing files that changed from the base of the PR and between c0e7b60 and f2bf1dc.

📒 Files selected for processing (29)
  • .github/workflows/ui.yml
  • .pre-commit-config.ci.yaml
  • .pre-commit-config.yaml
  • Cargo.toml
  • README.md
  • crates/codegen/Cargo.toml
  • docs/domains/query_engine/examples/README.md
  • docs/domains/query_engine/examples/simulator.md
  • domains/query_engine/server/Cargo.toml
  • domains/query_engine/tests/fixed/Cargo.toml
  • domains/query_engine/tests/fixed/src/lib.rs
  • domains/simulator/analyzer/Cargo.toml
  • domains/simulator/analyzer/src/lib.rs
  • domains/simulator/analyzer/src/model.rs
  • domains/simulator/analyzer/src/task.rs
  • domains/simulator/analyzer/src/view.rs
  • domains/simulator/application/Cargo.toml
  • domains/simulator/application/src/main.rs
  • domains/simulator/instrumentation/Cargo.toml
  • domains/simulator/instrumentation/src/lib.rs
  • domains/simulator/instrumentation/src/task.rs
  • domains/simulator/server/Cargo.toml
  • domains/simulator/server/src/main.rs
  • domains/simulator/ui-bindings/Cargo.toml
  • domains/simulator/ui-bindings/src/lib.rs
  • domains/simulator/ui-bindings/src/main.rs
  • domains/simulator/ui/Cargo.toml
  • domains/simulator/ui/src/lib.rs
  • ui/REVIEW.md

📝 Walkthrough

Walkthrough

The simulator moves from examples/simulator to domains/simulator. The change adds simulator instrumentation, execution, analysis, server, and UI binding packages. Workspace, dependency, documentation, workflow, hook, and binding paths now use the new location.

Changes

Simulator domain

Layer / File(s) Summary
Workspace path relocation
.github/workflows/ui.yml, .pre-commit-config*.yaml, Cargo.toml, README.md, crates/codegen/Cargo.toml, docs/domains/query_engine/examples/*, domains/query_engine/server/Cargo.toml, domains/query_engine/tests/fixed/*, ui/REVIEW.md
Workspace members, dependencies, documentation, workflows, hooks, and generated-binding paths now reference domains/simulator.
Simulator instrumentation and runtime
domains/simulator/instrumentation/*, domains/simulator/application/*
The simulator defines task states and resource entities, builds logical and physical plans, simulates worker activity, and emits telemetry.
Simulator UI contract and bindings
domains/simulator/ui/*, domains/simulator/ui-bindings/*
The UI packages define simulator entity references and generate TypeScript bindings for query, timeline, data-flow, and entity-list types.
Simulator model and analyzer
domains/simulator/analyzer/*
The analyzer builds models from simulator events and exposes query-scoped entities, task FSMs, resource timelines, and data-flow timelines.
Collector and analyzer server
domains/simulator/server/*
The server collects and exports simulator events, reconstructs event streams, and runs collector and analyzer services concurrently.

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested reviewers: johanpel, 9prady9

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes moving the simulator from examples/ to domains/.
Description check ✅ Passed The description explains the move, states why it is needed, links issue #102, and identifies the affected configuration and documentation.
Linked Issues check ✅ Passed The changes implement the relocation objective and update workspace, dependency, documentation, CI, and pre-commit paths required by [#102].
Out of Scope Changes check ✅ Passed The simulator files and path updates are directly related to the relocation objective in [#102].
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 12

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
domains/simulator/server/src/main.rs-64-68 (1)

64-68: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the environment variable name in the help text.

Line 66 states QUENT_CORS_ADDRESS. Line 34 defines the actual variable as QUENT_ANALYZER_CORS_ADDRESS, and line 67 binds that name. Users read line 66 in --help output and set a variable that has no effect.

🐛 Proposed fix
     /// Address to allow CORS requests from (e.g. "http://localhost:5173").
     /// If not set, CORS is disabled.
-    /// Overridden by the QUENT_CORS_ADDRESS environment variable if set.
+    /// Overridden by the QUENT_ANALYZER_CORS_ADDRESS environment variable if set.
     #[arg(long, env = env::QUENT_ANALYZER_CORS_ADDRESS)]
     cors_address: Option<String>,
🤖 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 `@domains/simulator/server/src/main.rs` around lines 64 - 68, Update the CORS
configuration documentation above the cors_address argument to reference
QUENT_ANALYZER_CORS_ADDRESS consistently with the env binding and its
definition, so the --help text names the effective environment variable.
🧹 Nitpick comments (6)
domains/simulator/instrumentation/Cargo.toml (1)

11-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify the sibling-domain path dependency.

Line 12 travels to the repository root and back into domains/. The equivalent direct path is ../../query_engine/model. This matches how line 12 in domains/simulator/analyzer/Cargo.toml and the ../instrumentation entries express sibling paths.

♻️ Proposed path simplification
-quent-query-engine-model = { path = "../../../domains/query_engine/model" }
+quent-query-engine-model = { path = "../../query_engine/model" }
🤖 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 `@domains/simulator/instrumentation/Cargo.toml` around lines 11 - 13, Update
the quent-query-engine-model dependency in the instrumentation Cargo.toml
manifest to use the direct sibling-domain path ../../query_engine/model instead
of traversing through the repository root; leave the other dependency paths
unchanged.
domains/simulator/analyzer/Cargo.toml (1)

11-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify the sibling-domain path dependencies.

Lines 11-13 travel to the repository root and back into domains/. The direct sibling paths are ../../query_engine/analyzer, ../../query_engine/model, and ../../query_engine/ui. The same file already uses direct relative paths for ../instrumentation and ../ui.

🤖 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 `@domains/simulator/analyzer/Cargo.toml` around lines 11 - 13, Update the path
dependencies for quent-query-engine-analyzer, quent-query-engine-model, and
quent-query-engine-ui to use the direct sibling paths
../../query_engine/analyzer, ../../query_engine/model, and
../../query_engine/ui, matching the existing relative-path style in Cargo.toml.
domains/simulator/application/Cargo.toml (1)

7-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

External crate versions are pinned per manifest instead of in [workspace.dependencies]. Both new manifests declare literal versions for external crates while declaring petgraph, tokio, tracing, and uuid with workspace = true. The result is two different clap constraints inside one workspace, and version bumps must touch each manifest separately.

  • domains/simulator/application/Cargo.toml#L7-L16: replace clap = {version = "4.5.57", ...} and rand = "0.10.2" with workspace = true entries, and add both crates to [workspace.dependencies] in the root Cargo.toml.
  • domains/simulator/server/Cargo.toml#L11-L12: replace axum = { version = "0.8.7" } and clap = { version = "4.5", ... } with workspace = true entries that reuse the same root declarations.
🤖 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 `@domains/simulator/application/Cargo.toml` around lines 7 - 16, Centralize the
external dependency versions in the root workspace: add clap and rand to
[workspace.dependencies], then update domains/simulator/application/Cargo.toml
lines 7-16 to use workspace = true for both; also update
domains/simulator/server/Cargo.toml lines 11-12 so axum and clap use the shared
workspace declarations.
domains/simulator/application/src/main.rs (1)

748-986: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the per-operator statistics generation.

execute_logical_plan now spans lines 647-986. Roughly 240 of those lines are the match op.kind block that builds random statistics. This block has one purpose and no dependency on worker state.

Move lines 749-965 into a free function, for example fn operator_statistics(kind: Physical, tasks_processed: u64) -> Vec<DynamicAttribute>. execute_logical_plan then reads as plan declaration, execution, and statistics emission.

🤖 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 `@domains/simulator/application/src/main.rs` around lines 748 - 986, Extract
the random per-operator attribute construction, including the attr macro and
match on Physical, from execute_logical_plan into a free function such as
operator_statistics(kind: Physical, tasks_processed: u64) ->
Vec<DynamicAttribute>. Keep all existing statistic generation behavior
unchanged, then call this function when populating operator::Statistics so
execute_logical_plan only handles plan execution and emission.
domains/simulator/analyzer/src/model.rs (1)

471-501: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mutate the model instead of rebuilding it field by field.

Lines 473-501 build temp_model, then destructure every field into a second SimulatorModel only to attach resource_group_types. A new field on SimulatorModel must be added in both places.

♻️ Proposed simplification
-        let temp_model = SimulatorModel {
+        let mut model = SimulatorModel {
             query_engine,
             arbitrary_resources: resources,
             tasks,
             resource_group_types: HashMap::default(),
         };
-        let mut resource_group_types = derive_resource_group_types(&temp_model)?;
+        let mut resource_group_types = derive_resource_group_types(&model)?;
         // Bubble up all the used_by_entity fields in the group type decls.
         for group_type_decl in resource_group_types.values_mut() {
             for contained_resource_type in &group_type_decl.contains_resource_types {
-                if let Ok(resource_type) = temp_model
+                if let Ok(resource_type) = model
                     .arbitrary_resources
                     .resource_type(contained_resource_type)
                 {
@@
-        Ok(SimulatorModel {
-            query_engine: temp_model.query_engine,
-            arbitrary_resources: temp_model.arbitrary_resources,
-            tasks: temp_model.tasks,
-            resource_group_types,
-        })
+        model.resource_group_types = resource_group_types;
+        Ok(model)
🤖 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 `@domains/simulator/analyzer/src/model.rs` around lines 471 - 501, Mutate the
existing temp_model instead of constructing a second SimulatorModel: make
temp_model mutable, assign the derived and updated resource_group_types to its
field after the bubbling loop, then return temp_model directly. Update the
construction flow around SimulatorModel and derive_resource_group_types while
preserving all existing field values.
domains/simulator/analyzer/src/lib.rs (1)

657-684: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the redundant borrow and second index.

Line 663 binds entry with &mut but only reads entry.operator_ids. Line 665 then indexes plain_builders again. The same pattern repeats on lines 675-679, 811-813, and 822-826.

Read the filter once, then index once.

♻️ Proposed simplification
                 if let Some(builder_indices) = plain_index.get(&resource_id) {
                     for &builder_idx in builder_indices {
-                        let entry = &mut plain_builders[builder_idx];
-                        if operator_matches(&entry.operator_ids, task_operator_id) {
-                            plain_builders[builder_idx].builder.try_push(&usage)?;
+                        let entry = &mut plain_builders[builder_idx];
+                        if operator_matches(&entry.operator_ids, task_operator_id) {
+                            entry.builder.try_push(&usage)?;
                         }
                     }
                 }

If the borrow checker rejects the combined borrow, split the filter check first:

let matches = operator_matches(&plain_builders[builder_idx].operator_ids, task_operator_id);
if matches {
    plain_builders[builder_idx].builder.try_push(&usage)?;
}
🤖 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 `@domains/simulator/analyzer/src/lib.rs` around lines 657 - 684, In the task
usage processing loops, remove the mutable entry borrow and avoid indexing each
builder twice: read the operator IDs from the indexed builder, store the match
result, then perform a single mutable builder access for try_push. Apply this
pattern to both plain and per-state builders here and to the corresponding
patterns around the other reported locations.
🤖 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 @.github/workflows/ui.yml:
- Line 177: Update the fallback binding path assigned to base_bindings in the
workflow’s pre-relocation branch to use
base/examples/simulator/server/ts-bindings, while preserving the ui-bindings
path when it exists.

In `@crates/codegen/Cargo.toml`:
- Line 18: Add quent-simulator-instrumentation to the root workspace
dependencies table, then update its dev-dependency declaration in the crate
manifest to use the workspace dependency instead of the local path.

In `@domains/simulator/analyzer/src/lib.rs`:
- Around line 1069-1094: Refactor SimulatorUiAnalyzer::entities_filtered to
validate entity_filter.entity_type_name first, returning the existing
InvalidArgument error for unknown types, then construct a single
tasks.values().filter closure using operator_matches and the time-window span
check. Preserve the current behavior for the recognized "task" type and for
filters without an entity type.
- Around line 1-140: Add accompanying tests across the simulator crates: in
domains/simulator/analyzer/src/lib.rs:1-140, table-test
operator_statistic_quantity, scale_operator_statistic, and
scaled_operator_statistic_name; in
domains/simulator/instrumentation/src/task.rs:73-96, exercise the Task FSM’s
emitted sequence including multi-worker sending and exit; in
domains/simulator/analyzer/src/model.rs:437-502, test
SimulatorModelBuilder::try_push and try_build with valid events and a missing
resource initialization that returns an error; in
domains/simulator/analyzer/src/task.rs:35-96, test active_span with one, two,
and many transitions plus try_to_ui_fsm bytes_per_sec derivation including equal
timestamps; and in domains/simulator/server/src/main.rs:92-99, verify each
exporter name maps to its expected Format and unknown names error.

In `@domains/simulator/analyzer/src/model.rs`:
- Around line 258-265: Replace panic-based invariant handling with
AnalyzerResult propagation at all three sites: in
domains/simulator/analyzer/src/model.rs lines 258-265, update the
TaskBuilder::try_new entry logic to use an Entry match and propagate errors with
?; in domains/simulator/analyzer/src/model.rs lines 447-460, replace
get_mut(&resource_type_name).unwrap() with InvalidTypeName error propagation;
and in domains/simulator/analyzer/src/lib.rs lines 842-865, replace both
panic-producing unwrap_or_else calls with AnalyzerError::BrokenImpl("chunked
bulk: unknown entry id") propagated via ?.

In `@domains/simulator/application/src/main.rs`:
- Around line 701-713: Validate Args::num_threads during clap parsing so only
values of at least one are accepted, preventing an empty self.threads vector. In
the physical_plan.execute task scheduling block, replace the truncated
tasks_per_thread_per_op division with balanced range calculation that assigns
every task, including the remainder, across threads.

In `@domains/simulator/instrumentation/src/task.rs`:
- Around line 84-94: Update the task FSM transitions around JoinPartition’s
producer sequence: include sending in exit_from and add a sending => sending
self-transition so repeated sending events for other workers are accepted before
exit. Preserve the existing sending => queueing transition for the normal
completion path.

In `@domains/simulator/server/src/main.rs`:
- Around line 122-129: Update the importer closure and the
`ImporterFn`/`UiAnalyzer` interfaces so event iterators yield
`ImporterResult<Event<_>>` and propagate errors lazily. Remove the eager
`collect::<Vec<_>>()` buffering in the `Simulator::import_events` path,
preserving errors through the returned iterator without discarding them or
panicking.

In `@domains/simulator/ui-bindings/src/lib.rs`:
- Around line 19-42: Add a Rust test for generate that creates a temporary
output directory containing stale content, invokes generate, verifies generation
succeeds and the stale content is removed, and confirms expected binding files
are emitted in the requested directory. Place the test alongside generate and
use the project’s existing temporary-directory and test conventions.

In `@domains/simulator/ui/Cargo.toml`:
- Around line 1-11: Add the required SPDX copyright and Apache-2.0 license
headers before [package] in domains/simulator/ui/Cargo.toml (lines 1-11) and
domains/simulator/ui-bindings/Cargo.toml (lines 1-11). In both manifests, also
set the new crates to edition 2024 and publish = false as required by the path
instructions.
- Around line 8-11: Move the local quent-analyzer dependency from the
manifest-level path declaration into [workspace.dependencies], then reference it
with workspace = true in domains/simulator/ui/Cargo.toml:8-11. Apply the same
workspace-based declaration to all three local crates in
domains/simulator/ui-bindings/Cargo.toml:8-11, ensuring neither manifest uses
direct path or git dependency declarations.

In `@domains/simulator/ui/src/lib.rs`:
- Around line 26-32: Correct EntityRef::is_resource and
EntityRef::is_resource_group so each returns true only when self matches its
corresponding variant, Resource and ResourceGroup respectively; preserve false
for all other variants. Add unit tests covering matching and non-matching
EntityRef variants for both methods.

---

Other comments:
In `@domains/simulator/server/src/main.rs`:
- Around line 64-68: Update the CORS configuration documentation above the
cors_address argument to reference QUENT_ANALYZER_CORS_ADDRESS consistently with
the env binding and its definition, so the --help text names the effective
environment variable.

---

Nitpick comments:
In `@domains/simulator/analyzer/Cargo.toml`:
- Around line 11-13: Update the path dependencies for
quent-query-engine-analyzer, quent-query-engine-model, and quent-query-engine-ui
to use the direct sibling paths ../../query_engine/analyzer,
../../query_engine/model, and ../../query_engine/ui, matching the existing
relative-path style in Cargo.toml.

In `@domains/simulator/analyzer/src/lib.rs`:
- Around line 657-684: In the task usage processing loops, remove the mutable
entry borrow and avoid indexing each builder twice: read the operator IDs from
the indexed builder, store the match result, then perform a single mutable
builder access for try_push. Apply this pattern to both plain and per-state
builders here and to the corresponding patterns around the other reported
locations.

In `@domains/simulator/analyzer/src/model.rs`:
- Around line 471-501: Mutate the existing temp_model instead of constructing a
second SimulatorModel: make temp_model mutable, assign the derived and updated
resource_group_types to its field after the bubbling loop, then return
temp_model directly. Update the construction flow around SimulatorModel and
derive_resource_group_types while preserving all existing field values.

In `@domains/simulator/application/Cargo.toml`:
- Around line 7-16: Centralize the external dependency versions in the root
workspace: add clap and rand to [workspace.dependencies], then update
domains/simulator/application/Cargo.toml lines 7-16 to use workspace = true for
both; also update domains/simulator/server/Cargo.toml lines 11-12 so axum and
clap use the shared workspace declarations.

In `@domains/simulator/application/src/main.rs`:
- Around line 748-986: Extract the random per-operator attribute construction,
including the attr macro and match on Physical, from execute_logical_plan into a
free function such as operator_statistics(kind: Physical, tasks_processed: u64)
-> Vec<DynamicAttribute>. Keep all existing statistic generation behavior
unchanged, then call this function when populating operator::Statistics so
execute_logical_plan only handles plan execution and emission.

In `@domains/simulator/instrumentation/Cargo.toml`:
- Around line 11-13: Update the quent-query-engine-model dependency in the
instrumentation Cargo.toml manifest to use the direct sibling-domain path
../../query_engine/model instead of traversing through the repository root;
leave the other dependency paths unchanged.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: dc4edfb3-1980-4e49-b572-9d3c258e58f3

📥 Commits

Reviewing files that changed from the base of the PR and between c0e7b60 and f2bf1dc.

📒 Files selected for processing (29)
  • .github/workflows/ui.yml
  • .pre-commit-config.ci.yaml
  • .pre-commit-config.yaml
  • Cargo.toml
  • README.md
  • crates/codegen/Cargo.toml
  • docs/domains/query_engine/examples/README.md
  • docs/domains/query_engine/examples/simulator.md
  • domains/query_engine/server/Cargo.toml
  • domains/query_engine/tests/fixed/Cargo.toml
  • domains/query_engine/tests/fixed/src/lib.rs
  • domains/simulator/analyzer/Cargo.toml
  • domains/simulator/analyzer/src/lib.rs
  • domains/simulator/analyzer/src/model.rs
  • domains/simulator/analyzer/src/task.rs
  • domains/simulator/analyzer/src/view.rs
  • domains/simulator/application/Cargo.toml
  • domains/simulator/application/src/main.rs
  • domains/simulator/instrumentation/Cargo.toml
  • domains/simulator/instrumentation/src/lib.rs
  • domains/simulator/instrumentation/src/task.rs
  • domains/simulator/server/Cargo.toml
  • domains/simulator/server/src/main.rs
  • domains/simulator/ui-bindings/Cargo.toml
  • domains/simulator/ui-bindings/src/lib.rs
  • domains/simulator/ui-bindings/src/main.rs
  • domains/simulator/ui/Cargo.toml
  • domains/simulator/ui/src/lib.rs
  • ui/REVIEW.md

Comment thread .github/workflows/ui.yml
base_bindings=base/ui/generated/ts-bindings
else
base_bindings=base/examples/simulator/server/ts-bindings
base_bindings=base/domains/simulator/server/ts-bindings

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the correct bindings path for the pre-relocation base revision.

When base/domains/simulator/ui-bindings does not exist, the workflow builds the base simulator server. On the base revision before this move, generated bindings are under base/examples/simulator/server/ts-bindings. Line 177 points to the new path, so diff cannot find the directory and the binding-change check fails.

Select the fallback from the base layout, or use the old path in this branch.

Proposed fix
           if [ -d base/ui/generated/ts-bindings ]; then
             base_bindings=base/ui/generated/ts-bindings
+          elif [ -d base/domains/simulator/server/ts-bindings ]; then
+            base_bindings=base/domains/simulator/server/ts-bindings
           else
-            base_bindings=base/domains/simulator/server/ts-bindings
+            base_bindings=base/examples/simulator/server/ts-bindings
           fi
🤖 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 @.github/workflows/ui.yml at line 177, Update the fallback binding path
assigned to base_bindings in the workflow’s pre-relocation branch to use
base/examples/simulator/server/ts-bindings, while preserving the ui-bindings
path when it exists.

Comment thread crates/codegen/Cargo.toml
quent-query-engine-model = { path = "../../domains/query_engine/model" }
quent-readme-example = { path = "../../examples/readme" }
quent-simulator-instrumentation = { path = "../../examples/simulator/instrumentation" }
quent-simulator-instrumentation = { path = "../../domains/simulator/instrumentation" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- root workspace dependency entry ---'
rg -n -C 3 '^quent-simulator-instrumentation\s*=' Cargo.toml || true

printf '%s\n' '--- target manifest ---'
cat -n crates/codegen/Cargo.toml

printf '%s\n' '--- all references ---'
rg -n 'quent-simulator-instrumentation|workspace\s*=\s*true|path\s*=' \
  Cargo.toml crates --glob 'Cargo.toml' --glob '!target/**' || true

printf '%s\n' '--- manifest paths and workspace membership ---'
find crates domains -name Cargo.toml -print 2>/dev/null | sort | while read -r manifest; do
  if rg -q '^name\s*=\s*"quent-simulator-instrumentation"' "$manifest"; then
    printf 'crate manifest: %s\n' "$manifest"
    cat -n "$manifest"
  fi
done

Repository: rapidsai/quent

Length of output: 22650


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- workspace and dependency tables ---'
sed -n '1,175p' Cargo.toml

printf '%s\n' '--- simulator workspace context ---'
find domains/simulator -maxdepth 3 -name Cargo.toml -print -exec sed -n '1,80p' {} \;

printf '%s\n' '--- TOML structure check ---'
python3 - <<'PY'
import tomllib
from pathlib import Path

root = tomllib.loads(Path("Cargo.toml").read_text())
target = tomllib.loads(Path("crates/codegen/Cargo.toml").read_text())
simulator = tomllib.loads(Path("domains/simulator/instrumentation/Cargo.toml").read_text())

workspace = root.get("workspace", {})
dependencies = workspace.get("dependencies", {})
members = workspace.get("members", [])

print("root workspace.dependencies contains target:",
      "quent-simulator-instrumentation" in dependencies)
print("root workspace dependency value:",
      dependencies.get("quent-simulator-instrumentation"))
print("target dev-dependency value:",
      target.get("dev-dependencies", {}).get("quent-simulator-instrumentation"))
print("workspace member patterns containing domains:",
      [member for member in members if "domain" in member or "simulator" in member])
print("simulator package name:", simulator["package"]["name"])
PY

Repository: rapidsai/quent

Length of output: 9051


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import re
from pathlib import Path

root_lines = Path("Cargo.toml").read_text().splitlines()
target_lines = Path("crates/codegen/Cargo.toml").read_text().splitlines()
simulator_manifest = Path("domains/simulator/instrumentation/Cargo.toml")

def table_ranges(lines):
    ranges = {}
    current = None
    for index, line in enumerate(lines):
        match = re.match(r"^\s*\[([^\]]+)\]\s*$", line)
        if match:
            current = match.group(1)
            ranges.setdefault(current, []).append(index)
    return ranges

root_tables = table_ranges(root_lines)
target_tables = table_ranges(target_lines)

def section(lines, table):
    starts = [i for i, line in enumerate(lines)
              if line.strip() == f"[{table}]"]
    if not starts:
        return []
    start = starts[0] + 1
    end = len(lines)
    for i in range(start, len(lines)):
        if re.match(r"^\s*\[[^\]]+\]\s*$", lines[i]):
            end = i
            break
    return lines[start:end]

workspace_deps = section(root_lines, "workspace.dependencies")
target_dev_deps = section(target_lines, "dev-dependencies")

root_entry = next(
    (line.strip() for line in workspace_deps
     if re.match(r"^quent-simulator-instrumentation\s*=", line)),
    None,
)
target_entry = next(
    (line.strip() for line in target_dev_deps
     if re.match(r"^quent-simulator-instrumentation\s*=", line)),
    None,
)

print("root workspace dependency:", root_entry)
print("codegen dev-dependency:", target_entry)
print("simulator manifest exists:", simulator_manifest.is_file())
print("simulator package declaration:",
      next((line.strip() for line in simulator_manifest.read_text().splitlines()
            if re.match(r'^name\s*=\s*"quent-simulator-instrumentation"', line)),
           None))
print("codegen entry uses workspace=true:",
      bool(target_entry and re.search(r"\bworkspace\s*=\s*true\b", target_entry)))
print("codegen entry uses direct path:",
      bool(target_entry and re.search(r"\bpath\s*=", target_entry)))
PY

Repository: rapidsai/quent

Length of output: 477


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import re
from pathlib import Path

root_lines = Path("Cargo.toml").read_text().splitlines()
target_lines = Path("crates/codegen/Cargo.toml").read_text().splitlines()
simulator_manifest = Path("domains/simulator/instrumentation/Cargo.toml")

def section(lines, table):
    marker = f"[{table}]"
    try:
        start = next(i for i, line in enumerate(lines) if line.strip() == marker) + 1
    except StopIteration:
        return []
    end = len(lines)
    for i in range(start, len(lines)):
        if re.match(r"^\s*\[[^\]]+\]\s*$", lines[i]):
            end = i
            break
    return lines[start:end]

workspace_deps = section(root_lines, "workspace.dependencies")
target_dev_deps = section(target_lines, "dev-dependencies")

root_entry = next(
    (line.strip() for line in workspace_deps
     if re.match(r"^quent-simulator-instrumentation\s*=", line)),
    None,
)
target_entry = next(
    (line.strip() for line in target_dev_deps
     if re.match(r"^quent-simulator-instrumentation\s*=", line)),
    None,
)

print("root workspace dependency:", root_entry)
print("codegen dev-dependency:", target_entry)
print("simulator manifest exists:", simulator_manifest.is_file())
print("codegen entry uses workspace=true:",
      bool(target_entry and re.search(r"\bworkspace\s*=\s*true\b", target_entry)))
print("codegen entry uses direct path:",
      bool(target_entry and re.search(r"\bpath\s*=", target_entry)))
PY

Repository: rapidsai/quent

Length of output: 405


Use the workspace dependency for quent-simulator-instrumentation.

Add the relocated crate to the root [workspace.dependencies] table, then change this dev-dependency to { workspace = true }.

🤖 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 `@crates/codegen/Cargo.toml` at line 18, Add quent-simulator-instrumentation to
the root workspace dependencies table, then update its dev-dependency
declaration in the crate manifest to use the workspace dependency instead of the
local path.

Source: Path instructions

@coderabbitai coderabbitai 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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 12

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
domains/simulator/server/src/main.rs-64-68 (1)

64-68: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the environment variable name in the help text.

Line 66 states QUENT_CORS_ADDRESS. Line 34 defines the actual variable as QUENT_ANALYZER_CORS_ADDRESS, and line 67 binds that name. Users read line 66 in --help output and set a variable that has no effect.

🐛 Proposed fix
     /// Address to allow CORS requests from (e.g. "http://localhost:5173").
     /// If not set, CORS is disabled.
-    /// Overridden by the QUENT_CORS_ADDRESS environment variable if set.
+    /// Overridden by the QUENT_ANALYZER_CORS_ADDRESS environment variable if set.
     #[arg(long, env = env::QUENT_ANALYZER_CORS_ADDRESS)]
     cors_address: Option<String>,
🤖 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 `@domains/simulator/server/src/main.rs` around lines 64 - 68, Update the CORS
configuration documentation above the cors_address argument to reference
QUENT_ANALYZER_CORS_ADDRESS consistently with the env binding and its
definition, so the --help text names the effective environment variable.
🧹 Nitpick comments (6)
domains/simulator/instrumentation/Cargo.toml (1)

11-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify the sibling-domain path dependency.

Line 12 travels to the repository root and back into domains/. The equivalent direct path is ../../query_engine/model. This matches how line 12 in domains/simulator/analyzer/Cargo.toml and the ../instrumentation entries express sibling paths.

♻️ Proposed path simplification
-quent-query-engine-model = { path = "../../../domains/query_engine/model" }
+quent-query-engine-model = { path = "../../query_engine/model" }
🤖 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 `@domains/simulator/instrumentation/Cargo.toml` around lines 11 - 13, Update
the quent-query-engine-model dependency in the instrumentation Cargo.toml
manifest to use the direct sibling-domain path ../../query_engine/model instead
of traversing through the repository root; leave the other dependency paths
unchanged.
domains/simulator/analyzer/Cargo.toml (1)

11-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify the sibling-domain path dependencies.

Lines 11-13 travel to the repository root and back into domains/. The direct sibling paths are ../../query_engine/analyzer, ../../query_engine/model, and ../../query_engine/ui. The same file already uses direct relative paths for ../instrumentation and ../ui.

🤖 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 `@domains/simulator/analyzer/Cargo.toml` around lines 11 - 13, Update the path
dependencies for quent-query-engine-analyzer, quent-query-engine-model, and
quent-query-engine-ui to use the direct sibling paths
../../query_engine/analyzer, ../../query_engine/model, and
../../query_engine/ui, matching the existing relative-path style in Cargo.toml.
domains/simulator/application/Cargo.toml (1)

7-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

External crate versions are pinned per manifest instead of in [workspace.dependencies]. Both new manifests declare literal versions for external crates while declaring petgraph, tokio, tracing, and uuid with workspace = true. The result is two different clap constraints inside one workspace, and version bumps must touch each manifest separately.

  • domains/simulator/application/Cargo.toml#L7-L16: replace clap = {version = "4.5.57", ...} and rand = "0.10.2" with workspace = true entries, and add both crates to [workspace.dependencies] in the root Cargo.toml.
  • domains/simulator/server/Cargo.toml#L11-L12: replace axum = { version = "0.8.7" } and clap = { version = "4.5", ... } with workspace = true entries that reuse the same root declarations.
🤖 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 `@domains/simulator/application/Cargo.toml` around lines 7 - 16, Centralize the
external dependency versions in the root workspace: add clap and rand to
[workspace.dependencies], then update domains/simulator/application/Cargo.toml
lines 7-16 to use workspace = true for both; also update
domains/simulator/server/Cargo.toml lines 11-12 so axum and clap use the shared
workspace declarations.
domains/simulator/application/src/main.rs (1)

748-986: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the per-operator statistics generation.

execute_logical_plan now spans lines 647-986. Roughly 240 of those lines are the match op.kind block that builds random statistics. This block has one purpose and no dependency on worker state.

Move lines 749-965 into a free function, for example fn operator_statistics(kind: Physical, tasks_processed: u64) -> Vec<DynamicAttribute>. execute_logical_plan then reads as plan declaration, execution, and statistics emission.

🤖 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 `@domains/simulator/application/src/main.rs` around lines 748 - 986, Extract
the random per-operator attribute construction, including the attr macro and
match on Physical, from execute_logical_plan into a free function such as
operator_statistics(kind: Physical, tasks_processed: u64) ->
Vec<DynamicAttribute>. Keep all existing statistic generation behavior
unchanged, then call this function when populating operator::Statistics so
execute_logical_plan only handles plan execution and emission.
domains/simulator/analyzer/src/model.rs (1)

471-501: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mutate the model instead of rebuilding it field by field.

Lines 473-501 build temp_model, then destructure every field into a second SimulatorModel only to attach resource_group_types. A new field on SimulatorModel must be added in both places.

♻️ Proposed simplification
-        let temp_model = SimulatorModel {
+        let mut model = SimulatorModel {
             query_engine,
             arbitrary_resources: resources,
             tasks,
             resource_group_types: HashMap::default(),
         };
-        let mut resource_group_types = derive_resource_group_types(&temp_model)?;
+        let mut resource_group_types = derive_resource_group_types(&model)?;
         // Bubble up all the used_by_entity fields in the group type decls.
         for group_type_decl in resource_group_types.values_mut() {
             for contained_resource_type in &group_type_decl.contains_resource_types {
-                if let Ok(resource_type) = temp_model
+                if let Ok(resource_type) = model
                     .arbitrary_resources
                     .resource_type(contained_resource_type)
                 {
@@
-        Ok(SimulatorModel {
-            query_engine: temp_model.query_engine,
-            arbitrary_resources: temp_model.arbitrary_resources,
-            tasks: temp_model.tasks,
-            resource_group_types,
-        })
+        model.resource_group_types = resource_group_types;
+        Ok(model)
🤖 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 `@domains/simulator/analyzer/src/model.rs` around lines 471 - 501, Mutate the
existing temp_model instead of constructing a second SimulatorModel: make
temp_model mutable, assign the derived and updated resource_group_types to its
field after the bubbling loop, then return temp_model directly. Update the
construction flow around SimulatorModel and derive_resource_group_types while
preserving all existing field values.
domains/simulator/analyzer/src/lib.rs (1)

657-684: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the redundant borrow and second index.

Line 663 binds entry with &mut but only reads entry.operator_ids. Line 665 then indexes plain_builders again. The same pattern repeats on lines 675-679, 811-813, and 822-826.

Read the filter once, then index once.

♻️ Proposed simplification
                 if let Some(builder_indices) = plain_index.get(&resource_id) {
                     for &builder_idx in builder_indices {
-                        let entry = &mut plain_builders[builder_idx];
-                        if operator_matches(&entry.operator_ids, task_operator_id) {
-                            plain_builders[builder_idx].builder.try_push(&usage)?;
+                        let entry = &mut plain_builders[builder_idx];
+                        if operator_matches(&entry.operator_ids, task_operator_id) {
+                            entry.builder.try_push(&usage)?;
                         }
                     }
                 }

If the borrow checker rejects the combined borrow, split the filter check first:

let matches = operator_matches(&plain_builders[builder_idx].operator_ids, task_operator_id);
if matches {
    plain_builders[builder_idx].builder.try_push(&usage)?;
}
🤖 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 `@domains/simulator/analyzer/src/lib.rs` around lines 657 - 684, In the task
usage processing loops, remove the mutable entry borrow and avoid indexing each
builder twice: read the operator IDs from the indexed builder, store the match
result, then perform a single mutable builder access for try_push. Apply this
pattern to both plain and per-state builders here and to the corresponding
patterns around the other reported locations.
🤖 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 @.github/workflows/ui.yml:
- Line 177: Update the fallback binding path assigned to base_bindings in the
workflow’s pre-relocation branch to use
base/examples/simulator/server/ts-bindings, while preserving the ui-bindings
path when it exists.

In `@crates/codegen/Cargo.toml`:
- Line 18: Add quent-simulator-instrumentation to the root workspace
dependencies table, then update its dev-dependency declaration in the crate
manifest to use the workspace dependency instead of the local path.

In `@domains/simulator/analyzer/src/lib.rs`:
- Around line 1069-1094: Refactor SimulatorUiAnalyzer::entities_filtered to
validate entity_filter.entity_type_name first, returning the existing
InvalidArgument error for unknown types, then construct a single
tasks.values().filter closure using operator_matches and the time-window span
check. Preserve the current behavior for the recognized "task" type and for
filters without an entity type.
- Around line 1-140: Add accompanying tests across the simulator crates: in
domains/simulator/analyzer/src/lib.rs:1-140, table-test
operator_statistic_quantity, scale_operator_statistic, and
scaled_operator_statistic_name; in
domains/simulator/instrumentation/src/task.rs:73-96, exercise the Task FSM’s
emitted sequence including multi-worker sending and exit; in
domains/simulator/analyzer/src/model.rs:437-502, test
SimulatorModelBuilder::try_push and try_build with valid events and a missing
resource initialization that returns an error; in
domains/simulator/analyzer/src/task.rs:35-96, test active_span with one, two,
and many transitions plus try_to_ui_fsm bytes_per_sec derivation including equal
timestamps; and in domains/simulator/server/src/main.rs:92-99, verify each
exporter name maps to its expected Format and unknown names error.

In `@domains/simulator/analyzer/src/model.rs`:
- Around line 258-265: Replace panic-based invariant handling with
AnalyzerResult propagation at all three sites: in
domains/simulator/analyzer/src/model.rs lines 258-265, update the
TaskBuilder::try_new entry logic to use an Entry match and propagate errors with
?; in domains/simulator/analyzer/src/model.rs lines 447-460, replace
get_mut(&resource_type_name).unwrap() with InvalidTypeName error propagation;
and in domains/simulator/analyzer/src/lib.rs lines 842-865, replace both
panic-producing unwrap_or_else calls with AnalyzerError::BrokenImpl("chunked
bulk: unknown entry id") propagated via ?.

In `@domains/simulator/application/src/main.rs`:
- Around line 701-713: Validate Args::num_threads during clap parsing so only
values of at least one are accepted, preventing an empty self.threads vector. In
the physical_plan.execute task scheduling block, replace the truncated
tasks_per_thread_per_op division with balanced range calculation that assigns
every task, including the remainder, across threads.

In `@domains/simulator/instrumentation/src/task.rs`:
- Around line 84-94: Update the task FSM transitions around JoinPartition’s
producer sequence: include sending in exit_from and add a sending => sending
self-transition so repeated sending events for other workers are accepted before
exit. Preserve the existing sending => queueing transition for the normal
completion path.

In `@domains/simulator/server/src/main.rs`:
- Around line 122-129: Update the importer closure and the
`ImporterFn`/`UiAnalyzer` interfaces so event iterators yield
`ImporterResult<Event<_>>` and propagate errors lazily. Remove the eager
`collect::<Vec<_>>()` buffering in the `Simulator::import_events` path,
preserving errors through the returned iterator without discarding them or
panicking.

In `@domains/simulator/ui-bindings/src/lib.rs`:
- Around line 19-42: Add a Rust test for generate that creates a temporary
output directory containing stale content, invokes generate, verifies generation
succeeds and the stale content is removed, and confirms expected binding files
are emitted in the requested directory. Place the test alongside generate and
use the project’s existing temporary-directory and test conventions.

In `@domains/simulator/ui/Cargo.toml`:
- Around line 1-11: Add the required SPDX copyright and Apache-2.0 license
headers before [package] in domains/simulator/ui/Cargo.toml (lines 1-11) and
domains/simulator/ui-bindings/Cargo.toml (lines 1-11). In both manifests, also
set the new crates to edition 2024 and publish = false as required by the path
instructions.
- Around line 8-11: Move the local quent-analyzer dependency from the
manifest-level path declaration into [workspace.dependencies], then reference it
with workspace = true in domains/simulator/ui/Cargo.toml:8-11. Apply the same
workspace-based declaration to all three local crates in
domains/simulator/ui-bindings/Cargo.toml:8-11, ensuring neither manifest uses
direct path or git dependency declarations.

In `@domains/simulator/ui/src/lib.rs`:
- Around line 26-32: Correct EntityRef::is_resource and
EntityRef::is_resource_group so each returns true only when self matches its
corresponding variant, Resource and ResourceGroup respectively; preserve false
for all other variants. Add unit tests covering matching and non-matching
EntityRef variants for both methods.

---

Other comments:
In `@domains/simulator/server/src/main.rs`:
- Around line 64-68: Update the CORS configuration documentation above the
cors_address argument to reference QUENT_ANALYZER_CORS_ADDRESS consistently with
the env binding and its definition, so the --help text names the effective
environment variable.

---

Nitpick comments:
In `@domains/simulator/analyzer/Cargo.toml`:
- Around line 11-13: Update the path dependencies for
quent-query-engine-analyzer, quent-query-engine-model, and quent-query-engine-ui
to use the direct sibling paths ../../query_engine/analyzer,
../../query_engine/model, and ../../query_engine/ui, matching the existing
relative-path style in Cargo.toml.

In `@domains/simulator/analyzer/src/lib.rs`:
- Around line 657-684: In the task usage processing loops, remove the mutable
entry borrow and avoid indexing each builder twice: read the operator IDs from
the indexed builder, store the match result, then perform a single mutable
builder access for try_push. Apply this pattern to both plain and per-state
builders here and to the corresponding patterns around the other reported
locations.

In `@domains/simulator/analyzer/src/model.rs`:
- Around line 471-501: Mutate the existing temp_model instead of constructing a
second SimulatorModel: make temp_model mutable, assign the derived and updated
resource_group_types to its field after the bubbling loop, then return
temp_model directly. Update the construction flow around SimulatorModel and
derive_resource_group_types while preserving all existing field values.

In `@domains/simulator/application/Cargo.toml`:
- Around line 7-16: Centralize the external dependency versions in the root
workspace: add clap and rand to [workspace.dependencies], then update
domains/simulator/application/Cargo.toml lines 7-16 to use workspace = true for
both; also update domains/simulator/server/Cargo.toml lines 11-12 so axum and
clap use the shared workspace declarations.

In `@domains/simulator/application/src/main.rs`:
- Around line 748-986: Extract the random per-operator attribute construction,
including the attr macro and match on Physical, from execute_logical_plan into a
free function such as operator_statistics(kind: Physical, tasks_processed: u64)
-> Vec<DynamicAttribute>. Keep all existing statistic generation behavior
unchanged, then call this function when populating operator::Statistics so
execute_logical_plan only handles plan execution and emission.

In `@domains/simulator/instrumentation/Cargo.toml`:
- Around line 11-13: Update the quent-query-engine-model dependency in the
instrumentation Cargo.toml manifest to use the direct sibling-domain path
../../query_engine/model instead of traversing through the repository root;
leave the other dependency paths unchanged.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: dc4edfb3-1980-4e49-b572-9d3c258e58f3

📥 Commits

Reviewing files that changed from the base of the PR and between c0e7b60 and f2bf1dc.

📒 Files selected for processing (29)
  • .github/workflows/ui.yml
  • .pre-commit-config.ci.yaml
  • .pre-commit-config.yaml
  • Cargo.toml
  • README.md
  • crates/codegen/Cargo.toml
  • docs/domains/query_engine/examples/README.md
  • docs/domains/query_engine/examples/simulator.md
  • domains/query_engine/server/Cargo.toml
  • domains/query_engine/tests/fixed/Cargo.toml
  • domains/query_engine/tests/fixed/src/lib.rs
  • domains/simulator/analyzer/Cargo.toml
  • domains/simulator/analyzer/src/lib.rs
  • domains/simulator/analyzer/src/model.rs
  • domains/simulator/analyzer/src/task.rs
  • domains/simulator/analyzer/src/view.rs
  • domains/simulator/application/Cargo.toml
  • domains/simulator/application/src/main.rs
  • domains/simulator/instrumentation/Cargo.toml
  • domains/simulator/instrumentation/src/lib.rs
  • domains/simulator/instrumentation/src/task.rs
  • domains/simulator/server/Cargo.toml
  • domains/simulator/server/src/main.rs
  • domains/simulator/ui-bindings/Cargo.toml
  • domains/simulator/ui-bindings/src/lib.rs
  • domains/simulator/ui-bindings/src/main.rs
  • domains/simulator/ui/Cargo.toml
  • domains/simulator/ui/src/lib.rs
  • ui/REVIEW.md
🛑 Comments failed to post (10)
domains/simulator/analyzer/src/lib.rs (2)

1-140: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

The five new Rust crates ship without tests. The coding guidelines require that new Rust components include accompanying tests. This cohort adds quent-simulator-instrumentation, quent-simulator, quent-simulator-analyzer, quent-simulator-server, and their UI crates, and none of the reviewed files contains a #[cfg(test)] module or a tests/ directory. Several behaviors reviewed above are only verifiable by reading the code.

  • domains/simulator/analyzer/src/lib.rs#L1-L140: add unit tests for scale_operator_statistic, scaled_operator_statistic_name, and operator_statistic_quantity. These are pure functions with table-driven inputs.
  • domains/simulator/instrumentation/src/task.rs#L73-L96: add a test that drives the Task FSM through the exact sequence the simulator emits, including the multi-worker sending loop and the exit that follows it.
  • domains/simulator/analyzer/src/model.rs#L437-L502: add a test that feeds a small synthetic SimulatorEvent stream through SimulatorModelBuilder::try_push and try_build, including a stream that omits a resource initializing event, to lock in error return rather than panic.
  • domains/simulator/analyzer/src/task.rs#L35-L96: add tests for active_span with one, two, and many transitions, and for try_to_ui_fsm bytes_per_sec derivation including the equal-timestamp case.
  • domains/simulator/server/src/main.rs#L92-L99: add a test that asserts each accepted exporter name maps to the expected Format and that an unknown name returns an error.

As per coding guidelines: "New Rust components must include accompanying tests."

📍 Affects 5 files
  • domains/simulator/analyzer/src/lib.rs#L1-L140 (this comment)
  • domains/simulator/instrumentation/src/task.rs#L73-L96
  • domains/simulator/analyzer/src/model.rs#L437-L502
  • domains/simulator/analyzer/src/task.rs#L35-L96
  • domains/simulator/server/src/main.rs#L92-L99
🤖 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 `@domains/simulator/analyzer/src/lib.rs` around lines 1 - 140, Add accompanying
tests across the simulator crates: in
domains/simulator/analyzer/src/lib.rs:1-140, table-test
operator_statistic_quantity, scale_operator_statistic, and
scaled_operator_statistic_name; in
domains/simulator/instrumentation/src/task.rs:73-96, exercise the Task FSM’s
emitted sequence including multi-worker sending and exit; in
domains/simulator/analyzer/src/model.rs:437-502, test
SimulatorModelBuilder::try_push and try_build with valid events and a missing
resource initialization that returns an error; in
domains/simulator/analyzer/src/task.rs:35-96, test active_span with one, two,
and many transitions plus try_to_ui_fsm bytes_per_sec derivation including equal
timestamps; and in domains/simulator/server/src/main.rs:92-99, verify each
exporter name maps to its expected Format and unknown names error.

Source: Coding guidelines


1069-1094: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove the duplicated task filter closure.

The closure body on lines 1079-1082 and the closure body on lines 1089-1092 are identical. Only the entity-type validation differs.

♻️ Proposed simplification
     fn entities_filtered(
         &self,
         entity_filter: EntityFilter,
         operator_ids: HashSet<Uuid>,
         time_window: SpanNanoSec,
     ) -> AnalyzerResult<Box<dyn Iterator<Item = &Task> + '_>> {
-        if let Some(entity_type_name) = entity_filter.entity_type_name {
-            match entity_type_name.as_str() {
-                "task" => Ok(Box::new(self.model.tasks.values().filter(move |task| {
-                    operator_matches(&operator_ids, task.operator_id())
-                        && task.span().is_ok_and(|s| s.intersects(&time_window))
-                }))),
-                _ => Err(AnalyzerError::InvalidArgument(format!(
-                    "{} is not a known entity type in this model",
-                    entity_type_name
-                ))),
-            }
-        } else {
-            Ok(Box::new(self.model.tasks.values().filter(move |task| {
-                operator_matches(&operator_ids, task.operator_id())
-                    && task.span().is_ok_and(|s| s.intersects(&time_window))
-            })))
-        }
+        if let Some(entity_type_name) = &entity_filter.entity_type_name
+            && entity_type_name != "task"
+        {
+            return Err(AnalyzerError::InvalidArgument(format!(
+                "{entity_type_name} is not a known entity type in this model"
+            )));
+        }
+        Ok(Box::new(self.model.tasks.values().filter(move |task| {
+            operator_matches(&operator_ids, task.operator_id())
+                && task.span().is_ok_and(|s| s.intersects(&time_window))
+        })))
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

impl SimulatorUiAnalyzer {
    /// Return an iterator over all tasks, filtered by time window and operator ids.
    fn entities_filtered(
        &self,
        entity_filter: EntityFilter,
        operator_ids: HashSet<Uuid>,
        time_window: SpanNanoSec,
    ) -> AnalyzerResult<Box<dyn Iterator<Item = &Task> + '_>> {
        if let Some(entity_type_name) = &entity_filter.entity_type_name
            && entity_type_name != "task"
        {
            return Err(AnalyzerError::InvalidArgument(format!(
                "{entity_type_name} is not a known entity type in this model"
            )));
        }
        Ok(Box::new(self.model.tasks.values().filter(move |task| {
            operator_matches(&operator_ids, task.operator_id())
                && task.span().is_ok_and(|s| s.intersects(&time_window))
        })))
    }
🤖 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 `@domains/simulator/analyzer/src/lib.rs` around lines 1069 - 1094, Refactor
SimulatorUiAnalyzer::entities_filtered to validate
entity_filter.entity_type_name first, returning the existing InvalidArgument
error for unknown types, then construct a single tasks.values().filter closure
using operator_matches and the time-window span check. Preserve the current
behavior for the recognized "task" type and for filters without an entity type.
domains/simulator/analyzer/src/model.rs (1)

258-265: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Invariant violations abort the process instead of returning AnalyzerError. Four sites in the analyzer crate panic on conditions the authors believe are unreachable. Every one of these sites sits on a path that analyzer_service_router in domains/simulator/server/src/main.rs runs while serving HTTP requests, and every enclosing function already returns AnalyzerResult. A malformed, truncated, or out-of-order event stream then crashes the service instead of producing an error response. domains/simulator/analyzer/src/lib.rs line 873 already models the correct behavior with AnalyzerError::BrokenImpl.

  • domains/simulator/analyzer/src/model.rs#L258-L265: replace TaskBuilder::try_new(id).unwrap() with an Entry match that propagates the error using ?.
  • domains/simulator/analyzer/src/model.rs#L447-L460: replace the get_mut(&resource_type_name).unwrap() with .ok_or_else(|| AnalyzerError::InvalidTypeName(resource_type_name.clone()))?.
  • domains/simulator/analyzer/src/lib.rs#L842-L865: replace both unwrap_or_else(|| panic!(...)) calls with .ok_or(AnalyzerError::BrokenImpl("chunked bulk: unknown entry id"))?.
📍 Affects 2 files
  • domains/simulator/analyzer/src/model.rs#L258-L265 (this comment)
  • domains/simulator/analyzer/src/model.rs#L447-L460
  • domains/simulator/analyzer/src/lib.rs#L842-L865
🤖 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 `@domains/simulator/analyzer/src/model.rs` around lines 258 - 265, Replace
panic-based invariant handling with AnalyzerResult propagation at all three
sites: in domains/simulator/analyzer/src/model.rs lines 258-265, update the
TaskBuilder::try_new entry logic to use an Entry match and propagate errors with
?; in domains/simulator/analyzer/src/model.rs lines 447-460, replace
get_mut(&resource_type_name).unwrap() with InvalidTypeName error propagation;
and in domains/simulator/analyzer/src/lib.rs lines 842-865, replace both
panic-producing unwrap_or_else calls with AnalyzerError::BrokenImpl("chunked
bulk: unknown entry id") propagated via ?.
domains/simulator/application/src/main.rs (1)

701-713: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

--num-threads 0 causes a division-by-zero panic.

Line 703 divides by self.threads.len(). Args::num_threads is a usize with no lower bound, so --num-threads 0 produces an empty threads vector and panics at this line.

The same line also truncates silently. With --num-tasks 32 --num-threads 5, each thread runs 6 tasks and the simulator emits 30 tasks per operator instead of 32.

Validate num_threads at parse time with a clap value parser, and distribute the remainder.

🐛 Proposed guard on the argument
     /// Number of threads per worker thread pool
-    #[arg(long, default_value_t = 2)]
+    #[arg(long, default_value_t = 2, value_parser = clap::value_parser!(u16).range(1..))]
     num_threads: usize,

Adjust the field type or convert the parsed value as needed. Alternatively guard at the use site:

-            let tasks_per_thread_per_op = num_tasks / self.threads.len();
+            if self.threads.is_empty() {
+                return;
+            }
+            let tasks_per_thread_per_op = num_tasks / self.threads.len();
🤖 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 `@domains/simulator/application/src/main.rs` around lines 701 - 713, Validate
Args::num_threads during clap parsing so only values of at least one are
accepted, preventing an empty self.threads vector. In the physical_plan.execute
task scheduling block, replace the truncated tasks_per_thread_per_op division
with balanced range calculation that assigns every task, including the
remainder, across threads.
domains/simulator/instrumentation/src/task.rs (1)

84-94: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect the fsm! macro contract and the simulator send loop.
set -euo pipefail

# Locate the fsm! macro implementation.
fd -t f -e rs . crates/model | xargs rg -n -C 10 'exit_from|macro_rules!\s+fsm|fn\s+fsm\b' || true

# Show how transitions and exit states are validated/generated.
rg -n -C 15 'exit_from' --type=rust crates || true

# Confirm the repeated sending calls in the producer.
rg -n -C 12 'fn execute_physical_operator_task' domains/simulator/application/src/main.rs

Repository: rapidsai/quent

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- FSM declaration ---'
cat -n domains/simulator/instrumentation/src/task.rs | sed -n '70,105p'

printf '%s\n' '--- Producer send loop ---'
cat -n domains/simulator/application/src/main.rs | sed -n '600,665p'

printf '%s\n' '--- Generated transition and exit behavior ---'
cat -n crates/model-macros/src/fsm_macro.rs | sed -n '243,360p'
rg -n -C 8 'TransitionEndpoint|transition\(|exit\(|Exit' crates/model crates/model-macros domains/simulator --type rust | head -n 260

Repository: rapidsai/quent

Length of output: 26110


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- FSM-generated handle ---'
cat -n crates/model-macros/src/fsm_macro.rs | sed -n '360,490p'

printf '%s\n' '--- State-generated handle lifecycle methods ---'
cat -n crates/model-macros/src/state_macro.rs | sed -n '300,390p'

printf '%s\n' '--- Runtime transition emission and exit guards ---'
rg -n -C 12 'struct .*Handle|fn emit_transition|fn exit|exited|TransitionInfo' crates --type rust | head -n 320

Repository: rapidsai/quent

Length of output: 31074


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- FSM handle implementation ---'
cat -n crates/model-macros/src/fsm_macro.rs | sed -n '483,570p'

printf '%s\n' '--- All emit_transition definitions ---'
rg -n -C 15 'emit_transition' crates --type rust

printf '%s\n' '--- Exit call sites and generated exit method ---'
rg -n -C 12 '\.exit\(\)|fn exit' domains crates --type rust | head -n 220

Repository: rapidsai/quent

Length of output: 31078


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- JoinPartition send selection ---'
rg -n -C 18 'JoinPartition|let send|send:' domains/simulator --type rust

printf '%s\n' '--- Consumers of FSM transition metadata ---'
rg -n -C 12 'fsm_def\.transitions|FsmDef|TransitionDef|TransitionEndpoint' crates domains --type rust | head -n 360

printf '%s\n' '--- Analyzer FSM validation and transition handling ---'
rg -n -C 14 'unreachable|invalid.*transition|transition.*valid|state.*transition|FsmTypeDecl|FsmTransitionDecl' crates/analyzer crates/yaml crates --type rust | head -n 360

Repository: rapidsai/quent

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Fsm transition declaration types ---'
rg -n -C 18 'enum FsmTransitionDecl|struct FsmTypeDecl|trait FsmTypeDeclaration|transitions\(' crates/analyzer/src/fsm crates/analyzer/src --type rust

printf '%s\n' '--- Uses of FsmTypeDeclaration transitions ---'
rg -n -C 16 'fsm_type_declaration|FsmTransitionDecl|FsmTypeDecl' crates/analyzer/src crates --type rust | head -n 300

Repository: rapidsai/quent

Length of output: 42285


Align the task FSM with the producer sequence.

JoinPartition emits sending once per other worker, then emits exit. Add sending => sending and sending to exit_from, or change the producer sequence.

🤖 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 `@domains/simulator/instrumentation/src/task.rs` around lines 84 - 94, Update
the task FSM transitions around JoinPartition’s producer sequence: include
sending in exit_from and add a sending => sending self-transition so repeated
sending events for other workers are accepted before exit. Preserve the existing
sending => queueing transition for the normal completion path.
domains/simulator/server/src/main.rs (1)

122-129: 🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Determine the importer closure signature expected by analyzer_service_router.
set -euo pipefail

rg -n -C 15 'fn analyzer_service_router' --type=rust domains/query_engine/server/src

# Importer type alias and its item type.
rg -n -C 8 'Importer|Box<dyn Iterator' --type=rust domains/query_engine/server/src || true

Repository: rapidsai/quent

Length of output: 17102


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- simulator importer and call site ---'
cat -n domains/simulator/server/src/main.rs | sed -n '105,140p'
rg -n -C 12 'fn import_events|import_events|ImporterResult|type ImporterResult|struct Importer' --type rust .

printf '%s\n' '--- analyzer cache consumers ---'
cat -n domains/query_engine/server/src/analyzer_cache.rs | sed -n '145,260p'
rg -n -C 8 'chain_context_events|for .*event|Analyzer::|analyzers' domains/query_engine/server/src/analyzer_cache.rs

Repository: rapidsai/quent

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

files = {
    "importer_fn": Path("domains/query_engine/server/src/analyzer_cache.rs"),
    "simulator_main": Path("domains/simulator/server/src/main.rs"),
    "ui_analyzer": Path("domains/query_engine/analyzer/src/ui.rs"),
    "simulator_analyzer": Path("domains/simulator/analyzer/src/lib.rs"),
}

text = {name: path.read_text() for name, path in files.items()}

checks = {
    "ImporterFn consumes infallible events":
        re.search(r"pub type ImporterFn.*Iterator<Item = Event<", text["importer_fn"], re.S),
    "chain_context_events consumes infallible events":
        re.search(r"chain_context_events.*?Iterator<Item = Event<", text["importer_fn"], re.S),
    "Simulator importer yields fallible events":
        re.search(r"Item\s*=\s*quent_model::io::ImporterResult<\s*quent_model::Event<", 
                  Path("crates/model-macros/src/model_macro.rs").read_text(), re.S),
    "Simulator main collects importer results":
        "collect::<quent_io::ImporterResult<Vec<_>>>()?" in text["simulator_main"],
    "UiAnalyzer constructors consume infallible events":
        bool(re.search(r"Iterator<Item = Event<", text["ui_analyzer"])),
}

for name, passed in checks.items():
    print(f"{'PASS' if passed else 'FAIL'}: {name}")
PY

printf '%s\n' '--- analyzer construction signatures ---'
rg -n -C 6 'fn try_new|fn extract_engine|Iterator<Item = Event|ImporterResult' \
  domains/query_engine/analyzer domains/simulator/analyzer

Repository: rapidsai/quent

Length of output: 22988


Accept fallible event streams before removing the buffer

Simulator::import_events yields ImporterResult<Event<_>>, while ImporterFn and UiAnalyzer require Iterator<Item = Event<_>>. Change these interfaces to propagate importer errors lazily before removing the Vec; do not discard errors or panic.

🤖 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 `@domains/simulator/server/src/main.rs` around lines 122 - 129, Update the
importer closure and the `ImporterFn`/`UiAnalyzer` interfaces so event iterators
yield `ImporterResult<Event<_>>` and propagate errors lazily. Remove the eager
`collect::<Vec<_>>()` buffering in the `Simulator::import_events` path,
preserving errors through the returned iterator without discarding them or
panicking.
domains/simulator/ui-bindings/src/lib.rs (1)

19-42: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add a test for binding generation.

Test that generate removes stale output, completes generation, and emits bindings into the requested directory. This protects the generated UI contract and the output-directory behavior. As per coding guidelines, “New Rust components must include accompanying tests.”

🤖 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 `@domains/simulator/ui-bindings/src/lib.rs` around lines 19 - 42, Add a Rust
test for generate that creates a temporary output directory containing stale
content, invokes generate, verifies generation succeeds and the stale content is
removed, and confirms expected binding files are emitted in the requested
directory. Place the test alongside generate and use the project’s existing
temporary-directory and test conventions.

Source: Coding guidelines

domains/simulator/ui/Cargo.toml (2)

1-11: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add SPDX headers to both new crate manifests.

  • domains/simulator/ui/Cargo.toml#L1-L11: add the required SPDX copyright and Apache-2.0 license header before [package].
  • domains/simulator/ui-bindings/Cargo.toml#L1-L11: add the required SPDX copyright and Apache-2.0 license header before [package].

As per path instructions, “New crates: edition 2024, publish = false, SPDX headers.”

📍 Affects 2 files
  • domains/simulator/ui/Cargo.toml#L1-L11 (this comment)
  • domains/simulator/ui-bindings/Cargo.toml#L1-L11
🤖 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 `@domains/simulator/ui/Cargo.toml` around lines 1 - 11, Add the required SPDX
copyright and Apache-2.0 license headers before [package] in
domains/simulator/ui/Cargo.toml (lines 1-11) and
domains/simulator/ui-bindings/Cargo.toml (lines 1-11). In both manifests, also
set the new crates to edition 2024 and publish = false as required by the path
instructions.

Source: Path instructions


8-11: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use workspace dependency declarations for local crates.

  • domains/simulator/ui/Cargo.toml#L8-L11: declare quent-analyzer in [workspace.dependencies] and use quent-analyzer.workspace = true.
  • domains/simulator/ui-bindings/Cargo.toml#L8-L11: declare the three local crates in [workspace.dependencies] and use workspace = true in this manifest.

As per path instructions, “Dependencies come from [workspace.dependencies] via workspace = true; no git deps.”

📍 Affects 2 files
  • domains/simulator/ui/Cargo.toml#L8-L11 (this comment)
  • domains/simulator/ui-bindings/Cargo.toml#L8-L11
🤖 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 `@domains/simulator/ui/Cargo.toml` around lines 8 - 11, Move the local
quent-analyzer dependency from the manifest-level path declaration into
[workspace.dependencies], then reference it with workspace = true in
domains/simulator/ui/Cargo.toml:8-11. Apply the same workspace-based declaration
to all three local crates in domains/simulator/ui-bindings/Cargo.toml:8-11,
ensuring neither manifest uses direct path or git dependency declarations.

Source: Path instructions

domains/simulator/ui/src/lib.rs (1)

26-32: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Return true only for the matching entity type.

Line 28 reports false for EntityRef::Resource and true for every non-resource variant. Line 31 reports false for EntityRef::Task instead of checking EntityRef::ResourceGroup. This misclassifies entities in analyzer resource views.

Proposed fix
     fn is_resource(&self) -> bool {
-        !matches!(self, EntityRef::Resource(_))
+        matches!(self, EntityRef::Resource(_))
     }
     fn is_resource_group(&self) -> bool {
-        !matches!(self, EntityRef::Task(_))
+        matches!(self, EntityRef::ResourceGroup(_))
     }

Add unit tests for both matching and non-matching variants. As per coding guidelines, “New Rust components must include accompanying tests.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

impl EntityId for EntityRef {
    fn is_resource(&self) -> bool {
        matches!(self, EntityRef::Resource(_))
    }
    fn is_resource_group(&self) -> bool {
        matches!(self, EntityRef::ResourceGroup(_))
    }
🤖 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 `@domains/simulator/ui/src/lib.rs` around lines 26 - 32, Correct
EntityRef::is_resource and EntityRef::is_resource_group so each returns true
only when self matches its corresponding variant, Resource and ResourceGroup
respectively; preserve false for all other variants. Add unit tests covering
matching and non-matching EntityRef variants for both methods.

Source: Coding guidelines

@johanpel

Copy link
Copy Markdown
Contributor

Looks like there are some conflicts that need to be fixed first.

@johanpel
johanpel marked this pull request as draft August 27, 2026 07:34
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.

Move simulator to domain/

2 participants