Fix rust-rulebook.md drift - #32
Merged
Merged
Conversation
Continuous integration never ran doctests for two of the workspace's crates: the concurrent test runner skips doctests and the workspace doctest step excludes them, so a dedicated step now covers both. A new aggregate job gives branch protection a single required status check that fails when any job fails or is cancelled, so a cancelled job can no longer read as green. An unused development dependency is removed from the speech-to-text crate. - `.github/workflows/ci.yml`: places the doctest step in the check-workshop job rather than the Linux test job, with a comment recording that nextest does not run doctests. - `ci-green`: runs under if: always() and exits nonzero unless every job in its needs list reports success; the list is static, so each future job must be added to it or it bypasses the gate. - `crates/gateway-stt/Cargo.toml`: drops the unreferenced tracing-subscriber dev-dependency, with the lockfile updated to match. Plan: vibe/2026-09-11-1-rulebook-debt-tiers.md
Four destructors that used to block on thread joins or a bounded network shutdown now only signal and detach, with explicit shutdown methods remaining the blocking, error-reporting path. Two error variants that discarded their underlying causes now carry them as sources, so printed error chains name the real failure. The session-agent supervisor event pipe is split by loss-tolerance: events the reducer awaits keep guaranteed delivery on the unbounded queue, while operator cancellations ride a bounded queue that drops redundant duplicates. - `Transcriber::signal_and_detach` - Drop and `abandon_startup` share one signal-and-detach path; the worker captures only owned and Arc state, so a detached thread finishes a running decode on its own. - `RecoveryCandidate::shutdown` - the new explicit fallible path owns the bounded shutdown request and disarms the drop signal even on failure, because the caller owns the outcome. - `SupervisedGatewayIdentity` - the default no-op `shutdown_unpublished` hook lets the failed-replacement-publish arm shut down an unpublished recovered child through the explicit path. - `RunLifecycle` - events split by loss-tolerance: `OperatorCancellation` alone rides a bounded queue of `CANCELLATION_CAPACITY` 1, since a full queue already holds a pending cancellation that retires the current run; settlements and close keep the unbounded guaranteed queue. - `Drop for SttEngine` - signals both workers and detaches their threads instead of running the blocking shutdown join. - `Drop for GatewaySupervisor` - revokes publication, signals the stop, and detaches both threads instead of joining within the shutdown budget. - `Drop for RecoveryCandidate` - runs the late-child shutdown request on a detached named thread instead of blocking the dropping thread. - `SessionError::Inference` - now carries the engine error as its source, and SessionError drops Eq and PartialEq because TranscribeError is not PartialEq. - `AudioError::InvalidBase64` - now carries the base64 decode failure as its source; both restored variants are `#[non_exhaustive]`. - `next_lifecycle_event` - a biased select drains the guaranteed queue before the bounded cancellation queue; cross-channel ordering is not load-bearing. - `InterimTaskOutput::Decode` - the interim transcript no longer stringifies the engine error; the result stays typed from decode through `finish_interim`. Design: extends message-passing @ crates/workshop-server/src/session_agents/lifecycle.rs::RunLifecycle Repairs: non-blocking Drop @ crates/gateway-stt-engine/src/engine.rs::SttEngine - dropping the engine during a running decode blocked until the decode finished Repairs: non-blocking Drop @ crates/gateway-stt-engine/src/worker.rs::Transcriber - dropping the transcriber joined the worker thread mid-decode Repairs: non-blocking Drop @ crates/workshop/src/gateway/supervisor.rs::RecoveryCandidate - dropping an unpublished candidate blocked on the late-child shutdown budget Repairs: non-blocking Drop @ crates/workshop/src/gateway/supervisor.rs::GatewaySupervisor - dropping the supervisor waited out the shutdown budget Repairs: bounded supervisor event queue @ crates/workshop-server/src/session_agents/lifecycle.rs::RunLifecycle - repeated operator cancellations grew the event queue without bound Plan: vibe/2026-09-11-1-rulebook-debt-tiers.md
Marks seven public types and error variants non-exhaustive so each can gain fields or variants without breaking downstream matches, and converts lint suppressions across the workspace from blanket allows to reasoned expects so a suppression that stops firing fails the build. Suppressions that had already gone stale were deleted outright, and match sites downstream of the newly non-exhaustive decode mode gained wildcard arms. Runtime behavior is unchanged apart from one defensive exit path.
- `#[non_exhaustive]` now marks `DecodeMode`, `DecodeRequest`, `EnginePolicy`, `GatewayStartup`, `ValidatedConnection`, and the `OwnerTimeout` and `GatewayPublicationError::Build` variants, so downstream matches must carry a wildcard arm and each type can grow without a breaking change.
- `Ok(_) =>` in `crates/gateway/src/main.rs` prints an error and returns `ExitCode::FAILURE` on any unrecognized future startup decision instead of falling through.
- `#[cfg_attr(` gates the suppressions that only fire in non-test builds (`FaultInjector`, `ProvisionModel`, `UnloadModel`, `sys_live_handle`, `DelimiterGroup::family`), keeping test builds free of unfulfilled expectations.
- `_ => return Ok(None)` in `WhisperModelFactory::load` treats an unrecognized decode mode as no model to load, while the scripted test factories `unreachable!` on one because their scripts only produce interim and final.
- `#[allow(dead_code)]` on `GatewaySource::ready`, `Request::Mcp`, `BindSchema`, and `NearDuplicateTools` was stale and is deleted rather than converted.
- `#[allow(clippy::expect_used)]` on `blocked_interim_keeps_exact_budget_until_worker_retirement_and_commit_retries`, `blocked_final_keeps_budget_after_epoch_cancellation_until_worker_retirement`, and `append_after_retirement` was stale and deleted.
- `#[allow(unused_imports)]` on the `parse_client_event` and `shared::{ClientError, ClientEvent, IdGenerator}` re-exports was stale and deleted; the `server` re-export keeps its suppression as an expect.
- `clippy::ref_as_ptr` was dropped from the `bridge.rs` test-module suppression list as no longer firing.
Plan: vibe/2026-09-11-1-rulebook-debt-tiers.md
Four in-process async tests now run on a paused clock, so their timeouts and cancellation races resolve deterministically instead of depending on wall-clock timing. The three affected crates enable the async runtime's test-utilities feature for their test builds, which makes the paused clock available. One rendezvous test no longer races a timer-based late arrival against a real-time wait; the late arrival now starts only after the rendezvous has timed out, staying deterministic while the paused clock auto-advances on idle. One cancellation test moves from a multi-thread runtime to a current-thread runtime, which pausing requires. No production code changes. - `crates/gateway-stt-engine/src/test_fixtures/tests/scenario_cleanup/decode.rs` spawns the late decode only after the rendezvous times out instead of racing it on a 50-millisecond timer; the oneshot channel that published the decode handle is removed. - `crates/promptforge-core/src/execute/tests/input.rs` runs `cancellation_interrupts_a_pending_input_wait` on `current_thread` instead of `multi_thread` with two worker threads, which `start_paused` requires. - `crates/gateway-stt-engine/Cargo.toml`, `crates/promptforge-core/Cargo.toml`, and `crates/promptforge-lua/Cargo.toml` add the `test-util` feature to the tokio dev-dependency. - `crates/promptforge-core/src/execute/tests/scheduler.rs` and `crates/promptforge-lua/src/dispatch.rs` gain `start_paused = true` with no body changes; their in-test sleeps now resolve on the paused clock. - `vibe-ledger.md` records the component-scope verify pass and the conversion decisions with their falsifiers. Plan: vibe/2026-09-11-1-rulebook-debt-tiers.md
Failure channels in the take pipeline, the realtime session, and the fixture API carried bare strings, so downstream classification compared message text and wrapped causes were discarded. Typed error enums now represent take failures, item finalization failures, and fixture operations, with sources retained and shared by reference where a failure crosses from the take into session gating. Every affected signature, assertion, and test moves to the typed form while the user-visible message text stays unchanged. - `TakeFailure` is a new thiserror enum of thirteen variants, retained as `Arc<TakeFailure>` because pending-failure reads clone it out of the take mutex for session precommit gating. - `FixtureError` is a new public non-exhaustive thiserror enum with twenty-two operation-named variants; crate-internal sources are boxed, while `SpeechError` and `serde_json::Error` are carried concretely. - `FinalizationError` types the item finalization join failures, and `SessionError::Finalization` now wraps it transparently. - `ClientError` gains Display and Error trait impls that write its message field. - `from_precommit` classifies on the typed variant instead of comparing message text. - `fail_precommit` and `replace_finalization` wrap caller-supplied strings in the test-gated `TakeFailure::Recorded` variant, preserving the string-injection hook. - `source_message` helpers in both integration suites assert the operation message on the fixture error and the original message on its source. - `PendingPrecommitFailure` carries `Arc<TakeFailure>` formatted inline, with no source chain. - `ItemFailure` keeps string payloads on the wire terminal; only its classification became typed. Design: removes stringly-typed @ crates/gateway-stt/src/test_fixtures.rs boundary: pub Design: removes stringly-typed @ crates/gateway-stt/src/take/state.rs::TakeState::record_failure Design: removes stringly-typed @ crates/gateway-stt/src/realtime/route.rs::RoutePolicy::precommit_failure Design: removes stringly-typed @ crates/gateway-stt/src/realtime/result_mailbox.rs::ItemFailure::from_precommit deps: TakeFailure Plan: vibe/2026-09-11-1-rulebook-debt-tiers.md
Test-only validators, build scripts, and build-tool binaries now report failures through anyhow instead of owned strings, while the remaining private production helpers return their crates' existing typed error enums. Two new private error enums give the tool-call parser and the profile-switch driver one variant per rejection, and each variant renders exactly the message the bare string carried, because those texts are wire warnings and user-facing descriptions. The cached Lua shim programs now keep a shared typed cause and re-wrap it at each install rather than flattening it to a string. No error message text changes. - `ToolCallRejection` is a new private thiserror enum with one variant per tool-call rejection; its display text becomes the turn's gateway_warning verbatim, so each variant keeps the exact string the bare channel carried, including the retained serde_json cause on the arguments variant. - `SwitchFailure` is a new private enum for profile-switch failures; its Transport variant keeps the gateway client error as the source while Refused and Failed relay the gateway's own messages, and the display text is what the failure status pushes to the user. - `Error::shared` re-wraps a cached SharedSource as a typed Error::LuaRuntime by cloning the Arc, and both LazyLock program statics now store that shared cause instead of a flattened string. - `parse_whoami_user_sid` takes the cache root and returns LocalError::CacheNotPrivate directly, folding every parse rejection into the existing enum instead of returning a reason string for the caller to wrap. - `anyhow::Result` replaces the string channel in the build-ui helper, the gateway build script, both build-tool argument parsers, the cfg(test) wire validators, and the test-fixture rendezvous; gateway and gateway-stt gate the new dependency behind the test-fixtures feature. - `replace_finalization` accepts anyhow futures from tests and stringifies only at the TakeFailure::Recorded boundary. - `Index::new` returns IndexError::layout for each broken invariant, so the picker drops its map_err. - `crates/gateway-local/src/artifacts/tests.rs` changes only to pass the cache path and compare message text, asserting the same failures as before; no behavior or message text changes anywhere in the diff. Design: removes stringly-typed @ crates/gateway/src/dialect.rs::parse_openai_tool_calls deps: Value Design: removes stringly-typed @ crates/gateway/src/config_write.rs::json_to_toml deps: Value Design: removes stringly-typed @ crates/gateway-local/src/artifacts/confine.rs::parse_whoami_user_sid deps: Path,bool,u8 Design: removes stringly-typed @ crates/workshop-server/src/session/menu.rs::drive_switch deps: GatewayClient,Push,str Design: removes stringly-typed @ crates/promptforge-tool-picker/src/rank.rs::Index::new Design: removes stringly-typed @ crates/promptforge-lua/src/coro.rs::SHIM_PROGRAM Design: removes stringly-typed @ crates/promptforge-lua/src/messages/mod.rs::MESSAGES_PROGRAM Design: removes stringly-typed @ crates/build-llama-cuda/src/main.rs::parse_args deps: String Design: removes stringly-typed @ crates/build-ui/src/lib.rs boundary: pub Design: removes stringly-typed @ crates/build-workshop/src/main.rs Design: removes stringly-typed @ crates/gateway/build.rs Design: removes stringly-typed @ crates/gateway/src/main.rs::wait_for_test_start_rendezvous Design: removes stringly-typed @ crates/gateway/src/test_support.rs::app_state_with_scripted_stt deps: Config,ScriptedModelFactory Design: removes stringly-typed @ crates/gateway-stt/src/realtime/wire/server.rs Design: removes stringly-typed @ crates/gateway-stt/src/test_fixtures.rs::RealtimeSessionFixture::replace_finalization boundary: pub Plan: vibe/2026-09-11-1-rulebook-debt-tiers.md
Plan: vibe/2026-09-11-1-rulebook-debt-tiers.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.