Skip to content

feat(reborn): env-configurable turn-runner concurrency (0 = unlimited) - #5265

Merged
henrypark133 merged 14 commits into
mainfrom
libsql-unlimited-concurrency
Jun 26, 2026
Merged

henrypark133 merged 14 commits into
mainfrom
libsql-unlimited-concurrency

Conversation

@henrypark133

Copy link
Copy Markdown
Collaborator

Why

Stress-test the libSQL backend under high write concurrency by removing the global turn-runner throttle at runtime, without recompiling. Builds on #5259 (local libSQL hosted single-tenant volume).

What

Adds env-var control over the Reborn turn-runner concurrency knobs. 0 means "unlimited" on every knob. Env layer is highest-precedence (over the [runner] config-file section), applies even with no config file, and uses strict-presence semantics (set-but-blank / non-numeric → fatal startup error).

Env var 0 → default
IRONCLAW_REBORN_RUNNER_WORKER_COUNT unlimited (no global scheduler throttle) 16
IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_RUNS_PER_USER unlimited 3
IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_TRIGGER_RUNS unlimited 8
IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_CONVERSATION_RUNS unlimited (already None)

For the libSQL stress test: IRONCLAW_REBORN_RUNNER_WORKER_COUNT=0.

How

  • worker_count changes from NonZeroUsize to Option<NonZeroUsize> (None = unlimited). The per-user / per-origin caps already used None = unlimited; this extends the same convention to the global scheduler.
  • scheduler_permit_count() maps None → tokio::sync::Semaphore::MAX_PERMITS, so the scheduler never throttles claimed runs (per-user / per-origin caps remain the only bound). worker_count only sizes the scheduler semaphore — single scheduler task, no N-task pool — so an unbounded permit count spawns no extra tasks.
  • resolve_worker_count() mirrors the existing resolve_concurrency_cap() (absent → default, 0 → unlimited, positive → clamp to 32).
  • Extracted the shared strict-env helpers into runtime/env_util.rs (moved out of trigger_poller.rs, no behavior change) and added a generic strict_env_var_parsed<T>. The three cap overrides go through one apply_cap_env_override(name, &mut slot) helper.

Tests

  • Env-override precedence, 0=unlimited, clamp-at-max, and fatal-blank/non-numeric for worker_count and the caps.
  • scheduler_permit_count(None) → MAX_PERMITS without panicking Semaphore::new.
  • Existing config-file tests guarded against env bleed.
  • cargo fmt + clippy clean (libsql + default features); runner / trigger_poller / concurrent_workers suites green.

Notes

🤖 Generated with Claude Code

serrrfirat and others added 6 commits June 18, 2026 20:48
…enant-volume

# Conflicts:
#	crates/ironclaw_reborn_cli/src/runtime/mod.rs
…enant-volume

# Conflicts:
#	Dockerfile.reborn
#	crates/ironclaw_reborn_cli/src/commands/config/init.rs
#	crates/ironclaw_reborn_cli/src/commands/serve.rs
#	crates/ironclaw_reborn_cli/src/commands/skills.rs
#	crates/ironclaw_reborn_cli/src/runtime/mod.rs
#	crates/ironclaw_reborn_cli/tests/smoke.rs
#	crates/ironclaw_reborn_composition/src/extension_installation_store.rs
#	crates/ironclaw_reborn_composition/src/factory.rs
#	crates/ironclaw_reborn_composition/src/lib.rs
#	crates/ironclaw_reborn_composition/src/local_runtime_profile.rs
#	crates/ironclaw_reborn_composition/src/profile.rs
#	crates/ironclaw_reborn_composition/src/readiness.rs
#	crates/ironclaw_reborn_composition/src/runtime.rs
#	crates/ironclaw_reborn_composition/src/runtime/local_dev.rs
#	crates/ironclaw_reborn_composition/src/runtime/local_dev/refreshing_capability_port.rs
#	crates/ironclaw_reborn_composition/src/runtime/local_dev/tests.rs
#	crates/ironclaw_reborn_composition/tests/profile_acceptance.rs
#	crates/ironclaw_reborn_config/src/config_file.rs
#	crates/ironclaw_reborn_config/src/home.rs
#	crates/ironclaw_reborn_config/src/profile.rs
#	crates/ironclaw_reborn_config/tests/profile_contract.rs
#	docker/reborn/entrypoint.sh
#	docs/reborn/deploy-reborn-cli-docker.md
…ited

Make the Reborn turn-runner concurrency knobs overridable from the
environment so a deployment can run with no global throttle to
stress-test the database backend (e.g. libSQL) under high write
concurrency.

New env vars (highest-precedence layer over the `[runner]` config-file
section), each with `0` meaning "unlimited":

- IRONCLAW_REBORN_RUNNER_WORKER_COUNT
- IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_RUNS_PER_USER
- IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_TRIGGER_RUNS
- IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_CONVERSATION_RUNS

The per-user / per-origin caps already treated `None` as unlimited; this
extends the same semantics to the global scheduler `worker_count`, which
was previously a `NonZeroUsize` clamped to 32. It is now
`Option<NonZeroUsize>` where `None` sizes the scheduler semaphore to
`tokio::sync::Semaphore::MAX_PERMITS`, leaving the per-user / per-origin
caps as the only concurrency bound. `worker_count` only feeds the
scheduler semaphore (single scheduler task, no N-task pool), so an
unbounded permit count spawns no extra tasks.

Implementation notes:
- `scheduler_permit_count()` maps the new `Option<NonZeroUsize>` to a
  permit count (None -> MAX_PERMITS).
- `resolve_worker_count()` mirrors the existing `resolve_concurrency_cap()`
  (absent -> default, 0 -> unlimited, positive -> clamp to 32).
- Env overrides apply even with no config file, using strict-presence
  semantics (set-but-blank / non-numeric is a fatal startup error).
- Extracted the shared strict-env helpers into `runtime/env_util.rs`
  (moved out of `trigger_poller.rs`, no behavior change) and added a
  generic `strict_env_var_parsed<T>` used by the runner overrides.

Tests: env-override precedence + 0=unlimited + clamp + fatal-blank for
worker_count and caps; `scheduler_permit_count` None->MAX_PERMITS without
panic; existing config-file tests guarded against env bleed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 25, 2026 21:35 Destroyed
@coderabbitai

coderabbitai Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 21ab8b1c-40a7-48a8-b3be-dbd467d1b649

📥 Commits

Reviewing files that changed from the base of the PR and between db50fd8 and af3fbe6.

📒 Files selected for processing (5)
  • crates/ironclaw_reborn/src/runtime.rs
  • crates/ironclaw_reborn_cli/src/operator_env.rs
  • crates/ironclaw_reborn_cli/src/runtime/mod.rs
  • crates/ironclaw_reborn_cli/src/runtime/test_env.rs
  • crates/ironclaw_reborn_cli/src/runtime/trigger_poller.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added environment-based overrides for turn-runner concurrency settings, including worker count and several concurrency caps.
    • Support for 0 as “unlimited” and clearer defaults for concurrency settings.
  • Bug Fixes

    • Prevented startup failures from invalid or blank concurrency overrides by validating values more strictly.
    • Improved handling of very large worker counts by rejecting unsafe values before runtime issues occur.
  • Documentation

    • Updated runtime configuration guidance to explain precedence, defaults, and override behavior.

Walkthrough

This PR makes turn-runner worker counts optional, adds strict parsing and precedence for IRONCLAW_REBORN_RUNNER_* overrides, generalizes runtime env test locking, and adds a disabled-libsql acceptance test.

Changes

Runner concurrency overrides

Layer / File(s) Summary
Worker-count model
crates/ironclaw_reborn_composition/src/runtime_input.rs, crates/ironclaw_reborn/src/runtime.rs, crates/ironclaw_reborn_config/src/config_file.rs, .env.example, crates/ironclaw_reborn_composition/tests/runtime.rs
worker_count becomes optional, None maps to unlimited scheduler permits, and the config/example docs describe the new 0 and ceiling semantics.
Strict env parsing
crates/ironclaw_reborn_cli/src/operator_env.rs, crates/ironclaw_reborn_cli/src/runtime/test_env.rs, crates/ironclaw_reborn_cli/src/runtime/trigger_poller.rs
Typed env parsing is added for strict presence-based variables, and the runtime env test lock is renamed to cover runner, trigger, and OAuth env vars.
Runner override resolution
crates/ironclaw_reborn_cli/src/runtime/mod.rs
runner_settings resolves optional worker counts, applies IRONCLAW_REBORN_RUNNER_* overrides for worker count and concurrency caps, and validates the final worker count against the semaphore ceiling.
Runner override tests
crates/ironclaw_reborn_cli/src/runtime/mod.rs
Tests cover absent and present runner sections, worker-count boundaries, env parse failures, override precedence, and the runtime env-lock migration across the runtime suite.

Libsql feature acceptance

Layer / File(s) Summary
Missing libsql failure
crates/ironclaw_reborn_composition/tests/profile_acceptance.rs
The acceptance suite adds a gated failure case for hosted_single_tenant_volume_build_input(...) when the libsql feature is disabled.

Sequence Diagram(s)

sequenceDiagram
  participant runner_settings
  participant strict_env_var_parsed
  participant resolve_worker_count
  participant ensure_worker_count_within_ceiling
  participant RebornRuntimeInput
  runner_settings->>strict_env_var_parsed: read IRONCLAW_REBORN_RUNNER_* overrides
  strict_env_var_parsed-->>runner_settings: parsed values or fatal error
  runner_settings->>resolve_worker_count: map runner.worker_count to Option<NonZeroUsize>
  runner_settings->>ensure_worker_count_within_ceiling: validate final worker count
  runner_settings->>RebornRuntimeInput: build runtime input
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • nearai/ironclaw#5085: Adds the scheduler and concurrent turn-execution wiring that this PR extends with optional worker-count and override handling.

Suggested reviewers

  • zmanian

Poem

Zero slipped into the runner’s gate,
And “unlimited” became its state.
Env vars spoke in strict, neat rhymes,
Tests kept watch through branching times.
The semaphore sang, no panic in sight,
While libsql’s absence held fast and tight.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Conventional Commits style is used and the title accurately summarizes the env-configurable turn-runner concurrency change.
Description check ✅ Passed The description is detailed and covers motivation, behavior, tests, and notes, though it doesn’t follow the template headings exactly.
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.

@github-actions github-actions Bot added size: L 200-499 changed lines risk: low Changes to docs, tests, or low-risk modules contributor: core 20+ merged PRs labels Jun 25, 2026

@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 support for overriding turn-runner concurrency settings via environment variables (such as IRONCLAW_REBORN_RUNNER_WORKER_COUNT) with strict presence semantics. It updates the worker_count configuration to be optional, where None represents an unlimited setting. A new env_util module is added to centralize strict environment variable parsing and display truncation, replacing duplicate helpers in trigger_poller.rs. Feedback on the changes highlights that the generic helper strict_env_var_parsed<T> contains a hardcoded error message expecting a "non-negative integer", which would be misleading if reused for non-integer types; using std::any::type_name::<T>() is suggested instead.

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.

Comment thread crates/ironclaw_reborn_cli/src/runtime/env_util.rs Outdated
@henrypark133
henrypark133 requested a review from serrrfirat June 25, 2026 22:16
@railway-app

railway-app Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

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

Service Status Web Updated (UTC)
ironclaw ✅ Success (View Logs) Web Jun 26, 2026 at 9:17 pm

Base automatically changed from codex/hosted-single-tenant-volume to main June 26, 2026 10:57

@serrrfirat serrrfirat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

code-review-multi summary

Reviewed PR #5265 at 935199bd64ef584abd6b7ac828b64b642b3a1da2 with five specialist reviewers plus intent analysis, forced per request.

Intent: make Reborn turn-runner concurrency env-configurable, with 0 meaning unlimited; also stacked on hosted single-tenant volume work.

Reviewer results:

  • Security: 0 findings
  • Bugs: 0 findings
  • Performance/Concurrency: 0 findings
  • Tests: 4 findings
  • Conventions: 2 low-severity stale-comment findings
  • Thermo-nuclear maintainability pass: 1 structural concern

Findings

Tests

  1. Medium: runner env overrides need caller-level coverage through build_runtime_input*, not only runner_settings().
  2. Medium: cap env blank/non-numeric fatal paths are not tested; invalid env coverage currently exercises only IRONCLAW_REBORN_RUNNER_WORKER_COUNT.
  3. Medium: IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_CONVERSATION_RUNS needs a positive bounded-value test because its default is already None.
  4. Low: the cfg(not(feature = "libsql")) hosted-volume error path needs a no-libSQL test.

Conventions

  • Low: crates/ironclaw_reborn/src/runtime.rs:61 still describes DEFAULT_TURN_RUNNER_WORKER_COUNT as spawned worker tasks, but the PR reframes the knob as scheduler slots/permits.
  • Low: crates/ironclaw_reborn_cli/src/runtime/mod.rs:801 still says strict env helpers live in trigger_poller; after this refactor they live in runtime::env_util.

Thermo-nuclear maintainability

  • The PR pushes crates/ironclaw_reborn/src/runtime.rs from 974 to 1009 lines. Under the thermo review bar, crossing 1k lines should be justified or decomposed; the new scheduler permit mapping/tests are small but could live in a focused config/helper module so runtime.rs does not continue growing.

Comment thread crates/ironclaw_reborn_cli/src/runtime/mod.rs Outdated
Comment thread crates/ironclaw_reborn_cli/src/runtime/mod.rs Outdated
Comment thread crates/ironclaw_reborn_cli/src/runtime/mod.rs
Comment thread crates/ironclaw_reborn_composition/src/local_runtime_profile.rs Outdated
/// [`tokio::sync::Semaphore::MAX_PERMITS`] so the global scheduler never
/// throttles claimed runs — the per-user / per-origin caps remain the only
/// concurrency bound. A bounded count passes through unchanged.
fn scheduler_permit_count(worker_count: Option<std::num::NonZeroUsize>) -> usize {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thermo-nuclear maintainability note: this PR pushes runtime.rs from 974 to 1009 lines. The helper is small, but the file is already the planned-runtime composition surface; can we decompose this first, for example by moving the worker-count-to-scheduler-permits mapping and its tests into a focused config/helper module?

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.

Thought about this one carefully and would prefer to decline the extraction as proposed. scheduler_permit_count has a single production call site, is a 4-line pure fn with colocated tests and a doc comment — it already is the clean abstraction; moving just it into its own module adds an import + indirection without reducing the concepts a reader holds (a one-function module isn't really "the owning file for a concern" the crate guardrail intends). At 1009 lines the file is also under this repo's own architecture.md soft threshold (1500), and the 1k crossing is incidental (+35 lines of cohesive, tested feature code, no new branching).

That said, the underlying signal is fair. If we do decompose runtime.rs, the cohesive unit is the planned-runtime config — DefaultPlannedRuntimeConfig + its Default impl + scheduler_permit_count + their tests → a planned_runtime_config.rs (matches the crate's one-concern-per-file convention and pulls the file back under 1k). Happy to do that as a focused follow-up PR rather than peeling off a single helper here. Let me know if you'd like me to open it.

…verage

The reborn-tests.yml `env:` block declared `CARGO_NET_RETRY` twice, which
GitHub Actions rejects as a duplicate mapping key — the workflow failed to
parse (0s "workflow file issue" run on push) and blocked the pull_request
checks from ever starting. Same class as #5193 / #5325 on main. Remove the
duplicate; keep the commented occurrence.

Address PR review feedback on the env-configurable turn-runner concurrency:

- env_util: make `strict_env_var_parsed<T>` error message type-aware via
  `std::any::type_name::<T>()` instead of hardcoding "non-negative integer",
  which was misleading for the generic helper.
- runtime/mod.rs: add caller-level coverage through
  `build_runtime_input` that `IRONCLAW_REBORN_RUNNER_WORKER_COUNT=0` reaches
  the built runtime input as `worker_count: None`; add blank/non-numeric
  fatal tests for a cap var; add a positive bounded
  `MAX_CONCURRENT_CONVERSATION_RUNS=2 -> Some(2)` test (the field defaults to
  None, so a silently-ignored override would otherwise pass).
- profile_acceptance: add a `cfg(not(feature = "libsql"))` regression that
  `hosted_single_tenant_volume_build_input` returns `MissingLibsqlFeature`.

Also gate two libsql-only test imports so the libsql-on CI build (webui-v2-beta
pulls in libsql) compiles warning-free.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 26, 2026 17:50 Destroyed
@github-actions github-actions Bot added size: XL 500+ changed lines risk: medium Business logic, config, or moderate-risk modules scope: sandbox Docker sandbox scope: ci CI/CD workflows scope: docs Documentation and removed size: L 200-499 changed lines risk: low Changes to docs, tests, or low-risk modules labels Jun 26, 2026

@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 @.env.example:
- Line 232: The .env.example note for IRONCLAW_REBORN_RUNNER_WORKER_COUNT
hard-codes a 32-worker clamp that may drift from the actual limit. Verify the
value of MAX_WORKER_COUNT in the runtime code path (for example, the constant
used by worker-count parsing in the CLI/runtime module) and update this comment
to match it; ideally mention MAX_WORKER_COUNT by name so the documentation stays
aligned if the limit changes later.

In `@crates/ironclaw_reborn_cli/tests/smoke.rs`:
- Around line 116-121: The smoke test in `assert!` is too strict because it
matches one exact comma-separated feature order; update the Dockerfile check to
be order-insensitive while still verifying both build invocations include
`libsql` and `postgres`. Adjust the matching logic in
`crates/ironclaw_reborn_cli/tests/smoke.rs` around the `dockerfile.matches(...)`
assertion so it accepts either order of the feature flags, while keeping the
requirement that both cargo-chef deps and the final binary are covered.

In `@README.md`:
- Around line 207-220: The README’s `IRONCLAW_REBORN_PROFILE` documentation and
the adjacent boot profile notes are missing the still-supported
`hosted-single-tenant` profile, which can mislead operators. Update the profile
सूची and the `run`/`repl` support description to include `hosted-single-tenant`
alongside the existing values, and make sure the explanatory text around
`hosted-single-tenant-volume` and the CLI-supported profiles stays consistent.
🪄 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: 371a0dec-399f-449e-8e70-e23c80e082fc

📥 Commits

Reviewing files that changed from the base of the PR and between 0c79a2d and 8c048d4.

📒 Files selected for processing (33)
  • .env.example
  • .github/workflows/reborn-tests.yml
  • Dockerfile.reborn
  • README.md
  • crates/ironclaw_reborn/src/runtime.rs
  • crates/ironclaw_reborn_cli/Cargo.toml
  • crates/ironclaw_reborn_cli/src/commands/config/init.rs
  • crates/ironclaw_reborn_cli/src/commands/serve.rs
  • crates/ironclaw_reborn_cli/src/commands/skills.rs
  • crates/ironclaw_reborn_cli/src/runtime/env_util.rs
  • crates/ironclaw_reborn_cli/src/runtime/mod.rs
  • crates/ironclaw_reborn_cli/src/runtime/test_env.rs
  • crates/ironclaw_reborn_cli/src/runtime/trigger_poller.rs
  • crates/ironclaw_reborn_cli/tests/smoke.rs
  • crates/ironclaw_reborn_composition/src/factory.rs
  • crates/ironclaw_reborn_composition/src/input.rs
  • crates/ironclaw_reborn_composition/src/lib.rs
  • crates/ironclaw_reborn_composition/src/local_runtime_profile.rs
  • crates/ironclaw_reborn_composition/src/profile.rs
  • crates/ironclaw_reborn_composition/src/readiness.rs
  • crates/ironclaw_reborn_composition/src/runtime.rs
  • crates/ironclaw_reborn_composition/src/runtime_input.rs
  • crates/ironclaw_reborn_composition/tests/facade_factory.rs
  • crates/ironclaw_reborn_composition/tests/profile_acceptance.rs
  • crates/ironclaw_reborn_composition/tests/runtime.rs
  • crates/ironclaw_reborn_config/src/config_file.rs
  • crates/ironclaw_reborn_config/src/home.rs
  • crates/ironclaw_reborn_config/src/profile.rs
  • crates/ironclaw_reborn_config/tests/profile_contract.rs
  • docker/reborn/config.hosted-single-tenant-volume.toml
  • docker/reborn/entrypoint.sh
  • docs/reborn/deploy-reborn-cli-docker.md
  • tests/dockerfile_runtime_home.rs
💤 Files with no reviewable changes (1)
  • .github/workflows/reborn-tests.yml

Comment thread .env.example Outdated
Comment thread crates/ironclaw_reborn_cli/tests/smoke.rs
Comment thread README.md Outdated
…urrency

# Conflicts:
#	.github/workflows/reborn-tests.yml
#	README.md
#	crates/ironclaw_reborn_cli/src/commands/serve.rs
#	crates/ironclaw_reborn_cli/src/commands/skills.rs
#	crates/ironclaw_reborn_cli/src/runtime/mod.rs
#	crates/ironclaw_reborn_cli/src/runtime/trigger_poller.rs
#	crates/ironclaw_reborn_composition/src/factory.rs
#	crates/ironclaw_reborn_composition/src/input.rs
#	crates/ironclaw_reborn_composition/src/local_runtime_profile.rs
#	crates/ironclaw_reborn_composition/src/readiness.rs
#	crates/ironclaw_reborn_composition/src/runtime.rs
#	crates/ironclaw_reborn_composition/tests/facade_factory.rs
#	crates/ironclaw_reborn_composition/tests/profile_acceptance.rs
#	docker/reborn/config.hosted-single-tenant-volume.toml
#	tests/dockerfile_runtime_home.rs
@github-actions github-actions Bot added risk: low Changes to docs, tests, or low-risk modules and removed risk: medium Business logic, config, or moderate-risk modules labels Jun 26, 2026

@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)
.env.example (1)

228-236: ⚠️ Potential issue | 🟡 Minor

Hard-coded "32" in .env.example drifts from source constant MAX_WORKER_COUNT

File: .env.example | Line: 232

The comment for IRONCLAW_REBORN_RUNNER_WORKER_COUNT explicitly states "clamped to 32". This is brittle; the value 32 is defined in crates/ironclaw_reborn_cli/src/runtime/mod.rs as const MAX_WORKER_COUNT: usize = 32.

Update the comment to reference the constant by name to prevent documentation drift if the limit changes:
positive values clamped to MAX_WORKER_COUNT

Instead of positive values clamped to 32.

🤖 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 @.env.example around lines 228 - 236, The comment for
IRONCLAW_REBORN_RUNNER_WORKER_COUNT in .env.example hard-codes the worker cap as
32, which can drift from the source of truth; update this documentation to
reference MAX_WORKER_COUNT by name instead of a literal value. Use the existing
runtime limit constant from runtime/mod.rs and keep the surrounding wording
consistent so the example stays aligned if the limit changes.
🤖 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 @.env.example:
- Around line 228-236: The comment for IRONCLAW_REBORN_RUNNER_WORKER_COUNT in
.env.example hard-codes the worker cap as 32, which can drift from the source of
truth; update this documentation to reference MAX_WORKER_COUNT by name instead
of a literal value. Use the existing runtime limit constant from runtime/mod.rs
and keep the surrounding wording consistent so the example stays aligned if the
limit changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 193b7880-31ed-4adb-bbb1-d1a7d4b0a17e

📥 Commits

Reviewing files that changed from the base of the PR and between 8c048d4 and 26aa898.

📒 Files selected for processing (2)
  • .env.example
  • crates/ironclaw_reborn/src/runtime.rs
💤 Files with no reviewable changes (1)
  • crates/ironclaw_reborn/src/runtime.rs

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 26, 2026 18:43 Destroyed
…ter merge

The merge of origin/main adopted main's readiness model where
`HostedSingleTenantVolume` is a *preview* diagnostic
(`HostedSingleTenantVolumePreview` / `Warning`), not a blocking dev-only
profile. The merged test file kept this branch's stale
`dev_only_profiles_are_visible_non_production_in_readiness` variant, which
still grouped `HostedSingleTenantVolume` with the dev-only profiles and
asserted `DevOnlyProfile` / `Blocking` — contradicting the adopted code and
main's dedicated `hosted_single_tenant_volume_is_visible_as_preview_readiness`
test. Restore main's loop (LocalDev + LocalDevYolo only); the volume profile's
preview readiness is covered by the separate test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 26, 2026 19:47 Destroyed
@henrypark133
henrypark133 requested a review from serrrfirat June 26, 2026 19:49
`worker_count` is the global scheduler-semaphore permit count. The feature
already treats `0` as the "unlimited" sentinel (sizes the semaphore to
`Semaphore::MAX_PERMITS`), but a positive value was silently clamped to
`MAX_WORKER_COUNT = 32` — so an operator asking for e.g. 64 got 32 with no
error, and the only way past 32 was to go fully unlimited. That asymmetry
half-defeats the env-configurable knob and diverged from the per-user /
trigger / conversation caps, which are passed through verbatim.

Remove the clamp and the `MAX_WORKER_COUNT` constant: `Some(n)` now resolves
to exactly `n`. This is safe — the permit count just sizes a semaphore
counter; runner tasks are still only spawned per claimed run, so a large
value degrades smoothly toward the `0` = unlimited regime. Update the two
clamp tests to assert verbatim pass-through (512 -> 512) and refresh the
`.env.example` note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 26, 2026 19:54 Destroyed
…g helper

`runner_settings` applied the three concurrency caps through
`apply_cap_env_override` but hand-inlined the `worker_count` override, so the
env-override block read asymmetrically and invited the question "why is
worker_count special?". The only reason is the type split (worker_count is
usize/NonZeroUsize scheduler permits; caps are u32/NonZeroU32) — stable Rust
can't express one helper generic over NonZero<T> (ZeroablePrimitive is
unstable). Add a sibling `apply_worker_count_env_override` so all four env
overrides read as uniform helper calls. Behavior-preserving (runner tests
unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 26, 2026 19:59 Destroyed
@github-actions github-actions Bot added size: XL 500+ changed lines and removed size: L 200-499 changed lines labels Jun 26, 2026

@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_cli/src/runtime/mod.rs`:
- Around line 1018-1033: `resolve_worker_count()` currently forwards any
positive `usize`, which lets values above `Semaphore::MAX_PERMITS` reach
`Semaphore::new(...)` in `turn_scheduler`, causing a startup panic instead of a
config error. Add an explicit upper-bound check in the worker-count resolution
path (or immediately before semaphore construction) to reject oversized values
and surface a clear validation error. Use the existing `resolve_worker_count`
and `TurnScheduler`/builder flow to locate the fix, and add a regression test
covering `MAX_PERMITS + 1` so the overflow case fails loudly.
🪄 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: 0c992b72-16d2-4e1e-ba03-c894d6a5c4e0

📥 Commits

Reviewing files that changed from the base of the PR and between 2b4b734 and a25c6af.

📒 Files selected for processing (2)
  • .env.example
  • crates/ironclaw_reborn_cli/src/runtime/mod.rs

Comment thread crates/ironclaw_reborn_cli/src/runtime/mod.rs

@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: Make Reborn turn-runner concurrency env-configurable, including unlimited zero values, strict env validation, and highest-precedence overrides for runtime stress testing.

Stats: 2 findings accepted for posting (from 8 raw reviewer findings; duplicates and non-blocking cleanup notes filtered) across 2 files. Reviewers run: security, bugs, performance, tests, conventions, local-patterns, maintainability, approach. Reviewers failed: none. Body-only: 0.

Findings

  1. High Worker-count overrides can exceed Tokio's semaphore ceiling (crates/ironclaw_reborn_cli/src/runtime/mod.rs:1024-1033, confidence 95) - anchor: crates/ironclaw_host_runtime/src/turn_scheduler.rs:434

    Positive worker_count values now pass through unchanged, but the runtime maps Some(worker_count) through scheduler_permit_count into TurnRunSchedulerConfig::with_max_concurrent_runs, and the scheduler constructs tokio::sync::Semaphore::new(config.max_concurrent_runs()). Tokio panics above Semaphore::MAX_PERMITS, so a malformed config/env value can crash startup instead of failing validation.

  2. Medium Remove the stale 32-worker clamp promise (crates/ironclaw_reborn_config/src/config_file.rs:159-162, confidence 92) - anchor: AGENTS.md:84

    RunnerSection.worker_count still documents that positive values are clamped to 32, but the current runtime path deliberately accepts positive values verbatim. That comment now promises a cross-layer guarantee the implementation does not enforce.

Comment thread crates/ironclaw_reborn_cli/src/runtime/mod.rs
Comment thread crates/ironclaw_reborn_config/src/config_file.rs
Removing the 32-worker clamp let any positive `worker_count` flow verbatim into
`scheduler_permit_count` → `TurnRunSchedulerConfig::with_max_concurrent_runs`
(which only floors at 1) → `tokio::sync::Semaphore::new(...)`. Tokio's
`Semaphore::new` panics above `Semaphore::MAX_PERMITS`, so a malformed
config/env value (e.g. `usize::MAX`) crashed startup instead of failing
validation — violating the repo's fail-loud boundary rule.

`resolve_worker_count` now returns a Result and rejects values above
`tokio::sync::Semaphore::MAX_PERMITS` as a config error, while still accepting
`1..=MAX_PERMITS` verbatim and keeping `0` as the explicit unlimited sentinel
(the unlimited path sizes the semaphore to exactly `MAX_PERMITS`, which Tokio
accepts). Both the config-file and env-override paths funnel through it.

Adds regression tests for `MAX_PERMITS + 1` on both paths, and fixes the stale
`RunnerSection.worker_count` doc that still promised the 32-worker clamp.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 26, 2026 21:11 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: Make Reborn turn-runner concurrency configurable via environment variables, with 0 meaning unlimited and env overrides taking highest precedence.

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

Bugs

  1. High Oversized worker_count can still panic direct runtime builders (crates/ironclaw_reborn/src/runtime.rs:675-676, confidence 82) — anchor: crates/ironclaw_reborn/src/runtime.rs:675
    The CLI now rejects worker_count values above tokio::sync::Semaphore::MAX_PERMITS, but DefaultPlannedRuntimeConfig.worker_count is still public and build_default_planned_runtime passes it through scheduler_permit_count into TurnRunSchedulerConfig::with_max_concurrent_runs. Direct composition callers can therefore still provide Some(n > MAX_PERMITS) and reach tokio::sync::Semaphore::new(...), which panics during scheduler startup instead of returning a build error.
  2. Medium Invalid config-file worker_count blocks a valid env override (crates/ironclaw_reborn_cli/src/runtime/mod.rs:1098-1100, confidence 66) — anchor: crates/ironclaw_reborn_cli/src/runtime/mod.rs:1100
    The PR states that the env layer has highest precedence over the [runner] config-file section, but runner_settings validates the config-file worker_count before applying IRONCLAW_REBORN_RUNNER_WORKER_COUNT. If config.toml contains an oversized worker_count and the env var supplies a valid smaller value, startup still fails before the higher-precedence env value can win.

Tests

  1. Medium Missing boundary test for exact semaphore ceiling (crates/ironclaw_reborn_cli/src/runtime/mod.rs:1037-1044, confidence 86) — anchor: crates/ironclaw_reborn_cli/src/runtime/mod.rs:1037
    The new worker-count validation accepts 1..=tokio::sync::Semaphore::MAX_PERMITS and rejects values above it, but tests only cover a mid-range value and MAX_PERMITS + 1. An off-by-one regression that rejects the exact ceiling would still pass.
  2. Low Missing oversized-invalid-value test for parsed env errors (crates/ironclaw_reborn_cli/src/runtime/env_util.rs:67-73, confidence 79) — anchor: crates/ironclaw_reborn_cli/src/runtime/env_util.rs:67
    strict_env_var_parsed truncates the raw env value before embedding it in the parse error, but the current tests only exercise truncation directly and short invalid parse values. The parsed-error safety path could regress into logging the full oversized env value without a failing test.

Maintainability

  1. Medium Duplicate strict-env helper home (crates/ironclaw_reborn_cli/src/runtime/env_util.rs:1-75, confidence 86) — anchor: crates/ironclaw_reborn_cli/src/operator_env.rs:1
    runtime/env_util.rs reimplements the strict-presence and truncation helpers already centralized in operator_env.rs, so the crate now has two places defining the same operator env-var contract. Keeping blank-value rejection and redaction behavior in sync across both modules adds risk without hiding new complexity.

Local Patterns

  1. Low Rename the shared env lock to match its broader scope (crates/ironclaw_reborn_cli/src/runtime/test_env.rs:12-18, confidence 74) — anchor: crates/ironclaw_reborn_cli/src/runtime/test_env.rs:12
    The helper now serializes trigger, runner, and OAuth env-var tests, but the static and accessor are still named TRIGGER_ENV_LOCK and lock_trigger_env. The file comments explain the name is historical, but new callers now have to learn that trigger-named APIs are the global runtime env lock.

Comment thread crates/ironclaw_reborn/src/runtime.rs
Comment thread crates/ironclaw_reborn_cli/src/runtime/mod.rs Outdated
Comment thread crates/ironclaw_reborn_cli/src/runtime/mod.rs Outdated
Comment thread crates/ironclaw_reborn_cli/src/runtime/env_util.rs Outdated
Comment thread crates/ironclaw_reborn_cli/src/runtime/env_util.rs Outdated
Comment thread crates/ironclaw_reborn_cli/src/runtime/test_env.rs Outdated
Addresses the review round on the worker_count work:

- High: oversized worker_count could still panic direct composition callers.
  `DefaultPlannedRuntimeConfig.worker_count` is public, so a caller bypassing
  the CLI could reach `Semaphore::new(n > MAX_PERMITS)`. `scheduler_permit_count`
  now saturates at `tokio::sync::Semaphore::MAX_PERMITS` as an infallible
  backstop (defense-in-depth), with a regression test.

- Medium: an oversized config-file worker_count rejected startup before the
  higher-precedence env override could win. Move the ceiling check off the
  per-layer resolution into a single `ensure_worker_count_within_ceiling` gate
  applied to the FINAL merged value, after env precedence. `resolve_worker_count`
  is pure layering again. Tests: env override rescues an oversized config value;
  the exact `MAX_PERMITS` boundary is accepted on both config + env paths.

- Medium: `runtime/env_util.rs` duplicated the strict-presence + truncation
  helpers already in `operator_env.rs`. Move `strict_env_var_parsed` into
  `operator_env.rs` beside its siblings, repoint `runner_settings`, and delete
  the duplicate module.

- Low: add an oversized-invalid-value test asserting the parse error truncates
  the echoed value.

- Low: rename the process-wide test env lock `TRIGGER_ENV_LOCK` / `lock_trigger_env`
  to scope-neutral `RUNTIME_ENV_LOCK` / `lock_runtime_env`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-5265 June 26, 2026 22:02 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: Make Reborn turn-runner concurrency configurable via environment variables, with 0 meaning unlimited and env overrides taking precedence over config.

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

Tests

  1. Medium Missing test for WORKER_COUNT=0 clearing a configured worker count (crates/ironclaw_reborn_cli/src/runtime/mod.rs:1140-1164, confidence 90) — anchor: crates/ironclaw_reborn_cli/src/runtime/mod.rs:1372
    The new precedence path is tested for IRONCLAW_REBORN_RUNNER_WORKER_COUNT=0 only when no [runner] section exists, and for env-over-config only with a positive value. There is no test that a zero env override clears a positive config-file worker_count before the final ceiling check runs, so the documented 0 = unlimited behavior could regress for real configs.

}

#[test]
fn runner_env_worker_count_overrides_config_file() {

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 — Missing test for WORKER_COUNT=0 clearing a configured worker count.

The new precedence path is tested for IRONCLAW_REBORN_RUNNER_WORKER_COUNT=0 only when no [runner] section exists, and for env-over-config only with a positive value. There is no test that a zero env override clears a positive config-file worker_count before the final ceiling check runs, so the documented 0 = unlimited behavior could regress for real configs.

Fix: Add runner_env_worker_count_zero_overrides_config_file covering IRONCLAW_REBORN_RUNNER_WORKER_COUNT=0 against a positive [runner].worker_count.

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-5265 — af3fbe66 Deployed Jun 26, 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: ci CI/CD workflows scope: docs Documentation scope: sandbox Docker sandbox size: XL 500+ changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants