fabro/lib/crates/fabro-cli/src
fabro-sh-0530[bot] 01892185ff
Replace bare unwrap() with documented expect() across production runtim… (#415)
Audit and remediation pass enforcing the project's
no-panic-in-production policy. Every `unwrap()` on a mutex/RwLock in
reachable runtime code is replaced with `expect()` carrying a message
that explains *why* the lock cannot be poisoned (no code panics while
holding it). Bare `unreachable!()` and `panic!()` calls are updated with
messages that name the invariant being asserted. One genuine bug is
fixed in the process.

## What changed

**`unwrap()` → `expect()` on locks** (`fabro-core`, `fabro-oauth`,
`fabro-util`, `fabro-workflow/*`, `fabro-server`): Every
`Mutex`/`RwLock` `.unwrap()` in production paths now carries the
standard justification pattern: `"<name> mutex/RwLock should not be
poisoned: no code panics while holding this lock"`.

**`unreachable!()` and `panic!()` message quality**: Bare
`unreachable!()` calls in `subagent.rs`, `wait.rs`, `condition.rs`,
`event/convert.rs`, and `server.rs` now name the structural invariant
(e.g. "outer match arm already verified…"). The `panic!` in `tools.rs`
now includes the offending name and the expected format, making it
actionable.

**`sha_newtype` / `short_sha_newtype` in `run_files.rs` — actual bug
fix**: These helpers previously called `unwrap_or_else(|e| panic!(…))`
on git output, meaning a malformed SHA from a real git subprocess would
panic in a request handler. They now return `Result<T, ApiError>` and
propagate errors to callers, which in turn propagate with `?`. This is
the only change that alters observable behavior under failure.

**Demo-only panics in `fabro-server/src/demo/mod.rs`**: Panic messages
updated to clarify that these paths operate on hardcoded compile-time
constants, so the panic is a programming-error guard rather than a
runtime failure guard.

## Design note

The lock-poisoning `expect` messages all follow a single template so
reviewers can quickly verify the claim: if you ever add code that can
panic inside a lock guard scope, the message becomes a lie and that must
be caught in review. The uniformity is intentional.


### Fabro Details

<details>
<summary>Ran 0 stages in 64m 54s for $14.28</summary>

| Stage | Duration | Cost | Retries |
|---|---|---|---|
| **Total** | **64m 54s** | **$14.28** | **0** |

</details>

<details>
<summary>Ran <code>Goal.fabro</code> (4 nodes and 5 edges)</summary>

```dot
digraph Goal {
    graph [
        goal="Complete the user-provided goal",
        rankdir=LR,
        max_node_visits=30
    ]

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

    work [
        label="Work",
        thread_id="goal",
        fidelity="full",
        max_visits=12,
        prompt="@prompts/continue.md"
    ]

    audit [
        label="Completion Audit",
        thread_id="goal",
        fidelity="full",
        goal_gate=true,
        retry_target="work",
        output_schema="routing",
        output_retries=2,
        max_visits=12,
        prompt="@prompts/audit.md"
    ]

    start -> work -> audit

    audit -> exit [label="Done", condition="outcome=succeeded"]
    audit -> work [label="Continue", condition="outcome=failed || preferred_label=Continue"]
    audit -> work [label="No clear verdict"]
}

```

</details>

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

---------

Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: Bryan Helmkamp <bryan@brynary.com>
2026-05-26 17:46:39 -04:00
..
commands Replace bare unwrap() with documented expect() across production runtim… (#415) 2026-05-26 17:46:39 -04:00
shared refactor(auth): split credential sources and vault schemas (#306) 2026-05-18 11:07:42 -04:00
sleep_inhibitor fix sleep_inhibitor lints under --all-features clippy 2026-04-23 22:45:07 -04:00
args.rs feat: Add approve/deny run controls to MCP and CLI (#400) 2026-05-25 15:49:57 -04:00
command_context.rs feat(llm): add catalog controls and speed billing (#249) 2026-05-13 14:12:16 -04:00
gh.rs test(cli): trim slow integration fixture setup 2026-04-28 19:14:56 -07:00
landing.rs feat(cli): split run events and raw logs 2026-05-06 13:29:35 -04:00
local_server.rs fix(error): preserve source chains across workspace 2026-05-01 17:30:20 -04:00
logging.rs fix(cli): keep run logs free of ANSI 2026-05-07 07:28:25 -07:00
main.rs feat(agent): expose Fabro run tools in sessions (#339) 2026-05-21 19:48:54 -04:00
manifest_args.rs Replace run-scoped sandbox config with named environments (#360) 2026-05-23 13:03:21 -04:00
server_client.rs refactor(install): share persistence pipeline (#332) 2026-05-21 08:04:04 -04:00
server_runs.rs feat: Replace duration/elapsed fields with wall_time_ms and StageTiming (#343) 2026-05-21 21:06:40 -04:00
user_config.rs fix(error): preserve source chains across workspace 2026-05-01 17:30:20 -04:00