Skip to content

fix(adaptive): reuse stable ACG scaffolds - #481

Open
teerthsharma wants to merge 8 commits into
NVIDIA:mainfrom
teerthsharma:fix/acg-stable-scaffold-reuse
Open

fix(adaptive): reuse stable ACG scaffolds#481
teerthsharma wants to merge 8 commits into
NVIDIA:mainfrom
teerthsharma:fix/acg-stable-scaffold-reuse

Conversation

@teerthsharma

@teerthsharma teerthsharma commented Jul 20, 2026

Copy link
Copy Markdown

Overview

ACG includes the first non-system message in its learning key. A workflow whose
system prompt, tool schemas, and output contract never change is therefore split
into a separate profile for every distinct first user task, so observations never
accumulate and the stable scaffold is never recognized as a reusable prefix.

This change buckets learning by the stable system/tool/structured-output
scaffold, preserves the prior task seed for requests without one, and gates reuse
on a fingerprint bound to the exact scaffold key.

Scope is the three items assessed as meaningful in the #323 review:
scaffold-aware keying, a stable-prefix fingerprint guard, and the
structured-output contract in PromptIR. No governor, drift detector,
convergence machinery, topology state, configuration surface, or binding change.
Nothing is added to Python, Node, Go, WebAssembly, or C FFI.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

5 source files (+432/-51), 18 test files (+938/-35).

  • The learning key derives from the stable scaffold. Requests carrying a system
    prompt, tool schemas, or a structured-output contract bucket under
    seed=stable-scaffold; requests without one keep the prior task-seed behavior.
  • structured_output_schema_id is populated and the canonicalized
    response_format becomes a scaffold block ahead of the first non-system
    message, so an unchanging output contract sits inside the stable prefix.
  • Fingerprints bind to the exact scaffold key. A prefix stopping inside the
    scaffold binds to that scaffold; one extending past it binds to the complete
    source request, because the normalized IR retains no lossless provider-prefix
    representation.
  • The gate fails closed on legacy, missing, shorter, mismatched, and
    beyond-scaffold-without-a-source-request fingerprints.
  • find_stable_prefix_length is removed. This change replaces its only caller
    and nothing else in the workspace used it.

Learning-key fragmentation on main

Control: main at 2ab7a070, no source change. Two requests sharing a system
prompt and tool schema, differing only in the first user task, key as:

agent-a::model=gpt-4o::seed=user:sha256:d006::system=sha256:1a842e58b::tools=sha256:69848c057
agent-a::model=gpt-4o::seed=user:sha256:5607::system=sha256:1a842e58b::tools=sha256:69848c057

system and tools are identical; only seed differs, so the two runs land in
separate profiles and neither accumulates enough observations to produce a
reusable prefix. On this head the pair produces one key with
seed=stable-scaffold.

Reuse determinism

A profile persisted by one process is read back by another, so the analysis must
not depend on the per-process seed Rust draws for HashMap iteration. Over N
processes producing outcomes with multiplicities c_1..c_k, the cross-process
agreement rate is

A = sum_i c_i (c_i - 1) / (N (N - 1))

the probability two independent processes agree, and equivalently the probability
that a persisted profile satisfies the reuse gate elsewhere. A = 1 exactly when
the analysis is seed-independent.

Measured over N = 20 processes on one 20-observation window whose first turn
varies in 1 of 20 runs, with four tool spans sharing a sequence index:

Rule Span order A Prefix length A Fingerprint A Prefix
Per-span run on sequence_index (main) 0.000 0.479 0.479 1 ×9, 2 ×11
Per-span run on (index, rank, span id) 1.000 1.000 1.000 1
Exact prefix mass 1.000 1.000 1.000 6

main derives the prefix as the leading run of per-span scores, then
re-sequences those scores by first-seen index. That index does not order the span
set: span ids carry the role and tool suffix, so assistant-1-search and
assistant-1-fetch are distinct spans at index 1, and the index is a minimum
across observations. At A = 0.479, better than half of cross-process profile
reads miss.

Two changes follow. Score ordering extends to (index, stability rank, span id),
injective because span ids are unique within one analysis. Prefix economics walks
that vector and stops pricing at the first non-stable span, so ranking the least
stable first ends the priced prefix at a contested position instead of pricing
across it.

The prefix length no longer reads that vector. It descends the prefix tree of
block sequences while one child holds the configured share, which is the rule
named in the #323 review: the same exact prefix observed for N samples. Descent
also requires a strict majority, which two disjoint children cannot both hold, so
the dominant child is unique where it exists and no tie-break is reachable; where
none dominates, the prefix stops. Equivalently, under d(x, y) = 2^-lcp(x, y)
the window is ultrametric, and every point of a closed ball is a center, so the
ball is fixed by its members rather than by traversal order.

That also recovers reuse. On this window 19 of 20 observations share an exact
6-block prefix; the per-span rule reports 1 because the minority span at index 1
stops the run. The outlier still fails the fingerprint gate, so the wider prefix
stays exactly validated.

Test coverage

Variable first-user tasks under one scaffold; changed system prompts, tool
schemas, and output contracts; canonical structured output; whitespace changes
hidden by normalized IR; prefixes beyond the scaffold; legacy state with no
fingerprint; same-run aggregation; fresh-cache rehydration; Redis restart;
serialization compatibility.

Adversarial cases: an interleaving storage backend that yields between the
learner's load and store halves shows concurrent runs never pair a fingerprint
with a foreign observation window; two workflows sharing a system prompt and
anchor turn collapse to one key and then fail closed once the prefix extends past
the scaffold; every rotation of one span set produces a single canonical ordering
without depending on a hash seed.

The Redis restart test previously read its learning key out of the hot cache, so
it passed for whichever key process_run wrote — and process_run also persists
under the plain agent id for rehydration, so a mis-keyed scaffold record could
have satisfied it. It now asserts the key is not the bare agent id and carries the
stable-scaffold marker before reloading.

Validation

PR head 25c771e7 on main at 2ab7a070, Windows 11, rustc 1.97.1, go 1.26.1:

Suite Result
cargo test -p nemo-relay-adaptive 538/538 lib, 8/8 surface, 36/36 response cache, 4/4 response-cache bench, 12/12 runtime integration, 1 doctest passed and 3 ignored
NEMO_RELAY_RUN_REDIS_TESTS=1 … --features redis-backend --test redis_integration 11/11 against Redis 8.0.5 on 127.0.0.1:6379
just test-python 609 passed, 5 skipped
just test-node 342 passed, 2 skipped, 0 failed of 344
cargo clippy -p nemo-relay-adaptive -p nemo-relay-python --all-targets -- -D warnings clean
cargo fmt --all -- --check clean

The 36 response-cache and 4 response-cache benchmark tests cover the opt-in
exact-match LLM response cache from #404 and pass unchanged on this head.

Limits

No provider-cache, cost, or latency improvement is claimed. The analysis-only
trace report, the three-arm interleaved experiment, and the provider
cache-read/cache-write, billed-cost, parity, and p50/p95/p99 evidence requested in
points 1 through 3 of the #323 review are not supplied here; this diff is the
internal keying and validation change those points would measure. An earlier
interleaved run showed the fragmentation directly (144 keys and 0 hints versus 1
key and 120 hints) but used an older main and a benchmark overlay, so it is not
offered as evidence for this diff.

The exact-prefix-mass rule widens prefixes relative to main, which is a
behavior change and not only a determinism fix; reuse remains gated on the exact
fingerprint.

Two suites did not run on this host: just test-go requires clang/lld, and
full-workspace just test-rust reaches unrelated CLI filesystem failures on
Windows. CI provides the authoritative Linux matrix.

Persisted JSON stays backward-compatible through an optional fingerprint field,
which is source-visible to downstream Rust constructing StabilityAnalysisResult
with a struct literal.

Where should the reviewer start?

crates/adaptive/src/acg_profile.rs for the learning-key boundary, then
crates/adaptive/src/acg/stability.rs for the prefix and ordering rules and
crates/adaptive/src/acg_component.rs for the gate. Focused tests are in
crates/adaptive/tests/unit/acg_profile_tests.rs,
crates/adaptive/tests/unit/acg/stability_internal_tests.rs, and
crates/adaptive/tests/unit/acg_component_tests.rs.

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

@copy-pr-bot

copy-pr-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added size:L PR is large Bug issue describes bug; PR fixes bug lang:rust PR changes/introduces Rust code labels Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

ACG prompt IR now includes canonicalized structured output. Learning and profile keys incorporate scaffold and response-format fingerprints. Stability results persist dominant prefix fingerprints, and intent construction validates live fingerprints before reuse. Tests cover key bucketing, persistence, serialization, and mismatch rejection.

Changes

ACG scaffold fingerprinting

Layer / File(s) Summary
Prompt scaffolds and key derivation
crates/adaptive/src/acg/ir_builder.rs, crates/adaptive/src/acg_profile.rs, crates/adaptive/tests/unit/acg/*, crates/adaptive/tests/unit/runtime_tests.rs
Structured output is canonicalized into prompt blocks and schema IDs. Stable scaffolds use deterministic learning-key seeds. Response formats are included when present.
Stability fingerprint computation and persistence
crates/adaptive/src/acg/stability.rs, crates/adaptive/src/acg_learner.rs, crates/adaptive/tests/unit/acg_learner_tests.rs, crates/adaptive/tests/integration/redis_tests.rs
Stability analysis computes dominant profile-prefix fingerprints. The learner persists fingerprints with observations and stability data. Tests cover concurrent runs, shared scaffolds, Redis reloads, and deterministic selection.
Fingerprint-gated reuse and regression coverage
crates/adaptive/src/acg_component.rs, crates/adaptive/tests/unit/acg_component_tests.rs
Intent construction requires matching stored and live fingerprints. Tests cover rehydration, changed content, whitespace changes, missing fingerprints, invalid prefix lengths, and request-scoped fixtures.

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

Sequence Diagram(s)

sequenceDiagram
  participant AnnotatedLlmRequest
  participant build_prompt_ir
  participant AcgLearner
  participant RedisBackend
  participant build_intent_bundle
  AnnotatedLlmRequest->>build_prompt_ir: messages and response_format
  build_prompt_ir-->>AcgLearner: PromptIR and structured_output_schema_id
  AcgLearner->>AcgLearner: analyze stability and derive prefix fingerprint
  AcgLearner->>RedisBackend: persist observations and stability
  RedisBackend-->>build_intent_bundle: stored stability fingerprint
  build_intent_bundle->>build_intent_bundle: compare live and stored fingerprints
  build_intent_bundle-->>AnnotatedLlmRequest: intent bundle or skipped result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.33% 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
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description includes all required sections, explains the changes and scope, identifies review starting points, and links related issues.
Title check ✅ Passed The title follows Conventional Commits format with a valid type and scope, uses an imperative summary, and is 41 characters long.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@teerthsharma
teerthsharma marked this pull request as ready for review July 20, 2026 13:59
@teerthsharma
teerthsharma requested a review from a team as a code owner July 20, 2026 13:59

@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: 3

🤖 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 `@crates/adaptive/src/acg_profile.rs`:
- Around line 101-110: In the response_format_hash construction within the
profile-building logic, remove the unreachable has_stable_scaffold conditional
and short_hash call. Map response_format_fingerprint directly to an owned string
so the full fingerprint is always preserved, while keeping the existing optional
behavior unchanged.

In `@crates/adaptive/src/acg/stability.rs`:
- Around line 165-178: Update the fingerprint construction around
request_fingerprint so a deeper prefix (prefix_length > scaffold_length) returns
None when observation.source_request_hash is absent, rather than falling back to
"stable-scaffold"; retain the stable fallback for non-deeper prefixes. Add a
regression test covering a deeper prefix without source_request_hash and
asserting no fingerprint is produced.

In `@crates/adaptive/tests/integration/redis_tests.rs`:
- Around line 531-543: Update the restart assertions in the Redis integration
test to derive the scaffold-specific learning key from the request used by
process_run, then pass that key to restarted.load_observations and
restarted.load_stability. Keep the existing count and fingerprint assertions,
ensuring they validate the scaffold profile record rather than the plain
agent_id aggregate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: e2272280-9799-46b2-baf1-c68bd359d9c6

📥 Commits

Reviewing files that changed from the base of the PR and between 37efc33 and 6e11d11.

📒 Files selected for processing (23)
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (15)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
crates/adaptive/**

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep crates/adaptive aligned with the canonical adaptive config schema, built-in section helpers, plugin lifecycle, and validation/report behavior.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/python/tests/coverage/py_storage_coverage_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/python/tests/coverage/py_storage_coverage_tests.rs
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/ir_builder.rs
🔇 Additional comments (22)
crates/adaptive/src/acg/ir_builder.rs (1)

35-83: LGTM!

Also applies to: 263-284

crates/adaptive/src/acg_profile.rs (1)

33-46: LGTM!

Also applies to: 71-100, 225-232

crates/adaptive/tests/unit/acg/ir_builder_tests.rs (1)

191-251: LGTM!

crates/adaptive/tests/unit/acg_profile_tests.rs (1)

49-145: LGTM!

crates/adaptive/tests/unit/runtime_tests.rs (1)

416-417: LGTM!

Also applies to: 493-495

crates/adaptive/tests/unit/acg_learner_tests.rs (1)

231-267: LGTM!

crates/adaptive/tests/unit/runtime_features_tests.rs (1)

90-97: LGTM!

Also applies to: 123-127

crates/python/tests/coverage/py_storage_coverage_tests.rs (1)

143-143: LGTM!

crates/adaptive/tests/unit/acg/economics_internal_tests.rs (1)

124-124: LGTM!

crates/adaptive/tests/unit/acg_component_tests.rs (1)

50-50: LGTM!

Also applies to: 235-235, 266-266, 291-311, 454-458, 534-538, 584-605, 646-646, 677-681, 737-737, 815-846, 945-950, 982-1131, 1185-1185, 1240-1240, 1287-1291, 1390-1390, 1431-1435, 1569-1573

crates/adaptive/src/acg_component.rs (1)

136-162: LGTM!

crates/adaptive/tests/integration/runtime_integration_tests.rs (1)

516-517: LGTM!

crates/adaptive/src/acg/stability.rs (1)

42-145: LGTM!

crates/adaptive/src/acg_learner.rs (1)

108-114: 📐 Maintainability & Code Quality

Provide the required validation evidence.

The supplied summary does not confirm cargo fmt --all, just test-rust, or the required Rust/Python/Go/Node matrix for this crates/adaptive change. Please run and attach results for cargo fmt --all, cargo clippy --workspace --all-targets -- -D warnings, just test-rust, and the repository’s full language matrix.

As per coding guidelines, “Any Rust change must run just test-rust,” “Any Rust change must run cargo fmt --all,” and “Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings.” As per path instructions, “Changes to crates/core or crates/adaptive must run the full language matrix.”

Sources: Coding guidelines, Path instructions

crates/adaptive/tests/unit/acg/stability_internal_tests.rs (1)

81-121: LGTM!

crates/adaptive/tests/unit/types_tests.rs (1)

44-44: LGTM!

Also applies to: 200-208

crates/adaptive/tests/unit/acg/economics_policy_tests.rs (1)

87-87: LGTM!

crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs (1)

84-84: LGTM!

crates/adaptive/tests/unit/cache_diagnostics_tests.rs (1)

85-85: LGTM!

crates/adaptive/tests/unit/intercepts_tests.rs (1)

53-53: LGTM!

crates/adaptive/tests/unit/storage_memory_internal_tests.rs (1)

87-87: LGTM!

crates/adaptive/tests/unit/storage_tests.rs (1)

92-92: LGTM!

Comment thread crates/adaptive/src/acg_profile.rs Outdated
Comment thread crates/adaptive/src/acg/stability.rs
Comment thread crates/adaptive/tests/integration/redis_tests.rs

@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

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

⚠️ Outside diff range comments (1)
crates/adaptive/tests/integration/redis_tests.rs (1)

551-553: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Assert fingerprint equality across the restart.

is_some() would also pass for a stale or changed fingerprint, so this test does not prove that the serialized value survived backend recreation. Capture the pre-restart fingerprint for learning_key and compare it with the reloaded value.

As per path instructions, “Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.”

🤖 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/adaptive/tests/integration/redis_tests.rs` around lines 551 - 553,
Update the restart persistence test around the stability assertions to capture
the pre-restart stable_prefix_fingerprint for learning_key before recreating the
backend, then assert the reloaded fingerprint equals that captured value rather
than only checking is_some(). Preserve the existing observation-count
assertions.

Source: Path instructions

🤖 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.

Outside diff comments:
In `@crates/adaptive/tests/integration/redis_tests.rs`:
- Around line 551-553: Update the restart persistence test around the stability
assertions to capture the pre-restart stable_prefix_fingerprint for learning_key
before recreating the backend, then assert the reloaded fingerprint equals that
captured value rather than only checking is_some(). Preserve the existing
observation-count assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: bd62dbe9-c14b-4043-8324-462a452bb69d

📥 Commits

Reviewing files that changed from the base of the PR and between 6e11d11 and bf70abf.

📒 Files selected for processing (4)
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (14)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
crates/adaptive/**

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep crates/adaptive aligned with the canonical adaptive config schema, built-in section helpers, plugin lifecycle, and validation/report behavior.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg/stability.rs
🔇 Additional comments (4)
crates/adaptive/src/acg_profile.rs (1)

18-19: LGTM!

Also applies to: 33-46, 71-102, 216-224

crates/adaptive/src/acg/stability.rs (1)

42-46: LGTM!

Also applies to: 77-77, 98-118, 121-200

crates/adaptive/tests/integration/redis_tests.rs (1)

518-546: LGTM!

crates/adaptive/tests/unit/acg/stability_internal_tests.rs (1)

81-109: LGTM!

Also applies to: 111-121, 123-135

@teerthsharma
teerthsharma marked this pull request as draft July 20, 2026 15:35
Signed-off-by: teerthsharma <teerths57@Gmail.com>
Signed-off-by: teerthsharma <teerths57@Gmail.com>
Add an interleaving storage backend that yields between the learner's load
and store halves, proving that concurrent runs never pair a stable-prefix
fingerprint with a foreign observation window and that the agent-level seed
adopts exactly one profile's fingerprint rather than blending profiles.

Add coverage for two workflows that share a system prompt and anchor turn:
they collapse into one learning key, and once the stable prefix extends past
the leading scaffold the fingerprint binds to a single complete request so
sibling workflows fail closed.

Rename the learner's grouping variable to learning_key, which is what
derive_acg_learning_key actually returns, to keep it distinct from the
separate diagnostics profile key.

Signed-off-by: teerthsharma <teerths57@Gmail.com>
Add doc comments for the functions this change introduces or reshapes:
the prefix fingerprint helpers, the structured-output scaffold block, the
response-format fingerprint, the key-parts derivation, and the intent bundle
gate. Each records why the rule is conservative, in particular why a prefix
that extends past the leading scaffold binds to the complete source request.

Signed-off-by: teerthsharma <teerths57@Gmail.com>
The restart test read its learning key back out of the hot cache, so it
passed for whichever key process_run happened to write. process_run also
persists the selected profile under the plain agent id for rehydration,
which meant a missing or mis-keyed scaffold record could still satisfy
the assertions.

Assert instead that the surviving key is not the bare agent id and
carries the stable-scaffold seed marker, so the reload proves the
scaffold-specific record survived the backend restart.

Signed-off-by: teerthsharma <teerths57@Gmail.com>
@teerthsharma
teerthsharma force-pushed the fix/acg-stable-scaffold-reuse branch from bf70abf to f5f43fe Compare August 2, 2026 00:45
@github-actions github-actions Bot added size:XL PR is extra large and removed size:L PR is large labels Aug 2, 2026
@teerthsharma
teerthsharma marked this pull request as ready for review August 2, 2026 00:51
@teerthsharma
teerthsharma requested a review from a team as a code owner August 2, 2026 00:51

@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: 5

Caution

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

⚠️ Outside diff range comments (1)
crates/adaptive/src/acg/ir_builder.rs (1)

203-224: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Image parts collapse to empty content in the IR, which weakens the scaffold-only fingerprint.

extract_text here maps ContentPart::ImageUrl and ContentPart::Image to String::new(), and the empty strings are then filtered out. Two System or Developer messages that differ only in image content produce byte-identical PromptBlock::content. profile_prefix_fingerprint binds a prefix that stops inside the scaffold to the prefix content only, so such a request passes the reuse gate against a different learned scaffold. crates/adaptive/src/acg_profile.rs already avoids this by emitting [image:{detail}:{sha256}] in its own extract_text. Align the IR builder with that behavior.

Note also that the two extract_text functions now have the same name, the same input type, and different semantics. Consider sharing one implementation.

🛠️ Proposed fix: keep an image discriminator in the IR text
             .map(|part| match part {
                 ContentPart::Text { text, .. } => text.clone(),
                 ContentPart::Refusal { refusal, .. } => refusal.clone(),
-                ContentPart::ImageUrl { .. } | ContentPart::Image { .. } => String::new(),
-                ContentPart::Audio { .. }
+                ContentPart::ImageUrl { .. }
+                | ContentPart::Image { .. }
+                | ContentPart::Audio { .. }
                 | ContentPart::File { .. }
                 | ContentPart::ToolUse { .. }
                 | ContentPart::ToolResult { .. }
                 | ContentPart::ProviderNative { .. } => {
                     serde_json::to_string(part).unwrap_or_default()
                 }
             })
🤖 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/adaptive/src/acg/ir_builder.rs` around lines 203 - 224, Update the
ir_builder extract_text function to preserve image content distinctions using
the established [image:{detail}:{sha256}] representation from acg_profile’s
extract_text, rather than returning empty strings for ImageUrl and Image parts.
Prefer sharing the existing implementation or helper so both extract_text
functions use identical image semantics and retain scaffold-only fingerprint
differences.
🤖 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 `@crates/adaptive/src/acg_component.rs`:
- Around line 162-182: Update the three build_intent_bundle_skipped emissions
for missing, unavailable, and mismatched stable_prefix_fingerprint in the
surrounding function to include the same agent_id, provider, and
observation_count attribution as the other skip events, plus the learning key
and prefix length. Preserve each existing reason value.

In `@crates/adaptive/src/acg/stability.rs`:
- Around line 98-111: Extract the shared fold-and-max tie-break logic from
analyze_stability and dominant_profile_prefix_fingerprint into one dominant
helper accepting an Iterator<Item = String>. Update both callers to pass their
filtered fingerprints through it, preserving the existing deterministic count
and hash tie-break behavior; keep the distinct unbound and learning-key-bound
fingerprint value spaces unchanged.

In `@crates/adaptive/tests/integration/redis_tests.rs`:
- Around line 532-563: Capture the pre-restart stable prefix fingerprint from
guard.acg_profiles[&learning_key] before dropping the backend, then replace the
post-restart is_some assertion with an exact equality check against that
captured value. Keep the existing observation and stability-count assertions
unchanged.

In `@crates/adaptive/tests/unit/acg_component_tests.rs`:
- Around line 1030-1059: Update the second legacy_stability scenario before the
over-long stable_prefix_length assignment to restore stable_prefix_fingerprint
to Some using the appropriate existing fingerprint value, so build_intent_bundle
reaches the stable_prefix_fingerprint_unavailable branch instead of repeating
the missing-fingerprint case. Keep the first missing-fingerprint assertion
unchanged.

In `@crates/adaptive/tests/unit/acg_learner_tests.rs`:
- Around line 536-544: Update the observation-count assertion in the concurrent
process_run test to verify the safety bound rather than requiring exactly one
surviving observation for alpha_key. Preserve the existing load_observations
flow and fingerprint-reproducibility loop, which should remain the invariant for
deterministic behavior.

---

Outside diff comments:
In `@crates/adaptive/src/acg/ir_builder.rs`:
- Around line 203-224: Update the ir_builder extract_text function to preserve
image content distinctions using the established [image:{detail}:{sha256}]
representation from acg_profile’s extract_text, rather than returning empty
strings for ImageUrl and Image parts. Prefer sharing the existing implementation
or helper so both extract_text functions use identical image semantics and
retain scaffold-only fingerprint differences.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 1a637956-51dd-46d6-8422-b87bc8bb1ad0

📥 Commits

Reviewing files that changed from the base of the PR and between bf70abf and f5f43fe.

📒 Files selected for processing (22)
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/src/acg/stability.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (14)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
crates/adaptive/**

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep crates/adaptive aligned with the canonical adaptive config schema, built-in section helpers, plugin lifecycle, and validation/report behavior.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

**/*.{rs,py,go,js,ts}: When observability configuration or lifecycle is exposed, keep FFI and Python, Go, and Node.js binding-native config objects and subscriber/exporter methods aligned in logical knobs and semantics.
Require every OpenTelemetry endpoint to have a type and nonblank destination; resolve header_env values at activation and reject missing, blank, or duplicate headers.
Concatenate layered ATOF sink, ATIF storage, and OpenTelemetry endpoint lists with higher-precedence entries first.
Preserve correct handling of mark events, start/end events, orphan cases, and span or trajectory fields derived from intended event data.
Run affected Rust tests and just test-rust when event fields change; run just test-python, just test-go, and just test-node when binding-native configuration or lifecycle changes.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
  • crates/adaptive/src/acg/stability.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/adaptive/tests/unit/storage_tests.rs
  • crates/adaptive/tests/unit/runtime_features_tests.rs
  • crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs
  • crates/adaptive/tests/unit/cache_diagnostics_tests.rs
  • crates/adaptive/tests/unit/acg/economics_internal_tests.rs
  • crates/adaptive/tests/unit/intercepts_tests.rs
  • crates/adaptive/tests/unit/acg_profile_tests.rs
  • crates/adaptive/tests/unit/types_tests.rs
  • crates/adaptive/tests/unit/acg/economics_policy_tests.rs
  • crates/adaptive/tests/unit/runtime_tests.rs
  • crates/adaptive/tests/integration/redis_tests.rs
  • crates/adaptive/tests/unit/storage_memory_internal_tests.rs
  • crates/adaptive/tests/unit/acg/ir_builder_tests.rs
  • crates/adaptive/tests/integration/runtime_integration_tests.rs
  • crates/adaptive/tests/unit/acg_learner_tests.rs
  • crates/adaptive/tests/unit/acg/stability_internal_tests.rs
  • crates/adaptive/tests/unit/acg_component_tests.rs
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/adaptive/src/acg_component.rs
  • crates/adaptive/src/acg/ir_builder.rs
  • crates/adaptive/src/acg_profile.rs
  • crates/adaptive/src/acg_learner.rs
  • crates/adaptive/src/acg/stability.rs
🔇 Additional comments (31)
crates/adaptive/src/acg/ir_builder.rs (2)

38-44: LGTM!

Also applies to: 57-78, 91-91, 334-364


142-172: LGTM!

Also applies to: 226-236, 400-405

crates/adaptive/src/acg_profile.rs (3)

18-19: LGTM!

Also applies to: 33-46, 71-75, 91-117, 296-303


133-163: LGTM!

Also applies to: 210-260, 305-330


262-265: 🗄️ Data Integrity & Integration

Resolve the serde_json feature set before relying on this fallback. The manifests contain no explicit preserve_order feature, but a transitive dependency could still enable it. If the resolved feature set includes preserve_order, make the fallback fail closed.

crates/adaptive/tests/unit/acg/ir_builder_tests.rs (1)

201-300: LGTM!

Also applies to: 302-346

crates/adaptive/tests/unit/acg_profile_tests.rs (1)

40-78: LGTM!

Also applies to: 80-149, 233-286, 437-596

crates/adaptive/src/acg/stability.rs (1)

42-46: LGTM!

Also applies to: 133-157, 178-207

crates/adaptive/tests/unit/acg/stability_internal_tests.rs (1)

82-109: LGTM!

Also applies to: 111-121, 123-135

crates/adaptive/tests/unit/acg_learner_tests.rs (2)

233-269: LGTM!

Also applies to: 578-630


393-505: LGTM!

crates/adaptive/tests/unit/runtime_features_tests.rs (1)

89-130: LGTM!

Also applies to: 148-181, 980-1010

crates/adaptive/tests/unit/cache_diagnostics_tests.rs (1)

85-85: LGTM!

Also applies to: 94-95

crates/adaptive/src/acg_component.rs (1)

110-129: LGTM!

Also applies to: 633-659

crates/adaptive/tests/unit/acg_component_tests.rs (2)

50-50: LGTM!

Also applies to: 237-237, 268-268, 293-313, 456-460, 536-540, 586-607, 648-648, 679-683, 739-739, 947-952, 1187-1187, 1242-1242, 1289-1293, 1392-1392, 1433-1437, 1571-1589


817-848: LGTM!

Also applies to: 984-1028, 1062-1133

crates/adaptive/tests/unit/runtime_tests.rs (3)

34-113: LGTM!


394-558: LGTM!


582-637: LGTM!

crates/adaptive/tests/integration/runtime_integration_tests.rs (3)

75-242: LGTM!


517-563: LGTM!


593-602: LGTM!

Also applies to: 717-751, 814-822

crates/adaptive/src/acg_learner.rs (2)

91-120: LGTM!


139-141: LGTM!

crates/adaptive/tests/unit/types_tests.rs (1)

34-47: LGTM!

Also applies to: 176-209

crates/adaptive/tests/unit/acg/economics_internal_tests.rs (1)

118-126: LGTM!

crates/adaptive/tests/unit/acg/economics_policy_tests.rs (1)

73-90: LGTM!

crates/adaptive/tests/unit/acg/multi_breakpoint_tests.rs (1)

72-87: LGTM!

crates/adaptive/tests/unit/intercepts_tests.rs (1)

39-58: LGTM!

crates/adaptive/tests/unit/storage_memory_internal_tests.rs (1)

77-90: LGTM!

crates/adaptive/tests/unit/storage_tests.rs (1)

82-95: LGTM!

Comment on lines +162 to +182
let Some(stored_fingerprint) = stability.stable_prefix_fingerprint.as_ref() else {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({"reason": "stable_prefix_fingerprint_missing"}),
);
return None;
};
let Some(live_fingerprint) = live_fingerprint.as_ref() else {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({"reason": "stable_prefix_fingerprint_unavailable"}),
);
return None;
};
if stored_fingerprint != live_fingerprint {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({"reason": "stable_prefix_fingerprint_mismatch"}),
);
return None;
}

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 | 🔵 Trivial | ⚡ Quick win

Add attribution to the three new skip events.

The other build_intent_bundle_skipped emissions in this function carry agent_id, provider, and observation_count. These three carry only reason. When reuse stops in production, an operator cannot tell which agent or profile was rejected, which is exactly the case these events exist to explain. Include the learning key and the prefix length as well.

🔍 Proposed event payloads
     let Some(stored_fingerprint) = stability.stable_prefix_fingerprint.as_ref() else {
         acg_debug::emit(
             "build_intent_bundle_skipped",
-            json!({"reason": "stable_prefix_fingerprint_missing"}),
+            json!({
+                "reason": "stable_prefix_fingerprint_missing",
+                "agent_id": agent_id,
+                "provider": provider,
+                "learning_key": learning_key,
+                "stable_prefix_length": stability.stable_prefix_length,
+            }),
         );
         return None;
     };
     let Some(live_fingerprint) = live_fingerprint.as_ref() else {
         acg_debug::emit(
             "build_intent_bundle_skipped",
-            json!({"reason": "stable_prefix_fingerprint_unavailable"}),
+            json!({
+                "reason": "stable_prefix_fingerprint_unavailable",
+                "agent_id": agent_id,
+                "provider": provider,
+                "learning_key": learning_key,
+                "stable_prefix_length": stability.stable_prefix_length,
+                "prompt_block_count": prompt_ir.blocks.len(),
+            }),
         );
         return None;
     };
     if stored_fingerprint != live_fingerprint {
         acg_debug::emit(
             "build_intent_bundle_skipped",
-            json!({"reason": "stable_prefix_fingerprint_mismatch"}),
+            json!({
+                "reason": "stable_prefix_fingerprint_mismatch",
+                "agent_id": agent_id,
+                "provider": provider,
+                "learning_key": learning_key,
+                "stable_prefix_length": stability.stable_prefix_length,
+            }),
         );
         return None;
     }
📝 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.

Suggested change
let Some(stored_fingerprint) = stability.stable_prefix_fingerprint.as_ref() else {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({"reason": "stable_prefix_fingerprint_missing"}),
);
return None;
};
let Some(live_fingerprint) = live_fingerprint.as_ref() else {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({"reason": "stable_prefix_fingerprint_unavailable"}),
);
return None;
};
if stored_fingerprint != live_fingerprint {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({"reason": "stable_prefix_fingerprint_mismatch"}),
);
return None;
}
let Some(stored_fingerprint) = stability.stable_prefix_fingerprint.as_ref() else {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({
"reason": "stable_prefix_fingerprint_missing",
"agent_id": agent_id,
"provider": provider,
"learning_key": learning_key,
"stable_prefix_length": stability.stable_prefix_length,
}),
);
return None;
};
let Some(live_fingerprint) = live_fingerprint.as_ref() else {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({
"reason": "stable_prefix_fingerprint_unavailable",
"agent_id": agent_id,
"provider": provider,
"learning_key": learning_key,
"stable_prefix_length": stability.stable_prefix_length,
"prompt_block_count": prompt_ir.blocks.len(),
}),
);
return None;
};
if stored_fingerprint != live_fingerprint {
acg_debug::emit(
"build_intent_bundle_skipped",
json!({
"reason": "stable_prefix_fingerprint_mismatch",
"agent_id": agent_id,
"provider": provider,
"learning_key": learning_key,
"stable_prefix_length": stability.stable_prefix_length,
}),
);
return None;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/adaptive/src/acg_component.rs` around lines 162 - 182, Update the
three build_intent_bundle_skipped emissions for missing, unavailable, and
mismatched stable_prefix_fingerprint in the surrounding function to include the
same agent_id, provider, and observation_count attribution as the other skip
events, plus the learning key and prefix length. Preserve each existing reason
value.

Comment thread crates/adaptive/src/acg/stability.rs Outdated
Comment on lines +532 to +563
let learning_key = {
let guard = hot_cache.read().unwrap();
assert_eq!(guard.acg_profiles.len(), 1);
guard.acg_profiles.keys().next().unwrap().clone()
};
// Both requests carry the same scaffold and differ only in the first user
// task, so the surviving record must be the scaffold-keyed profile rather
// than the plain agent seed `process_run` also writes for rehydration.
assert_ne!(learning_key, agent_id);
assert!(
learning_key.contains("::seed=stable-scaffold::"),
"expected a scaffold-keyed profile, got {learning_key}"
);
drop(backend);

let restarted = RedisBackend::new("redis://127.0.0.1/", prefix)
.await
.unwrap();
let observations = restarted
.load_observations(&learning_key)
.await
.unwrap()
.unwrap();
let stability = restarted
.load_stability(&learning_key)
.await
.unwrap()
.unwrap();

assert_eq!(observations.len(), 2);
assert_eq!(stability.total_observations, 2);
assert!(stability.stable_prefix_fingerprint.is_some());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Strengthen the restart fingerprint assertion to check exact value, not just presence.

Line 563 only asserts stability.stable_prefix_fingerprint.is_some() after the Redis restart. Capture the pre-restart fingerprint from guard.acg_profiles[&learning_key] before drop(backend), and assert exact equality after reload. This confirms the persisted fingerprint round-trips correctly, not just that some value survived.

As per path instructions, "Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests."

🔧 Proposed fix to assert exact fingerprint equality across restart
-    let learning_key = {
-        let guard = hot_cache.read().unwrap();
-        assert_eq!(guard.acg_profiles.len(), 1);
-        guard.acg_profiles.keys().next().unwrap().clone()
-    };
+    let (learning_key, expected_fingerprint) = {
+        let guard = hot_cache.read().unwrap();
+        assert_eq!(guard.acg_profiles.len(), 1);
+        let key = guard.acg_profiles.keys().next().unwrap().clone();
+        let fingerprint = guard.acg_profiles[&key].stable_prefix_fingerprint.clone();
+        (key, fingerprint)
+    };
     // Both requests carry the same scaffold and differ only in the first user
     // task, so the surviving record must be the scaffold-keyed profile rather
     // than the plain agent seed `process_run` also writes for rehydration.
     assert_ne!(learning_key, agent_id);
     assert!(
         learning_key.contains("::seed=stable-scaffold::"),
         "expected a scaffold-keyed profile, got {learning_key}"
     );
     drop(backend);

     let restarted = RedisBackend::new("redis://127.0.0.1/", prefix)
         .await
         .unwrap();
     let observations = restarted
         .load_observations(&learning_key)
         .await
         .unwrap()
         .unwrap();
     let stability = restarted
         .load_stability(&learning_key)
         .await
         .unwrap()
         .unwrap();

     assert_eq!(observations.len(), 2);
     assert_eq!(stability.total_observations, 2);
-    assert!(stability.stable_prefix_fingerprint.is_some());
+    assert!(expected_fingerprint.is_some());
+    assert_eq!(stability.stable_prefix_fingerprint, expected_fingerprint);
 }
📝 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.

Suggested change
let learning_key = {
let guard = hot_cache.read().unwrap();
assert_eq!(guard.acg_profiles.len(), 1);
guard.acg_profiles.keys().next().unwrap().clone()
};
// Both requests carry the same scaffold and differ only in the first user
// task, so the surviving record must be the scaffold-keyed profile rather
// than the plain agent seed `process_run` also writes for rehydration.
assert_ne!(learning_key, agent_id);
assert!(
learning_key.contains("::seed=stable-scaffold::"),
"expected a scaffold-keyed profile, got {learning_key}"
);
drop(backend);
let restarted = RedisBackend::new("redis://127.0.0.1/", prefix)
.await
.unwrap();
let observations = restarted
.load_observations(&learning_key)
.await
.unwrap()
.unwrap();
let stability = restarted
.load_stability(&learning_key)
.await
.unwrap()
.unwrap();
assert_eq!(observations.len(), 2);
assert_eq!(stability.total_observations, 2);
assert!(stability.stable_prefix_fingerprint.is_some());
let (learning_key, expected_fingerprint) = {
let guard = hot_cache.read().unwrap();
assert_eq!(guard.acg_profiles.len(), 1);
let key = guard.acg_profiles.keys().next().unwrap().clone();
let fingerprint = guard.acg_profiles[&key].stable_prefix_fingerprint.clone();
(key, fingerprint)
};
// Both requests carry the same scaffold and differ only in the first user
// task, so the surviving record must be the scaffold-keyed profile rather
// than the plain agent seed `process_run` also writes for rehydration.
assert_ne!(learning_key, agent_id);
assert!(
learning_key.contains("::seed=stable-scaffold::"),
"expected a scaffold-keyed profile, got {learning_key}"
);
drop(backend);
let restarted = RedisBackend::new("redis://127.0.0.1/", prefix)
.await
.unwrap();
let observations = restarted
.load_observations(&learning_key)
.await
.unwrap()
.unwrap();
let stability = restarted
.load_stability(&learning_key)
.await
.unwrap()
.unwrap();
assert_eq!(observations.len(), 2);
assert_eq!(stability.total_observations, 2);
assert!(expected_fingerprint.is_some());
assert_eq!(stability.stable_prefix_fingerprint, expected_fingerprint);
🤖 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/adaptive/tests/integration/redis_tests.rs` around lines 532 - 563,
Capture the pre-restart stable prefix fingerprint from
guard.acg_profiles[&learning_key] before dropping the backend, then replace the
post-restart is_some assertion with an exact equality check against that
captured value. Keep the existing observation and stability-count assertions
unchanged.

Source: Path instructions

Comment on lines +1030 to +1059
let mut legacy_stability = stability;
legacy_stability.stable_prefix_fingerprint = None;
assert!(
build_intent_bundle(
"agent-openai",
"openai",
plugin.as_ref(),
RequestSurface::OpenAIChat,
&request,
&prompt_ir,
&legacy_stability,
MIN_ACG_OBSERVATIONS,
)
.is_none()
);

legacy_stability.stable_prefix_length = prompt_ir.blocks.len() + 1;
assert!(
build_intent_bundle(
"agent-openai",
"openai",
plugin.as_ref(),
RequestSurface::OpenAIChat,
&request,
&prompt_ir,
&legacy_stability,
MIN_ACG_OBSERVATIONS,
)
.is_none()
);

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 | 🟡 Minor | ⚡ Quick win

The last assertion repeats the missing branch instead of covering unavailable.

Line 1031 sets stable_prefix_fingerprint = None, and line 1046 then sets an over-long stable_prefix_length. build_intent_bundle checks the stored fingerprint before the live one, so the final case exits through stable_prefix_fingerprint_missing, exactly like the case above it. The stable_prefix_fingerprint_unavailable path stays uncovered.

Restore a Some fingerprint before setting the over-long prefix length.

💚 Proposed fix
-    legacy_stability.stable_prefix_length = prompt_ir.blocks.len() + 1;
+    // Restore the stored fingerprint so the over-long prefix exercises the
+    // "live fingerprint unavailable" branch rather than the "missing" branch.
+    legacy_stability.stable_prefix_fingerprint = Some("sha256:stored".to_string());
+    legacy_stability.stable_prefix_length = prompt_ir.blocks.len() + 1;
📝 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.

Suggested change
let mut legacy_stability = stability;
legacy_stability.stable_prefix_fingerprint = None;
assert!(
build_intent_bundle(
"agent-openai",
"openai",
plugin.as_ref(),
RequestSurface::OpenAIChat,
&request,
&prompt_ir,
&legacy_stability,
MIN_ACG_OBSERVATIONS,
)
.is_none()
);
legacy_stability.stable_prefix_length = prompt_ir.blocks.len() + 1;
assert!(
build_intent_bundle(
"agent-openai",
"openai",
plugin.as_ref(),
RequestSurface::OpenAIChat,
&request,
&prompt_ir,
&legacy_stability,
MIN_ACG_OBSERVATIONS,
)
.is_none()
);
let mut legacy_stability = stability;
legacy_stability.stable_prefix_fingerprint = None;
assert!(
build_intent_bundle(
"agent-openai",
"openai",
plugin.as_ref(),
RequestSurface::OpenAIChat,
&request,
&prompt_ir,
&legacy_stability,
MIN_ACG_OBSERVATIONS,
)
.is_none()
);
// Restore the stored fingerprint so the over-long prefix exercises
// the "live fingerprint unavailable" branch rather than the "missing" branch.
legacy_stability.stable_prefix_fingerprint = Some("sha256:stored".to_string());
legacy_stability.stable_prefix_length = prompt_ir.blocks.len() + 1;
assert!(
build_intent_bundle(
"agent-openai",
"openai",
plugin.as_ref(),
RequestSurface::OpenAIChat,
&request,
&prompt_ir,
&legacy_stability,
MIN_ACG_OBSERVATIONS,
)
.is_none()
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/adaptive/tests/unit/acg_component_tests.rs` around lines 1030 - 1059,
Update the second legacy_stability scenario before the over-long
stable_prefix_length assignment to restore stable_prefix_fingerprint to Some
using the appropriate existing fingerprint value, so build_intent_bundle reaches
the stable_prefix_fingerprint_unavailable branch instead of repeating the
missing-fingerprint case. Keep the first missing-fingerprint assertion
unchanged.

Comment on lines +536 to +544
assert_eq!(
backend
.load_observations(&alpha_key)
.await
.unwrap()
.unwrap()
.len(),
1,
);

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 | 🟡 Minor | ⚡ Quick win

Assert the safety bound, not the exact interleaving outcome.

This asserts that exactly one observation survives for alpha_key after three concurrent process_run futures. That value depends on the current poll order of tokio::join! and on the exact placement of the yield_now calls in InterleavingBackend. Both are implementation details, not contract. The test can flake or fail on an unrelated refactor even though the property the comment describes still holds.

Assert the bound instead, and keep the fingerprint-reproducibility loop below as the real invariant.

💚 Proposed assertion change
-    assert_eq!(
-        backend
-            .load_observations(&alpha_key)
-            .await
-            .unwrap()
-            .unwrap()
-            .len(),
-        1,
-    );
+    let alpha_window = backend
+        .load_observations(&alpha_key)
+        .await
+        .unwrap()
+        .unwrap()
+        .len();
+    assert!(
+        (1..=2).contains(&alpha_window),
+        "interleaved runs may drop an observation, but never all of them: got {alpha_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.

Suggested change
assert_eq!(
backend
.load_observations(&alpha_key)
.await
.unwrap()
.unwrap()
.len(),
1,
);
let alpha_window = backend
.load_observations(&alpha_key)
.await
.unwrap()
.unwrap()
.len();
assert!(
(1..=2).contains(&alpha_window),
"interleaved runs may drop an observation, but never all of them: got {alpha_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 `@crates/adaptive/tests/unit/acg_learner_tests.rs` around lines 536 - 544,
Update the observation-count assertion in the concurrent process_run test to
verify the safety bound rather than requiring exactly one surviving observation
for alpha_key. Preserve the existing load_observations flow and
fingerprint-reproducibility loop, which should remain the invariant for
deterministic behavior.

The stable prefix is derived from span scores sorted on the first-seen
sequence index alone. That key is not injective over the span set: span
ids carry the role and the tool suffix, so assistant-1-search and
assistant-1-fetch are distinct spans sharing index 1, and the index is a
minimum across observations, which collides further. A stable sort on
that key leaves tied spans in HashMap iteration order, which is seeded
per process, so the stable prefix length and its fingerprint varied
between runs on identical input.

Over 20 processes with one contested turn position and four tool spans
at one index, the unfixed comparator produced 20 distinct span orders,
2 distinct prefix lengths, and 2 distinct fingerprints. A profile learned
in one process therefore failed the reuse gate in another.

Sort by (sequence index, stability rank, span id) instead. Span ids are
unique within an analysis, so the key is injective and a total order over
a finite set admits exactly one sorted sequence. The same 20 processes
now agree on all three. Ranking the least stable span first makes the
prefix stop before a contested position rather than extend across it,
which matches the fail-closed rule the reuse gate already applies.

Fold the duplicated dominant-fingerprint tie-break into one helper so the
rule that decides reuse determinism exists in a single place.

Signed-off-by: teerthsharma <teerths57@Gmail.com>
The stable prefix was the leading run of per-span scores above the stable
threshold. That reads a span-level statistic, presence rate times dominant
content fraction, and then re-sequences those scores, so the answer depended
on the order the span map was enumerated in and diverged from the exact
prefix a provider cache actually keys on.

Derive it from the observations instead: descend the prefix tree of block
sequences while one child still holds the configured share of the window.
Descent also requires a strict majority, and two disjoint children cannot
both hold one, so the dominant child is unique wherever it exists and no
tie-break is reachable. Where no child dominates, the prefix stops.

The rule is the one the review asked for, the same exact prefix observed for
N samples, and it recovers reuse the span rule discarded. On a 20-observation
window whose first turn varies in 1 of 20 runs, the span rule reports a
1-block prefix while 19 of 20 observations share an exact 6-block prefix; the
outlier still fails the fingerprint gate, so the wider prefix stays exactly
validated. Across 20 processes the rule returns one length and one
fingerprint.

Remove find_stable_prefix_length, whose only caller this replaces and which
nothing else in the workspace uses. Fold the block identity shared by the
length rule and the fingerprint into one definition so the two cannot drift.
Record that prefix economics, not the length rule, is what the stability rank
in the score ordering protects.

Signed-off-by: teerthsharma <teerths57@Gmail.com>
Record the quantity the ordering and prefix rules exist to hold at 1:
over N processes producing outcomes with multiplicities c_i, the
agreement rate A = sum c_i (c_i - 1) / (N (N - 1)) is the probability two
independent processes agree, and so the probability that a profile
persisted by one satisfies the reuse gate in another.

Tighten the surrounding doc comments and drop the unreachable trailing
expression from the descent loop.

Signed-off-by: teerthsharma <teerths57@Gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug issue describes bug; PR fixes bug lang:rust PR changes/introduces Rust code size:XL PR is extra large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant