-
Notifications
You must be signed in to change notification settings - Fork 0
Failures and ECAM
The loop that justifies the whole project: inject a failure → the aircraft reports it on the ECAM → manage it with the controls. This page covers both halves — the failure catalog and the (homegrown) ECAM detection layer.
Failures are injected by stable ids that are ours, not FBW's enum. The catalog lives in
core-rs/src/failures.rs.
| API | CLI | MCP (interactive) |
|---|---|---|
inject_failure(id) |
fail <id> |
inject_failure(failure_id) |
clear_failure(id) |
unfail <id> |
clear_failure(failure_id) |
list_failures() |
failures |
list_failures |
active_failures() |
shown by failures (*) |
(not exposed — see below) |
Each catalog entry has: a stable id (e.g. elec.tr.1), a description, a group, and ata — the
ATA chapter id FBW uses for the same failure, copied as a cross-reference.
Behavior worth knowing:
-
Takes effect on the next tick. Follow
failwithrun 2(orwatch) to let the systems settle and reconfigure. The active set is re-sent to the vendor every tick, so inject-before-tick ordering doesn't matter. - Idempotent. Injecting twice, or clearing something inactive, is a no-op, not an error — it's set semantics, so an agent needn't track state.
-
Stable across vendor bumps.
elec.tr.1keeps meaning the same thing after a pin bump; a bump becomes a visible diff (or a compile error if a variant disappears), not a silent renumbering.
FBW's FailureType derives only Clone, Copy, PartialEq, Eq, Hash — no Debug, no Serialize, no
numeric id — and its shape changes with the pin. There is nothing safe to expose directly, so the
project owns a hand-written mapping. Scope grows by phase: today the catalog is the electrical (ATA 24)
failures — generators, TRs, static inverter, buses — the systems the current phases can observe.
There is no battery or contactor failure anywhere in FBW's enum. The nearest proxy to "battery loss" is
elec.bus.dc_bat. The project does not invent an id the vendor can't honor.
CLAUDE.md originally anticipated read_ecam() would "map the FWC's warnings." There is no FWC in
the vendored Rust — zero matches for FlightWarningComputer, master_caution, or master_warning
across the tree, and the vendor itself says so (surveillance.rs: "TODO: Comes from FWC"). The
TypeScript ECAM isn't even vendored (the submodule is sparse-checked-out to the WASM systems only).
So read_ecam() is a homegrown rule engine over variables the Rust does write, in
core-rs/src/ecam.rs — not a
mapping of a nonexistent FWC. Full evidence:
docs/fase2-ecam.md.
Each read_ecam() entry carries id, message (the ECAM text, e.g. "APU GEN FAULT"), severity
(warning > caution > advisory, worst first), system, and source:
-
source = vendor_flag([fbw]in the CLI) — the flag is computed by FlyByWire's own model (a pushbutton's FAULT light). -
source = derived([ours]in the CLI) — the rule is ours (e.g. "TR powered but without normal potential").
That distinction is not cosmetic: it is the boundary between inherited and invented ground truth. The research contribution is the evaluable environment; if you can't say which part of the ground truth is FBW's, you can't say what the benchmark measures. So it is recorded per rule and surfaced all the way to the CLI and the binding.
Without an FWC there is no phase inhibition. The rules are evaluated only if the ECAM would be
alive (AC ESS or DC ESS powered); otherwise read_ecam() returns an empty list. In cold & dark
the ECAM is empty because it isn't powered — exactly as on the real aircraft. An empty ECAM on an
unpowered aircraft is not evidence that nothing is wrong.
Losing the APU generator when it is the only AC source raises two cautions, and that is correct:
fail elec.apu_gen.1
run 5
ecam
CAUTION AC ESS BUS FAULT (ELEC) [fbw]
CAUTION APU GEN FAULT (ELEC) [fbw]
APU GEN FAULT is the source fault; AC ESS BUS FAULT is the downstream bus going dark because the
APU GEN was the only source. The ECAM stays readable because the batteries hold DC ESS alive — which
is exactly why the power gate looks at AC ESS or DC ESS. Managing the cascade (not an isolated
message) is the task. This is the scenario in Scenarios and the MCP-Server.
See Design-Decisions (D-013, D-014) for the full rationale.
A320 Systems Twin · GPLv3 · systems model by FlyByWire (vendored, pinned to 13bce4b) · repository
Get started
Operate
Benchmark
Reference