Skip to content

test(reborn): composition test-support accessors for WebUI approval/auth interaction services - #5654

Merged
henrypark133 merged 4 commits into
mainfrom
w5-webui-api2-enabler
Jul 6, 2026
Merged

henrypark133 merged 4 commits into
mainfrom
w5-webui-api2-enabler

Conversation

@henrypark133

Copy link
Copy Markdown
Collaborator

Summary

Enabler for the W5-WEBUI-API-2 coverage lane (mid-gate credential refresh scenarios over BOTH approval and auth gate kinds — the #5174 bug class). The integration harness builds its runtime via build_default_planned_runtime and never constructs composition's real interaction services, so gate-dispatch paths are unreachable at the integration tier by construction. This PR adds the two accessors that close that gap; the test lane consuming them follows in a separate PR.

⚠️ Production-crate touch (independently droppable)

This PR touches crates/ironclaw_reborn_composition — deliberately minimal and inert in production builds:

  • New file src/runtime/test_support.rs (~104 lines) declared via a 3-line #[cfg(feature = "test-support")] #[path = ...] mod test_support; in runtime.rs, following the existing #[path = "runtime/tests/*.rs"] submodule convention in the same file. runtime.rs itself grows by 3 lines.
  • Two accessors on RebornServices: local_dev_approval_interaction_service_for_test and local_dev_auth_interaction_service_for_test, matching the existing local_dev_*_for_test pattern. Both take turn_coordinator as an explicit parameter because harness callers build their planned runtime independently of build_reborn_runtime, so self's coordinator would be a different instance.
  • Zero production-behavior change: every test-support edge to this crate in the workspace is under [dev-dependencies] (root, crate-self, reborn CLI). Verified by building the crate with and without the feature and grepping the rlib for the accessor symbols: 0 occurrences without, 8 with.
  • One documented divergence from the production approval recipe: the optional approval_audit_sink (defaults None, audit-recording only) is omitted; noted in the accessor doc comment as a drift guard.

If this touch is unwanted, the single commit drops cleanly without affecting sibling W5 lanes.

Test plan

  • New smoke test local_dev_test_support_interaction_service_accessors_build_real_services extends the existing tests/runtime.rs suite: builds a live local-dev runtime, calls both accessors with the runtime's own coordinator, asserts each answers Ok with an empty pending list — discriminating vs the harness's Rejecting*/Unavailable* stubs, which return errors.
  • Mutation-verified both accessors (forced None return / dropped product_auth wiring → RED with the expected panics; reverted → GREEN).
  • cargo test -p ironclaw_reborn_composition --test runtime --features test-support → 9 passed
  • cargo clippy --all --benches --tests --examples --all-features → zero warnings; workspace cargo build clean

🤖 Generated with Claude Code

…uth interaction services

Adds `RebornServices::local_dev_approval_interaction_service_for_test` /
`local_dev_auth_interaction_service_for_test`, unblocking W5-WEBUI-API-2
(RESOLVE_GATE coverage for both approval and auth gate kinds) — the
#5174 bug class. A harness that builds its own planned runtime
directly (e.g. via `build_default_planned_runtime`, bypassing
`build_reborn_runtime`) previously had no way to get a real
`DefaultApprovalInteractionService` / auth-interaction-service pair,
only the fail-closed `Rejecting*`/`Unavailable*` fallbacks.

Production-crate touch: `crates/ironclaw_reborn_composition` gains a
new `runtime/test_support.rs` file (the two accessors, ~75 lines) plus
a 3-line `#[cfg(feature = "test-support")] #[path = "runtime/test_support.rs"]
mod test_support;` in `runtime.rs`. Both the module declaration and
every method inside are gated behind `#[cfg(feature = "test-support")]`
(off by default; confirmed via rlib symbol diff that the module
compiles to zero bytes without the feature). The accessors live in a
`runtime`-tree submodule rather than `factory.rs` because the recipe
they mirror depends on five module-private types only reachable from
code inside `crate::runtime` (Rust's private-item visibility extends
to descendant modules, not just the defining file) — and it's a new
file rather than inlined into the 10k+-line `runtime.rs` for the same
reason this crate already splits its own unit tests into
`runtime/tests/*.rs` submodules. Zero behavior change: every call
reuses the exact production constructors
(`DefaultApprovalInteractionService::new`, `ApprovalResolverPort::new`,
`LocalDevApprovalLeaseTermsProvider::new`,
`build_webui_auth_interaction_service`) with the exact arguments the
production `build_reborn_runtime` recipe already assembles.

`turn_coordinator` is an explicit `Arc<dyn TurnCoordinator>` parameter,
not `self.turn_coordinator`: a `RebornServices` built by
`build_reborn_services` alone carries a different `TurnCoordinator`
instance than a caller-built planned runtime (e.g.
`RebornIntegrationGroup`'s own coordinator) drives its turns through.

Exercised by a new smoke test in
`crates/ironclaw_reborn_composition/tests/runtime.rs`
(`local_dev_test_support_interaction_service_accessors_build_real_services`)
that builds a live local-dev runtime, calls both accessors with the
runtime's own coordinator, and asserts each returns a real, working
service (`Ok` with an empty pending list) rather than a fail-closed
fallback — mutation-verified by temporarily forcing each accessor to
its fail-closed path and confirming the test goes red, then reverting.
The actual RESOLVE_GATE test scenarios these accessors unblock are
W5-WEBUI-API-2's own follow-on PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 5, 2026 04:16

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added the scope: docs Documentation label Jul 5, 2026
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5654 July 5, 2026 04:16 Destroyed
@github-actions github-actions Bot added size: M 50-199 changed lines risk: low Changes to docs, tests, or low-risk modules contributor: core 20+ merged PRs labels Jul 5, 2026
@coderabbitai

coderabbitai Bot commented Jul 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added feature-gated, test-only helpers to create local-dev approval and auth interaction services from runtime state.
    • Local-dev approval-service construction was consolidated to a shared helper.
  • Tests
    • Added Tokio smoke tests covering local-dev pending listing with real (non-fallback) services.
    • Added a scenario that verifies turn resumption is triggered exactly once through a provided coordinator.
  • Documentation
    • Expanded integration testing notes to document the new test-support accessors, including their None behavior when local-dev runtime is unavailable and auth fallback conditions.

Walkthrough

Adds a feature-gated test_support module for local-dev RebornServices accessors, extracts shared approval-service wiring into a helper, and adds integration coverage plus CLAUDE.md updates for the new test-only entrypoints.

Changes

Local-dev test-support accessors

Layer / File(s) Summary
Module registration and shared builder
crates/ironclaw_reborn_composition/src/runtime.rs
Registers test_support behind test-support, adds build_local_dev_approval_interaction_service, and routes build_reborn_runtime through it.
Test-support accessors
crates/ironclaw_reborn_composition/src/runtime/test_support.rs
Adds local_dev_approval_interaction_service_for_test and local_dev_auth_interaction_service_for_test on RebornServices, both gated behind test-support and both returning no service when local_runtime is absent.
Smoke test and documentation
crates/ironclaw_reborn_composition/tests/runtime.rs, tests/integration/CLAUDE.md
Adds runtime tests for the optional accessors and supplied coordinator behavior, plus CLAUDE.md coverage for the new test-support APIs.

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

Sequence Diagram(s)

sequenceDiagram
  participant Test
  participant RebornServices
  participant LocalDevRuntime
  participant DefaultApprovalInteractionService
  participant WebUIAuthFactory

  Test->>RebornServices: local_dev_approval_interaction_service_for_test(turn_coordinator)
  RebornServices->>LocalDevRuntime: build local-dev policy + read model
  RebornServices->>DefaultApprovalInteractionService: construct approval service
  RebornServices-->>Test: Ok(Some(...))

  Test->>RebornServices: local_dev_auth_interaction_service_for_test(turn_coordinator)
  RebornServices->>LocalDevRuntime: read turn state
  RebornServices->>WebUIAuthFactory: build_webui_auth_interaction_service
  RebornServices-->>Test: Some(...)

  Test->>DefaultApprovalInteractionService: resolve approval gate
  DefaultApprovalInteractionService->>RebornServices: use supplied turn_coordinator
  RebornServices-->>Test: resume_turn observed once
Loading

Possibly related PRs

  • nearai/ironclaw#5309: Touches the same local-dev approval interaction-service wiring in crates/ironclaw_reborn_composition/src/runtime.rs, specifically the persistent grantee/resolver path.

Suggested reviewers: ilblackdragon, think-in-universe

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has a solid Summary/Test plan, but most required template sections are missing or unfilled. Add the missing template sections: Change Type, Linked Issue, Security Impact, Reborn Trust-Boundary Checklist, Database Impact, Blast Radius, Rollback Plan, Review Follow-Through, and Review track.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title follows Conventional Commits style and accurately names the new test-support accessors.
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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces test-support accessors on RebornServices to build real, working instances of DefaultApprovalInteractionService and AuthInteractionService for local-dev testing, along with a smoke test to verify their construction and documentation in CLAUDE.md. The review feedback suggests replacing silent fallbacks like .ok()? with explicit .expect(...) calls within these test-support methods to ensure setup failures are reported with clear context rather than silently returning None.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

turn_coordinator: Arc<dyn TurnCoordinator>,
) -> Option<Arc<dyn ApprovalInteractionService>> {
let local_runtime = self.local_runtime.as_ref()?;
let local_dev_capability_policy = Arc::new(local_dev_capability_policy().ok()?);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

In Rust tests, prefer using .expect() with a descriptive message instead of fallbacks like .ok()? or .unwrap() to ensure that setup failures are explicitly reported with clear context, rather than silently returning None and causing downstream test failures or unexpected behavior.

Suggested change
let local_dev_capability_policy = Arc::new(local_dev_capability_policy().ok()?);
let local_dev_capability_policy = Arc::new(
local_dev_capability_policy()
.expect("failed to resolve local-dev capability policy in test accessor")
);
References
  1. In Rust tests, prefer using .expect() with a descriptive message instead of .unwrap() or fallbacks like unwrap_or_else() to ensure that failures are explicitly reported with clear context.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Superseded in 0f4b69f by a broader fix: rather than .expect() (which would only turn a silent None into a test panic), the fallible construction now propagates via Result<Option<...>, RebornRuntimeError>, matching how build_reborn_runtime itself handles this error.

Comment on lines +74 to +79
.with_persistent_grantee_resolver(Arc::new(
RegistryPersistentApprovalGranteeResolver::new(Arc::clone(
&local_runtime.extension_registry,
))
.ok()?,
))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

In Rust tests, prefer using .expect() with a descriptive message instead of fallbacks like .ok()? or .unwrap() to ensure that setup failures are explicitly reported with clear context, rather than silently returning None and causing downstream test failures or unexpected behavior.

Suggested change
.with_persistent_grantee_resolver(Arc::new(
RegistryPersistentApprovalGranteeResolver::new(Arc::clone(
&local_runtime.extension_registry,
))
.ok()?,
))
.with_persistent_grantee_resolver(Arc::new(
RegistryPersistentApprovalGranteeResolver::new(Arc::clone(
&local_runtime.extension_registry,
))
.expect("failed to build persistent grantee resolver in test accessor")
))
References
  1. In Rust tests, prefer using .expect() with a descriptive message instead of .unwrap() or fallbacks like unwrap_or_else() to ensure that failures are explicitly reported with clear context.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Same as the sibling comment on line 24 — superseded in 0f4b69f by propagating via Result<Option<...>, RebornRuntimeError> instead of .expect(), since the grantee-resolver construction now lives inside the shared build_local_dev_approval_interaction_service helper.

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

🤖 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/runtime/test_support.rs`:
- Around line 39-82: The test-only accessor in
local_dev_approval_interaction_service_for_test duplicates the approval-service
wiring from the production runtime path, which risks drift. Extract the shared
construction recipe for DefaultApprovalInteractionService and its attached
lease-terms provider, read model, resolver, persistent policy/grantee stores,
and tool override store into a private helper shared by
build_reborn_runtime/local_runtime_parts and this test-support method. Keep the
helper in crate::runtime so both production and test wiring use the same symbols
and stay identical.
- Around line 39-82: The `local_dev_approval_interaction_service_for_test`
helper is collapsing construction failures into `None` via `.ok()?`, which hides
real errors from `local_dev_capability_policy()` and
`RegistryPersistentApprovalGranteeResolver::new`. Change this path to surface
failures explicitly, ideally by returning a `Result` with context instead of
`Option`, so callers can distinguish missing `local_runtime` from
policy/resolver initialization errors. Keep the fix localized around
`local_dev_approval_interaction_service_for_test` and the
`ApprovalInteractionService` assembly chain.
🪄 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: 001252ac-6769-44ed-af15-9abd4a15b5eb

📥 Commits

Reviewing files that changed from the base of the PR and between 85c02c2 and e8edfed.

📒 Files selected for processing (4)
  • crates/ironclaw_reborn_composition/src/runtime.rs
  • crates/ironclaw_reborn_composition/src/runtime/test_support.rs
  • crates/ironclaw_reborn_composition/tests/runtime.rs
  • tests/integration/CLAUDE.md

Comment thread crates/ironclaw_reborn_composition/src/runtime/test_support.rs
@github-actions

github-actions Bot commented Jul 5, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ 9 Reborn crate(s) have 0 int-tier coverage (target: 0) — ironclaw_embeddings, ironclaw_gateway, ironclaw_hooks, ironclaw_oauth, ironclaw_process_sandbox, ironclaw_prompt_envelope, ironclaw_scripts, ironclaw_skill_learning, ironclaw_tui

Reborn integration-tier coverage

Line coverage (Reborn crates): 28.54% — 49278 / 172648 lines

Per-crate breakdown (62 crates, lowest-covered first)
Crate Line % Covered / Total
ironclaw_embeddings 0% 0 / 337
ironclaw_gateway 0% 0 / 283
ironclaw_hooks 0% 0 / 4468
ironclaw_oauth 0% 0 / 155
ironclaw_process_sandbox 0% 0 / 795
ironclaw_prompt_envelope 0% 0 / 88
ironclaw_scripts 0% 0 / 347
ironclaw_skill_learning 0% 0 / 61
ironclaw_tui 0% 0 / 4776
ironclaw_outbound 0.22% 3 / 1339
ironclaw_event_projections 0.4% 6 / 1489
ironclaw_reborn_event_store 0.66% 6 / 906
ironclaw_reborn_config 1.36% 15 / 1101
ironclaw_llm 3.62% 437 / 12075
ironclaw_event_streams 3.87% 40 / 1034
ironclaw_product_adapter_registry 5.38% 25 / 465
ironclaw_extractors 6.18% 26 / 421
ironclaw_wasm_sandbox_core 7.37% 7 / 95
ironclaw_product_workflow 7.97% 768 / 9635
ironclaw_webui_v2 8.5% 228 / 2683
ironclaw_processes 8.61% 98 / 1138
ironclaw_common 10.22% 74 / 724
ironclaw_events 12.45% 143 / 1149
ironclaw_product_adapters 12.53% 280 / 2234
ironclaw_network 13.25% 66 / 498
ironclaw_skills 14.58% 377 / 2585
ironclaw_first_party_extensions 22.46% 1125 / 5010
ironclaw_triggers 23.1% 663 / 2870
ironclaw_reborn_traces 23.24% 1492 / 6420
ironclaw_secrets 26.22% 450 / 1716
ironclaw_reborn 28.98% 2542 / 8771
ironclaw_reborn_composition 30.36% 9268 / 30526
ironclaw_capabilities 32.97% 580 / 1759
ironclaw_auth 33.09% 667 / 2016
ironclaw_runtime_policy 33.2% 80 / 241
ironclaw_memory_native 37.02% 857 / 2315
ironclaw_host_api 39.9% 942 / 2361
ironclaw_filesystem 40.17% 1403 / 3493
ironclaw_host_runtime 41.16% 6170 / 14989
ironclaw_threads 41.98% 1326 / 3159
ironclaw_trust 42.56% 326 / 766
ironclaw_loop_support 42.68% 3142 / 7362
ironclaw_memory 47.47% 357 / 752
ironclaw_first_party_extension_ports 48.74% 637 / 1307
ironclaw_wasm 48.79% 363 / 744
ironclaw_projects 50% 147 / 294
ironclaw_extensions 51.4% 1211 / 2356
ironclaw_agent_loop 51.49% 2400 / 4661
ironclaw_resources 51.63% 1109 / 2148
ironclaw_run_state 52.73% 222 / 421
ironclaw_authorization 53.54% 461 / 861
ironclaw_turns 57.78% 5220 / 9035
ironclaw_safety 59.38% 1035 / 1743
ironclaw_observability 61.54% 16 / 26
ironclaw_conversations 66.13% 937 / 1417
ironclaw_approvals 66.63% 549 / 824
ironclaw_dispatcher 67.15% 92 / 137
ironclaw_mcp 67.42% 569 / 844
ironclaw_reborn_identity 70.91% 156 / 220
ironclaw_wasm_limiter 74.6% 47 / 63
ironclaw_product_context 78.57% 11 / 14
ironclaw_attachments 84.92% 107 / 126

This signal is informational: coverage never gates the PR — not the percentage, not the per-crate holes, not the 0-coverage callout.

Exemptions (0 file(s) excluded from the accounting above)

No exemptions configured.

@railway-app

railway-app Bot commented Jul 5, 2026 •

Copy link
Copy Markdown

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

Service Status Web Updated (UTC)
ironclaw ✅ Success (View Logs) Web Jul 5, 2026 at 7:14 am

Compress test_support.rs and runtime.rs comments/doc-comments from
multi-paragraph narratives to their load-bearing crux (audit-sink
divergence, turn_coordinator instance rationale, module-privacy note);
tighten the corresponding CLAUDE.md reference bullets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5654 July 5, 2026 07:08 Destroyed

@henrypark133 henrypark133 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Code Review (multi-agent)

Intent: Add test-support accessors so WebUI approval/auth interaction services are reachable in Reborn composition integration tests.

Stats: 4 findings (from 6 raw, 4 after dedup) across 1 file. Reviewers run: security, bugs, performance, tests, conventions, local-patterns, maintainability, approach. Reviewers failed: none. Body-only: 0.

Conventions

  1. Medium Do not collapse test-support wiring errors into None (crates/ironclaw_reborn_composition/src/runtime/test_support.rs:24-24, confidence 90) — anchor: .claude/rules/error-handling.md:13
    The approval accessor documents None as meaning there is no local-dev runtime, but the new .ok()? calls turn an invalid local-dev capability policy or grantee resolver construction failure into the same None. This also overlaps a maintainability concern: the approval accessor duplicates the production approval-service wiring recipe instead of sharing one helper.
  2. Low Accessor docs omit the required test-only note (crates/ironclaw_reborn_composition/src/runtime/test_support.rs:15-17, confidence 75) — anchor: crates/ironclaw_reborn_composition/CLAUDE.md:6
    The new public *_for_test rustdoc names the production wiring it mirrors, but the per-method docs do not explicitly say the handles are tests-only and gated behind test-support.

Tests

  1. Medium Accessor test does not prove supplied coordinator is used (crates/ironclaw_reborn_composition/src/runtime/test_support.rs:51-76, confidence 75) — anchor: crates/ironclaw_reborn_composition/src/runtime/test_support.rs:51
    The smoke test calls list_pending, but both interaction services use the supplied TurnCoordinator on resolve/resume paths. A regression that ignored the parameter or used a stale coordinator would still pass.
  2. Low Non-local runtime None behavior is untested (crates/ironclaw_reborn_composition/src/runtime/test_support.rs:23-72, confidence 75) — anchor: crates/ironclaw_reborn_composition/src/runtime/test_support.rs:23
    Both accessors document returning None without a local-dev runtime, but the added test only covers the local-dev Some path.

turn_coordinator: Arc<dyn TurnCoordinator>,
) -> Option<Arc<dyn ApprovalInteractionService>> {
let local_runtime = self.local_runtime.as_ref()?;
let local_dev_capability_policy = Arc::new(local_dev_capability_policy().ok()?);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Medium — Do not collapse test-support wiring errors into None.

The accessor documents None as meaning there is no local-dev runtime, but this .ok()? also turns a local-dev capability-policy construction failure into None; the later grantee resolver .ok()? does the same. That silently drops wiring errors and diverges from production, which propagates these failures. It is also a maintainability smell because the approval-service construction is now hand-copied from production wiring.

Fix: Extract the production approval interaction construction into a private helper shared by build_reborn_runtime and this accessor, and return Result<Option<Arc<dyn ApprovalInteractionService>>, RebornRuntimeError> so only an absent local runtime maps to Ok(None).

Also flagged by: maintainability/Medium

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 0f4b69f: extracted build_local_dev_approval_interaction_service (shared by build_reborn_runtime + this accessor); accessor now returns Result<Option<...>, RebornRuntimeError> so capability-policy/grantee-resolver failures propagate instead of collapsing to None.

),
)),
approval_resolver,
turn_coordinator,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Medium — Accessor test does not prove supplied coordinator is used.

The new accessors take a caller-supplied TurnCoordinator, but the added smoke test only calls list_pending. Both approval and auth interaction services use this coordinator on resolve/resume paths, so a regression that ignored the parameter or used a stale service-owned coordinator would still pass.

Fix: Add a caller-level test, for example tests::runtime::local_dev_test_support_interaction_services_use_supplied_turn_coordinator_on_resolve, that drives approval/auth resolve through services built with a supplied coordinator.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 0f4b69f: added local_dev_test_support_interaction_services_use_supplied_turn_coordinator_on_resolve — drives a real builtin.write_file approval gate to BlockedApproval and resolves it through a service built with a spy TurnCoordinator wrapping the runtime's own; asserts only the spy's resume_turn fires.

&self,
turn_coordinator: Arc<dyn TurnCoordinator>,
) -> Option<Arc<dyn ApprovalInteractionService>> {
let local_runtime = self.local_runtime.as_ref()?;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Low — Non-local runtime None behavior is untested.

Both new public test-support accessors document returning None without a local-dev runtime, but the added test only covers the local-dev Some path. No adjacent test covers the non-local/disabled-services branch for either accessor.

Fix: Add tests::runtime::local_dev_test_support_interaction_service_accessors_return_none_without_local_dev_runtime covering both accessors on non-local services.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 0f4b69f: added local_dev_test_support_interaction_service_accessors_return_none_without_local_dev_runtime, covering both accessors against RebornServices::disabled().

use super::*;

impl RebornServices {
/// Real `DefaultApprovalInteractionService` wired like `build_reborn_runtime`.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Low — Accessor docs omit the required test-only note.

The rustdoc names the production wiring it mirrors, but the per-method docs do not explicitly say the handle is tests-only and gated behind test-support; that caveat currently lives only in file-level comments/PR text, so generated docs and hover text miss it.

Fix: Add a doc-comment sentence to both accessors, for example: For tests only -- gated behind test-support, ships zero bytes in production builds.

Also flagged by: local-patterns/Low

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 0f4b69f: both accessors now have an explicit "For tests only -- gated behind test-support, ships zero bytes in production builds." doc line.

henrypark133 and others added 2 commits July 6, 2026 08:53
…s into None

local_dev_approval_interaction_service_for_test masked local-dev
capability-policy and grantee-resolver construction failures behind
`.ok()?`, diverging from production (which propagates via `?`), and
hand-duplicated the DefaultApprovalInteractionService wiring recipe.
Extract build_local_dev_approval_interaction_service as the single
shared recipe for build_reborn_runtime and the test accessor; the
accessor now returns Result<Option<...>, RebornRuntimeError> so only a
genuinely-absent local-dev runtime maps to Ok(None).

Also covers two other review gaps: a caller-level test proving the
supplied TurnCoordinator (not a stale/runtime-owned one) drives
approval resolve/resume, and a test for the non-local-dev None branch
on both *_for_test accessors. Doc comments now note test-only/
test-support gating explicitly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 6, 2026 16:54
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5654 July 6, 2026 16:54 Destroyed
@ironloopai

ironloopai Bot commented Jul 6, 2026 •

Copy link
Copy Markdown
Contributor

✅ IronLoop Review Status

Head: 0f4b69ff8b1dc3cba248388f0c52824d85539881
Result: 1/1 reviewers completed without blocking findings.
Next: Ready for normal human review and CI checks.
Updated: 2026-07-06T16:56:28.297Z

Current reviewers:

Reviewer State Verdict Findings Last update
ironloop/common-reviewer (reviewer) Completed Approved 0 blocking findings / 0 notes 2026-07-06T16:56:28.198Z
Reviewer summaries
Reviewer Detail
ironloop/common-reviewer (reviewer) Approved; 0 blocking findings; No concrete blocking issues found in the reviewed diff. The changes keep the approval/auth interaction accessors behind test-support, share the production local-dev approval wirin…
Recent activity
Time Reviewer State Detail
2026-07-06T16:54:31.336Z ironloop/common-reviewer (reviewer) Queued Accepted review request for head 0f4b69f.
2026-07-06T16:54:31.336Z ironloop/common-reviewer (reviewer) Queued Waiting for this reviewer lane to become available.
2026-07-06T16:54:31.398Z ironloop/common-reviewer (reviewer) Queued Added to the local review work handoff.
2026-07-06T16:54:32.451Z ironloop/common-reviewer (reviewer) Started Reviewer worker started attempt 1.
2026-07-06T16:54:35.672Z ironloop/common-reviewer (reviewer) Workspace ready Prepared isolated checkout (merge_ref) at c93e604.
2026-07-06T16:56:12.513Z ironloop/common-reviewer (reviewer) Running Codex is reviewing; process live; elapsed 1m 38s; timeout in 18m 22s; last heartbeat 2026-07-06T16:56:12.513Z. Activity (stderr): ...s/ironclaw_reborn_composition/src/slack_serve/e2e_tests.rs:775:impl TurnCoordinator for ScriptedTriggerCoordinator {….
2026-07-06T16:56:28.198Z ironloop/common-reviewer (reviewer) Result captured Approved; 0 blocking findings.
2026-07-06T16:56:28.198Z ironloop/common-reviewer (reviewer) Completed Review completed and terminal status was persisted.
Available commands
  • @ironloop agents
  • @ironloop review
  • @ironloop review --agent <agent-id-or-alias>
  • @ironloop status
Run metadata

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

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added size: L 200-499 changed lines and removed size: M 50-199 changed lines labels Jul 6, 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

Verdict: ✅ Approved
Findings: 0 blocking / 0 notes
Next: No reviewer action needed.
Head: 0f4b69ff8b1dc3cba248388f0c52824d85539881

Run details

Status: Current
Needs human: no
Needs validation: no

**Inline candidates:** 0

Summary

No concrete blocking issues found in the reviewed diff. The changes keep the approval/auth interaction accessors behind test-support, share the production local-dev approval wiring, and add caller-level tests for the supplied TurnCoordinator path.

Findings

None.

Developer follow-up

After fixing this feedback:

  1. Push the fix to this PR branch.
  2. Re-run this reviewer with @ironloop review --agent reviewer if you only changed this reviewer's findings.
  3. Re-run all reviewers with @ironloop review when the fix may affect multiple areas.
  4. Use @ironloop status to check queued/running/completed/stale/stalled state while reviewers run.

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-5654 — 0f4b69ff Deployed Jul 6, 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 scope: docs Documentation size: L 200-499 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants