Skip to content

fix active channel extension search guidance - #6653

Merged
BenKurrek merged 2 commits into
mainfrom
codex/fix-active-channel-guidance
Jul 24, 2026
Merged

BenKurrek merged 2 commits into
mainfrom
codex/fix-active-channel-guidance

Conversation

@BenKurrek

Copy link
Copy Markdown
Collaborator

Summary

  • classify only setup_needed external-channel search results as requiring connection setup
  • route active external-channel results through the existing ready guidance
  • add a caller-level regression proving active results never instruct the model to call builtin.extension_install

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

None.

Validation

  • cargo fmt --all -- --check
  • cargo clippy --all --benches --tests --examples --all-features -- -D warnings — owning-crate all-targets/all-features clippy passed; the broader workspace run was stopped after the user requested publication
  • cargo build — covered by the owning-crate test/clippy builds
  • Relevant tests pass: active/setup-needed external-channel guidance regressions; isolated rerun of the one load-sensitive timeout from the full suite
  • cargo test --features integration if database-backed or integration behavior changed — not applicable: no database or integration behavior changed
  • Manual testing — not applicable: deterministic lifecycle response classification is covered through the real lifecycle facade
  • If a coding agent was used and supports it, review-pr or pr-shepherd --fix was run before requesting review — not run before draft publication

Additional evidence:

  • Red: active_external_channel_search_result_gets_ready_guidance failed against the old classifier with the contradictory “personal setup is incomplete” response.
  • Green: cargo test -p ironclaw_reborn_composition external_channel_search_result -- --nocapture — 2 passed.
  • cargo clippy -p ironclaw_reborn_composition --all-targets --all-features -- -D warnings — passed.
  • scripts/pre-commit-safety.sh — passed.
  • Full owning-crate run: 1,411/1,412 unit tests passed; multi_tool_call_response_survives_surface_change_mid_register hit its unrelated 10-second timeout under suite load, then passed in isolation in 2.24 seconds. All integration targets passed.
  • Current main has a pre-existing test-build mismatch in runtime.rs (channel_host_assembly vs _channel_host_assembly). Test/clippy evidence above used a temporary local one-line correction that is not included in this PR.

Test Strategy

User behavior:

An active external channel is reported as ready and never receives setup-needed or reinstall guidance.

Risk areas:

  • Model behavior
  • Browser
  • Side effect
  • Persistence
  • Security or permissions
  • External provider
  • Cross-component behavior

Tests added or updated:

  • Unit or contract: updated the lifecycle-facade regression to assert active-channel ready guidance and reject setup/install instructions; retained setup-needed channel coverage.
  • Reborn integration: Not applicable: the behavior is deterministic response classification exercised through the real lifecycle facade.
  • Recorded fixture: Not applicable: no model selection or request-shape behavior changed.
  • Browser E2E: Not applicable: no browser behavior changed.
  • Backend or runtime: Not applicable: no backend/runtime behavior changed.
  • Live canary: Not applicable: no live provider behavior is required to verify the classifier.

What the tests prove:

The old classifier reproduces the contradiction, the new classifier preserves setup guidance for setup_needed, and an active channel returns ready guidance without builtin.extension_install.

Commands run:

  • cargo test -p ironclaw_reborn_composition active_external_channel_search_result_gets_ready_guidance -- --nocapture
  • cargo test -p ironclaw_reborn_composition external_channel_search_result -- --nocapture
  • cargo test -p ironclaw_reborn_composition --no-fail-fast
  • cargo test -p ironclaw_reborn_composition multi_tool_call_response_survives_surface_change_mid_register -- --nocapture
  • cargo clippy -p ironclaw_reborn_composition --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • git diff --check
  • scripts/pre-commit-safety.sh

Security Impact

None. This changes only model-visible lifecycle guidance selection.

Reborn Trust-Boundary Checklist

N/A: no authority, trust-bearing types, untrusted prompt content, serialization, queues, errors, or runtime boundaries changed.

Database Impact

None.

Blast Radius

Limited to the top-level message attached to extension-search responses containing active or setup-needed external channels. Installation state and lifecycle transitions are unchanged.

Rollback Plan

Revert commit bd25dc0bb to restore the previous classifier and guidance behavior.

Review Follow-Through

The PR is intentionally limited to the guidance bug. Telegram /start interception and message formatting are excluded.


Review track: B (product behavior bug fix)

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

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

@ironloopai

ironloopai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

🔎 IronLoop Review Status

Head: 372ff42153f209c7f932b135f7eef22392a45fdc
Result: One or more review results were superseded by a newer PR head.
Next: Run @ironloopai review on the latest PR head.
Updated: 2026-07-24T17:05:46.553Z

Current reviewers:

Reviewer State Verdict Findings Last update
ironloop/common-reviewer (reviewer) Superseded N/A N/A 2026-07-24T17:05:46.537Z
Reviewer summaries
Reviewer Detail
ironloop/common-reviewer (reviewer) Superseded by a newer PR head. New head: 372ff42. Previous verdict: Changes requested.
Recent activity
Time Reviewer State Detail
2026-07-24T16:29:19.921Z ironloop/common-reviewer (reviewer) Queued Accepted review request for head bd25dc0.
2026-07-24T16:29:19.921Z ironloop/common-reviewer (reviewer) Queued Waiting for this reviewer lane to become available.
2026-07-24T16:29:20.010Z ironloop/common-reviewer (reviewer) Started Reviewer worker started.
2026-07-24T16:29:23.214Z ironloop/common-reviewer (reviewer) Workspace ready Prepared isolated checkout (merge_ref) at 817e61f.
2026-07-24T16:31:42.850Z ironloop/common-reviewer (reviewer) Result captured Changes requested; 1 blocking finding.
2026-07-24T16:31:42.850Z ironloop/common-reviewer (reviewer) Completed Review completed and terminal status was persisted.
2026-07-24T16:35:13.866Z ironloop/common-reviewer (reviewer) Deduplicated Repeated trigger reused the existing reviewer job.
2026-07-24T17:05:46.537Z ironloop/common-reviewer (reviewer) Superseded A newer PR head replaced this review (372ff42).
Available commands
  • @ironloopai help
  • @ironloopai agents
  • @ironloopai review
  • @ironloopai review --agent <agent>
Run metadata

Admission: webhook accepted the request and IronLoop persisted reviewer state before this projection.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved search guidance for external channels that still require setup.
    • Updated ready-state guidance so active external channels are clearly identified as ready.
    • Prevented setup-incomplete messaging and unnecessary installation prompts for already active channels.

Walkthrough

Search guidance now distinguishes setup-needed external channels from active ready results. Predicate logic, routing, and related tests are updated in extension_lifecycle.rs.

Changes

External channel guidance

Layer / File(s) Summary
Search result classification
crates/ironclaw_reborn_composition/src/extension_host/extension_lifecycle.rs
The ready-result predicate now targets active results, and a helper identifies setup-needed external channel results.
Guidance routing and validation
crates/ironclaw_reborn_composition/src/extension_host/extension_lifecycle.rs
Search routing uses the setup-needed predicate; tests verify setup-incomplete guidance versus ready guidance and exclude builtin.extension_install for active channels.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • nearai/ironclaw#4996: Updates extension search result phases and onboarding suppression used by search guidance.
  • nearai/ironclaw#5034: Adjusts extension search predicates and messaging for ready versus setup-needed results.

Suggested reviewers: ilblackdragon

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is directly about the guidance fix, though it does not use the preferred Conventional Commits format.
Description check ✅ Passed The description matches the template and covers summary, change type, validation, test strategy, impact, rollback, and review follow-through.
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.

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

❤️ Share

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

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6653 July 24, 2026 16:29 Destroyed
@github-actions github-actions Bot added size: S 10-49 changed lines risk: low Changes to docs, tests, or low-risk modules contributor: core 20+ merged PRs labels Jul 24, 2026

@ironloopai ironloopai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❌ IronLoop Review: reviewer

Review at a glance

Verdict Blocking Notes Inline Head
❌ Changes requested 1 0 1 bd25dc0bb3c8

Head: bd25dc0bb3c85967f4c23f0e3e913cc169a29682
Next: Fix the blocking findings, push the PR branch, then re-run this reviewer.

Run details

Status: Current
Needs human: no
Needs validation: no

Summary

The active-channel regression reaches the lifecycle facade, but the retained setup-needed path is only helper-tested and does not verify the emitted guidance branch.

Findings

Blocking: 1 / Notes: 0

Blocking findings

1. ❌ [MEDIUM] Exercise setup-needed channel guidance through the facade

Location: crates/ironclaw_reborn_composition/src/extension_host/extension_lifecycle.rs:3387
This test only invokes the classifier with a fabricated payload. It does not execute ExtensionManagementPort::search, which is where the classifier selects and attaches the model-visible setup/install message. Add a caller-level regression with an external channel that remains SetupNeeded, then assert its search response retains the incomplete-setup and builtin.extension_install guidance.

Developer follow-up

After fixing this feedback:

  1. Push the fix to this PR branch.
  2. Re-run this reviewer with @ironloopai review --agent reviewer if you only changed this reviewer's findings.
  3. Re-run all reviewers with @ironloopai review when the fix may affect multiple areas.


#[test]
fn installed_external_channel_search_result_gets_activation_guidance() {
fn setup_needed_external_channel_search_result_gets_activation_guidance() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This only tests the classifier, not the search branch that emits the model-visible setup/install guidance. Please add a facade-level SetupNeeded external-channel search regression asserting the incomplete-setup and builtin.extension_install message.

@BenKurrek
BenKurrek marked this pull request as ready for review July 24, 2026 16:35
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

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

@coderabbitai coderabbitai Bot 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: 1

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

Inline comments:
In
`@crates/ironclaw_reborn_composition/src/extension_host/extension_lifecycle.rs`:
- Around line 3070-3083: Update
extension_search_has_setup_needed_external_channel_result so it only matches
SetupNeeded channel extensions whose credential_requirements are empty; preserve
the existing false result for non-ExtensionSearch payloads and leave
credential-gated extensions out of the channel-specific guidance.
🪄 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: Pro Plus

Run ID: d7751aa2-ab3c-4337-90e4-30a9b77367fb

📥 Commits

Reviewing files that changed from the base of the PR and between 073ded0 and bd25dc0.

📒 Files selected for processing (1)
  • crates/ironclaw_reborn_composition/src/extension_host/extension_lifecycle.rs

Comment on lines +3070 to 3083
fn extension_search_has_setup_needed_external_channel_result(
payload: Option<&LifecycleProductPayload>,
) -> bool {
let Some(LifecycleProductPayload::ExtensionSearch { extensions, .. }) = payload else {
return false;
};
extensions.iter().any(|extension| {
matches!(
extension.installation_phase,
Some(LifecyclePublicState::SetupNeeded | LifecyclePublicState::Active)
) && extension
.summary
.surface_kinds
.contains(&CapabilitySurfaceKind::Channel)
extension.installation_phase == Some(LifecyclePublicState::SetupNeeded)
&& extension
.summary
.surface_kinds
.contains(&CapabilitySurfaceKind::Channel)
})
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the credential-requirements guard.

This predicate now classifies every SetupNeeded channel as personal connection setup, including results with unresolved credential_requirements. Restore the empty-requirements check so credential-gated extensions do not receive the channel-specific builtin.extension_install guidance.

Proposed fix
     extensions.iter().any(|extension| {
         extension.installation_phase == Some(LifecyclePublicState::SetupNeeded)
+            && extension.summary.credential_requirements.is_empty()
             && extension
                 .summary
                 .surface_kinds

Based on the supplied lifecycle guidance contract, this branch must remain limited to setup-needed channels without package credential requirements.

📝 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
fn extension_search_has_setup_needed_external_channel_result(
payload: Option<&LifecycleProductPayload>,
) -> bool {
let Some(LifecycleProductPayload::ExtensionSearch { extensions, .. }) = payload else {
return false;
};
extensions.iter().any(|extension| {
matches!(
extension.installation_phase,
Some(LifecyclePublicState::SetupNeeded | LifecyclePublicState::Active)
) && extension
.summary
.surface_kinds
.contains(&CapabilitySurfaceKind::Channel)
extension.installation_phase == Some(LifecyclePublicState::SetupNeeded)
&& extension
.summary
.surface_kinds
.contains(&CapabilitySurfaceKind::Channel)
})
}
fn extension_search_has_setup_needed_external_channel_result(
payload: Option<&LifecycleProductPayload>,
) -> bool {
let Some(LifecycleProductPayload::ExtensionSearch { extensions, .. }) = payload else {
return false;
};
extensions.iter().any(|extension| {
extension.installation_phase == Some(LifecyclePublicState::SetupNeeded)
&& extension.summary.credential_requirements.is_empty()
&& extension
.summary
.surface_kinds
.contains(&CapabilitySurfaceKind::Channel)
})
}
🤖 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/ironclaw_reborn_composition/src/extension_host/extension_lifecycle.rs`
around lines 3070 - 3083, Update
extension_search_has_setup_needed_external_channel_result so it only matches
SetupNeeded channel extensions whose credential_requirements are empty; preserve
the existing false result for non-ExtensionSearch payloads and leave
credential-gated extensions out of the channel-specific guidance.

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6653 July 24, 2026 17:05 Destroyed
@railway-app

railway-app Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the ironclaw-pr-6653 environment in ironclaw-ci-preview

Service Status Web Updated (UTC)
ironclaw ✅ Success (View Logs) Web Jul 24, 2026 at 5:20 pm

@BenKurrek
BenKurrek merged commit e3698db into main Jul 24, 2026
60 of 62 checks passed
@BenKurrek
BenKurrek deleted the codex/fix-active-channel-guidance branch July 24, 2026 18:20

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-6653 — 372ff421 Deployed Jul 24, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: low Changes to docs, tests, or low-risk modules size: S 10-49 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant