Skip to content

Failures and ECAM

santisoutoo edited this page Jul 24, 2026 · 1 revision

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.

Injecting failures

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 fail with run 2 (or watch) 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.1 keeps 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.

Why stable ids (D-013)

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.

Reading the ECAM

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.

Warning fields

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.

The power gate

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.

Worked cascade: APU GEN FAULT

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.

Clone this wiki locally