fabro/lib/crates/fabro-cli/tests/it/cmd
Bryan Helmkamp 3eef9ee928
Model Test Bounded Concurrency Implementation Plan (#204)
This change makes bulk `fabro model test` run configured model checks
concurrently instead of serially. A new `--jobs/-j` flag (defaulting to
4, minimum 1) controls the concurrency bound; the single-model path
(`--model <MODEL>`) is unaffected. Under the hood, the serial `for` loop
over configured models is replaced with a
`futures::stream::buffer_unordered(jobs)` pipeline that clones the
shared-state `Client` per request. Completed results carry their
original list index and are sorted before rendering, so final stdout
table rows and JSON output remain in listing order regardless of which
requests finish first.

Three new integration tests verify the concurrency behavior using an
inline Axum harness with a `ConcurrencyGate` barrier. The gate holds all
in-flight requests until the expected number arrive simultaneously, then
releases them, letting tests assert `max_in_flight` exactly rather than
relying on timing. The ordering test goes further by assigning
reverse-listing response delays so the last-listed model always finishes
first; if the index sort were dropped, the JSON result order would
invert and the assertion would fail. A 15-second gate timeout ensures a
regression to serial execution surfaces as a clear `max_in_flight == 1`
failure rather than a hung test.

Existing behavior is fully preserved: unconfigured models are still
skipped without a POST, a configured model returning `skip` after
listing is still a failure, `--deep` uses the same `--jobs` value, and
`--jobs 1` reproduces the previous serial behavior for users hitting
provider rate limits.

### Fabro Details

<details>
<summary>Ran 9 stages in 30m 52s for $19.61</summary>

| Stage | Duration | Cost | Retries |
|---|---|---|---|
| start | 0s | – | 0 |
| toolchain | 1s | – | 0 |
| preflight_compile | 2m 8s | – | 0 |
| preflight_lint | 2m 21s | – | 0 |
| implement | 8m 56s | $3.87 | 0 |
| simplify_opus | 7m 55s | $1.43 | 0 |
| simplify_gpt | 6m 58s | $14.32 | 0 |
| verify | 1m 49s | – | 0 |
| fmt | 2s | – | 0 |
| **Total** | **30m 52s** | **$19.61** | **0** |

</details>

<details>
<summary>Ran <code>ImplementPlan.fabro</code> (12 nodes and 15
edges)</summary>

```dot
digraph ImplementPlan {
    graph [
        goal="Implement and simplify",
        model_stylesheet="
            * { model: claude-opus-4-7; }
        "
    ]
    rankdir=LR

    start [shape=Mdiamond, label="Start"]
    exit  [shape=Msquare, label="Exit"]

    toolchain         [label="Toolchain", shape=parallelogram, script="command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1", max_retries=0]
    preflight_compile [label="Preflight Compile", shape=parallelogram, script="cargo check -q --workspace 2>&1", max_retries=0]
    preflight_lint    [label="Preflight Lint", shape=parallelogram, script="cargo +nightly-2026-04-14 clippy -q --workspace --all-targets -- -D warnings 2>&1", max_retries=0]
    fix_lints         [label="Fix Lints", prompt="The preflight lint step failed. Read the build output from context and fix all clippy lint warnings.", max_visits=3]
    implement         [label="Implement", prompt="Read the plan file referenced in the goal and implement every step. Make all the code changes described in the plan. Use red/green TDD."]
    simplify_opus     [label="Simplify (Opus)", prompt="@prompts/simplify.md"]
    simplify_gpt      [label="Simplify (GPT-55)", prompt="@prompts/simplify.md", model="gpt-55"]
    verify            [label="Verify", shape=parallelogram, script="cargo +nightly-2026-04-14 clippy -q --workspace --all-targets -- -D warnings 2>&1 && cargo nextest run --cargo-quiet --workspace --status-level fail 2>&1 && cargo dev docs refresh 2>&1 && cargo dev docs check 2>&1", goal_gate=true, retry_target="fixup"]
    fixup             [label="Fixup", prompt="The verify step failed. Read the build output from context and fix all clippy lint warnings, test failures, and generated docs errors.", max_visits=3]
    fmt               [label="Format", shape=parallelogram, script="cargo +nightly-2026-04-14 fmt --all 2>&1", max_retries=0]

    start -> toolchain
    toolchain -> preflight_compile [condition="outcome=succeeded"]
    toolchain -> exit
    preflight_compile -> preflight_lint [condition="outcome=succeeded"]
    preflight_compile -> exit
    preflight_lint -> implement [condition="outcome=succeeded"]
    preflight_lint -> fix_lints
    fix_lints -> preflight_lint
    implement -> simplify_opus -> simplify_gpt -> verify
    verify -> fmt   [condition="outcome=succeeded"]
    verify -> fixup
    fixup -> verify
    fmt -> exit
}

```

</details>

⚒️ Generated with [Fabro](https://fabro.sh)

---------

Co-authored-by: Fabro <noreply@fabro.sh>
2026-05-04 13:46:44 -04:00
..
archive.rs chore(test): extract TestContext::set_http_target helper 2026-04-30 10:11:47 -04:00
artifact_cp.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
artifact_list.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
attach.rs test(cli): align attach JSON snapshot with new OpenAI default 2026-05-04 11:54:45 -04:00
auth.rs test(cli): tighten env-dev-token-ignore tests 2026-05-01 16:25:13 -04:00
config.rs migrate cli install tests off sparse settings layers 2026-04-23 18:37:37 -04:00
create.rs chore(test): extract TestContext::set_http_target helper 2026-04-30 10:11:47 -04:00
diff.rs test(cli): prune slow integration outliers 2026-04-28 19:26:27 -07:00
discord.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
docs.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
doctor.rs chore(clippy): require reasons on allow attributes 2026-04-19 20:24:24 -04:00
dump.rs feat(run): separate stage state and artifact retries 2026-05-01 20:10:47 -04:00
exec.rs chore(test): extract TestContext::set_http_target helper 2026-04-30 10:11:47 -04:00
fabro.rs feat(cli): rename store dump to dump 2026-04-23 07:48:03 -04:00
fork.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
graph.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
inspect.rs feat(run): separate stage state and artifact retries 2026-05-01 20:10:47 -04:00
install.rs fix(install): reject wildcard public URLs 2026-04-25 18:58:00 -04:00
json_global.rs fix(cli): remove dev-token env auth override 2026-05-01 15:04:01 -04:00
logs.rs Unify run event principals 2026-05-01 21:56:47 -04:00
mod.rs remove(cli): drop pr list command entirely 2026-04-24 08:56:07 -04:00
model.rs chore(catalog): add GPT-5.5 and GPT-5.5 Pro, set 5.5 as OpenAI default 2026-05-04 11:12:40 -04:00
model_list.rs refactor(cli): separate local socket and storage defaults 2026-04-06 11:57:14 -04:00
model_test.rs Model Test Bounded Concurrency Implementation Plan (#204) 2026-05-04 13:46:44 -04:00
parse.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
pr.rs remove(cli): drop pr list command entirely 2026-04-24 08:56:07 -04:00
pr_close.rs refactor(pr): simplify server-side PR plumbing 2026-04-24 11:17:01 -04:00
pr_create.rs refactor(types): remove stage status compatibility 2026-04-30 06:48:47 -04:00
pr_merge.rs refactor(pr): simplify server-side PR plumbing 2026-04-24 11:17:01 -04:00
pr_view.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
preflight.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
provider.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
provider_login.rs Complete provider credential auth and scripted install 2026-04-13 09:15:45 -04:00
ps.rs test(cli): tighten env-dev-token-ignore tests 2026-05-01 16:25:13 -04:00
render_graph.rs lint(clippy): disallow blocking std::io and std::net on Tokio paths 2026-04-19 16:06:02 -04:00
repo.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
repo_deinit.rs refactor(config): move project state under .fabro 2026-04-11 12:55:46 -04:00
repo_init.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
resume.rs test(cli): prune slow integration outliers 2026-04-28 19:26:27 -07:00
rewind.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
rm.rs chore(test): extract TestContext::set_http_target helper 2026-04-30 10:11:47 -04:00
run.rs feat(api): expose web_url on run responses and run.created event 2026-05-03 18:18:19 -04:00
runner.rs fix(test): align worker token fixtures with auth routing 2026-05-02 12:08:00 -04:00
sandbox_cp.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
sandbox_preview.rs Make git metadata sandbox-native 2026-04-27 21:43:15 -07:00
sandbox_ssh.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
secret.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
secret_list.rs feat: add typed secrets metadata and API 2026-04-12 12:47:08 -04:00
secret_rm.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
secret_set.rs test(cli): align stale CI snapshots 2026-04-24 19:53:02 -04:00
send_analytics.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
send_panic.rs refactor(cli): deglobalize server and storage target flags 2026-04-05 16:06:42 -04:00
server_start.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
server_status.rs refactor(server): unify daemon runtime metadata 2026-04-22 16:07:52 -04:00
server_stop.rs refactor(test): promote shared server-lifecycle test helpers into fabro-test 2026-04-19 16:43:26 -04:00
start.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
support.rs Merge remote-tracking branch 'origin/main' 2026-05-02 10:06:25 -04:00
system.rs feat(system): add server-backed system commands 2026-04-06 16:10:06 -04:00
system_df.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
system_events.rs refactor(cli): finish command context cleanup 2026-04-23 07:14:32 -04:00
system_info.rs refactor(cli): finish command context cleanup 2026-04-23 07:14:32 -04:00
system_prune.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
test_panic.rs test: speed up slow default-profile tests and tighten nextest thresholds 2026-04-05 13:15:59 -04:00
top_level.rs feat(cli): show curated landing output for bare fabro 2026-04-17 08:59:03 -04:00
unarchive.rs chore(test): extract TestContext::set_http_target helper 2026-04-30 10:11:47 -04:00
uninstall.rs refactor(server): unify daemon runtime metadata 2026-04-22 16:07:52 -04:00
upgrade.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
validate.rs fix(cli): keep validate off runtime preflight 2026-04-28 14:50:04 -07:00
version.rs feat(cli): add fabro version command 2026-04-14 16:30:53 -04:00
wait.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
worker_auth.rs fix(test): align worker token fixtures with auth routing 2026-05-02 12:08:00 -04:00
workflow.rs test(cli): refresh list output expectations 2026-04-14 11:30:34 -04:00
workflow_create.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00
workflow_list.rs feat(cli): render fatal errors with miette 2026-04-24 15:35:57 -04:00