Expand description
bhtune — the headless adapter (Rust library target bhtune_cli).
Builds the bhtune binary: a scriptable, no-GUI way to run an MRFT tune and inspect its
history, intended for scheduled/unattended use (cron, CI, batch tuning campaigns) as well
as interactive terminal use.
args— theclapderiveCli/Commanddefinitions and the wrapper enums adaptingbhtune-core’s domain enums toclap::ValueEnum(required by Rust’s orphan rule).config,db,driver,logging, andretention— re-exports ofbhtune-runtimeservices used by CLI command handlers. Configuration precedence, database bootstrap/seeding, driver construction, logging, and retention behavior are shared with the HTTP adapter rather than implemented here.commands— one module per subcommand family:check,tune/simulate,template,history,export,opc.output— CLI-specific--output table|jsonformatting and error presentation; shared sample export serialization is provided bybhtune-runtime.
main.rs stays a one-line delegator to run; run_with_cli is the internal entry
point, kept separate so tests can exercise it against an already-parsed args::Cli
without needing to control std::env::args() — mirroring opcda-bridge-client’s
run/run_with_cli split. Logging is initialized in run, not run_with_cli, for
the same reason: it keeps tracing setup (and its process-global, only-succeeds-once
subscriber installation) entirely out of run_with_cli’s own large, injection-based test
suite – see logging’s test module doc comment.
Non-interactive/scheduled use (cron, CI, batch campaigns) is tune/simulate’s
--yes/--write-pid <level> flags (bypassing the interactive write-back prompt) plus
the global [tuning] timing configuration, which mandatorily bounds unattended runs and
caps individual driver operations, and this module’s distinguished exit codes
(EXIT_ABORTED, EXIT_TIMED_OUT,
EXIT_POOR_QUALITY, EXIT_ACTUATION_FAILED, EXIT_WRITE_BACK_FAILED,
EXIT_RESTORE_INCOMPLETE), so a
scheduler can tell “aborted”, “timed out”, “the plant data couldn’t be trusted”, “test ran
but the write-back failed”, “the loop may not have been fully restored”, and “never ran at
all” apart without parsing stdout. See AGENTS.md’s cli-automation/cli-safety sections.
Modules§
- args
- Command-line argument definitions (
clapderive) and the small wrapper enums that adaptbhtune-core’s domain enums toclap::ValueEnum. - cancel
- A single, process-wide Ctrl+C listener shared by every await point in a tune. Registering
the signal exactly once, as early in the process as possible, closes the gap where a
Ctrl+C delivered while no listener happens to be alive is silently swallowed – tokio
installs a process-wide
SIGINThandler the first timectrl_c()is polled and never reverts to the OS default, so a lost signal isn’t merely unhandled, it’s gone. - commands
- One module per subcommand family.
- config
- Global bhtune configuration, including the shared
[tuning]timing policy and theCLI flag > env var > TOML config file > built-in defaultprecedence used by settings that expose command-line or environment overrides. - db
- Opens the CLI’s database for mutating commands, seeds the built-in and user-catalog
DCS/PLC templates, and runs the retention sweep. Read-only commands such as
bhtune checkuse a separate connection that skips bootstrap and retention. - driver
- Constructs the selected
bhtune_driver::Driverimplementation from aTuneRequest. - gateway
- Shared opcda-bridge compatibility checks for live mutations and inspection surfaces.
- logging
- Shared structured application logging, matching
opcda-bridge-gateway’s owntracingstack andlog.*configuration conventions (level/directory/format/rotation, resolved with the sameCLI flag > env var > config file > defaultprecedence as every other bhtune setting) – seecrate::config::LogConfig/resolve_log_settings. - output
- Output format selection for
history list,history show,tune, andsimulate. These commands support--output json; other commands keep their existing human-readable output. - retention
- Age-based deletion of old tune runs.
Constants§
- EXIT_
ABORTED - A
tune/simulaterun was aborted (Ctrl+C) before it finished; the loop was restored to its pre-test mode. Distinct fromEXIT_FAILUREso a scheduler can tell “someone intentionally stopped this” apart from “this broke”. - EXIT_
ACTUATION_ FAILED - A live OPC DA tune was aborted because an accepted MV command could not be confirmed at
the controller before its deadline or before a replacement relay command was required.
The ordinary restore path still ran;
EXIT_RESTORE_INCOMPLETEtakes precedence if that restore could not itself be confirmed. - EXIT_
CHECK_ FAILED - A
checkpreflight completed, but one or more checks failed or--strictrejected a warning. The command never starts a tune. - EXIT_
FAILURE - A setup problem (bad flags, an unreadable config file, a database error, an unexpected
driver error) prevented the command from running to completion at all. Equal to
ExitCode::FAILURE. - EXIT_
POOR_ QUALITY - A
tune/simulaterun was aborted because a driver reported a non-GoodOPC quality for a tuning-critical reading (finding 5 of the live-plant safety review): an initial reading, the transition-to-manual setpoint capture, or an in-flight PV poll sample, and (for the in-flight case) the global Config > OPC quality policy rejectedUncertain, or the quality wasBadrather than merelyUncertain. The loop was restored to its pre-test mode, exactly likeEXIT_ABORTED/EXIT_TIMED_OUT. Distinct from both so a scheduler’s alerting can tell “the plant data itself couldn’t be trusted” apart from a user-initiated stop or a run that simply took too long. Seecommands::tune::TuneOutcome::PoorQualityand AGENTS.md’ssafety-qualitysection. - EXIT_
RESTORE_ INCOMPLETE - A
tune/simulaterun ended (via normal completion, Ctrl+C, or a timeout) without being able to confirm the loop was fully restored to its pre-test mode/MV/setpoint – either a second Ctrl+C was received while the restore was in flight, or[tuning].restore_timeout_secselapsed first. Distinct from every other exit code because it means the loop may have been left mutated with no further attempt made to fix it: an operator must check it by hand, using the tag/value named in the warning printed to stderr. Seecommands::tune::TuneOutcome::RestoreIncompleteand AGENTS.md’ssafety-cancellationsection. - EXIT_
SUCCESS - Process exited normally, and if this was
tune/simulate, any PID write-back either succeeded or was cleanly skipped. Equal toExitCode::SUCCESS. - EXIT_
TIMED_ OUT - A
tune/simulaterun was aborted because[tuning].timeout_secselapsed before the engine reported completion; the loop was restored to its pre-test mode, exactly likeEXIT_ABORTED. Distinct from it so a scheduler’s alerting can tell “this run had to be killed for running too long” (possibly a stuck relay, a misconfigured tag mapping, or a stalled driver read – worth investigating) apart from “an operator stopped it on purpose” (routine). Seecommands::tune::TuneOutcome::TimedOutand AGENTS.md’scli-safetysection. - EXIT_
WRITE_ BACK_ FAILED - A
tune/simulaterun completed the MRFT test itself, but writing the selected PID constants back to the DCS failed (the write was rejected, errored, or its confirmation readback didn’t match). Distinct from bothEXIT_SUCCESS(nothing to report) andEXIT_FAILURE(the test itself never produced a result) so an unattended--write-pid/--yesrun can tell “the test ran fine but the loop was NOT updated” apart from either of those. Seecommands::tune::TuneOutcomeand AGENTS.md’scli-automationsection.
Functions§
- run
- Parses real CLI arguments, initializes structured logging, and runs, returning a process exit code.