Skip to content

Verified: Forcing

Each claim the Forcing page makes, with the tests that prove it in the last green CI run: 9 of 16 verified. The claims live in docs/claims/forcing.yaml.

Last green CI run 16 Oct 2026, 14:48 UTC on c7618d3 · all runtime claims

FRC-001 verified

A force on an input replaces the driver's reading before the logic runs, every scan, so the program sees the forced value.

where the docs say so

  • pass TestForceInputOverridesDriver in runtime

FRC-002 verified

A force on an output or state tag is laid back over whatever the logic wrote every scan, so the driver is handed the forced value.

where the docs say so · TestForceOutputReappliedAfterLogic holds Alarm FALSE while the logic writes TRUE every scan (it never reads itself back) and checks the tag and the driver's output on each scan.

  • pass TestForceHoldsAgainstPlantAndLogic in acceptance
  • pass TestForceOutputReappliedAfterLogic in runtime

FRC-003 verified

Forcing a struct member (P101.Speed, Recipe.Steps[2].Mode) holds only that member; the rest of the struct follows its writers.

where the docs say so

  • pass TestForceStructMember in runtime
  • pass TestForceEnumMemberByName in runtime

FRC-004 verified

A forced value is coerced like any write: an enumerated tag or member takes its member name, and a name that is no member is refused with the list of members.

where the docs say so

  • pass TestForceEnumMemberByName in runtime
  • pass TestForceEnumMemberByPath in server

FRC-005 verified

The force table records the actual value the tag would hold (the driver's latest reading, the logic's latest write) and removing a force puts the tag back to it at once, not on the next write.

where the docs say so · The driver's latest reading (an input) and the logic's latest write (an output) are each asserted as the actual value, and unforce restores it at once for both.

  • pass TestUnforceRestoresActual in runtime
  • pass TestForceInputOverridesDriver in runtime
  • pass TestForceOutputReappliedAfterLogic in runtime

FRC-006 verified

A write to a forced tag through POST /api/tags is refused with 409 rather than accepted and silently overridden.

where the docs say so

FRC-008 partly verified

Set Active Step jumps a running SFC chart once: every step is deactivated and the target activated, old steps see a falling edge and the new step a rising edge, and nothing is held, so the chart evolves normally from the next scan.

where the docs say so · The N action starting and stopping is asserted; P0/P1/final-scan action edges and Step.T restarting from zero are not.

FRC-009 partly verified

Fire Transition takes one transition once whatever its condition says (sources deactivated, targets activated), is refused when a source step is not active, and addresses an unnamed transition as t<line>.

where the docs say so · Firing against a FALSE condition, the source/target swap, the refusal and t<line> addressing are asserted; "once" is not: no scan after a firing could tell a held transition from a released one (its source step is already inactive).

  • pass TestSFCFireTransition in runtime
  • pass TestSFCAPI in server

FRC-010 partly verified

An SFC command needs pou only when two running charts share the step or transition name.

where the docs say so · Only the single-chart case (resolved without pou) is asserted; no test runs two charts sharing a name to show pou is then required and resolves it.

  • pass TestSFCProgramResolution in runtime
  • pass TestSFCAPI in server

FRC-011 partly verified

Forces are not retained: a restart comes up with no forces.

where the docs say so · Asserts a forced setpoint, and a forced element of an array setpoint, is retained at its actual value, never the forced one; a restart coming up with an empty force table is not exercised.

  • pass TestRetainSavesActualNotForced in runtime
  • pass TestRetainedArraySavesActualNotForced in runtime

FRC-012 verified

The force table lives on the leader (a standby proxies the API to it), and a takeover or a leader stepping down drops it.

where the docs say so

  • pass TestTakeoverDropsForces in runtime
  • pass TestForceProxiedFromStandby in server

FRC-013 partly verified

Every force, removal, clear-all, step jump and fired transition leaves a line in the controller log with the caller's address.

where the docs say so · Asserts the force, clear-all, step-jump and fired-transition lines appear; the removal line, and the caller's address on any line, are not checked.

FRC-014 partly verified

Every force and SFC write passes the same guard as POST /api/tags: same-origin by default, the token when NAUTILUS_TOKEN is set.

where the docs say so · Cross-origin refusal is asserted on all five write endpoints; the token requirement only on POST /api/forces, set through Options.AuthToken rather than the NAUTILUS_TOKEN variable.

  • pass TestForceAuth in server

FRC-015 partly verified

GET /api/forces lists name, value, actual and sinceMs; DELETE /api/forces/{name} removes one (404 if it was not forced); POST /api/forces/clear removes all and returns the count.

where the docs say so · The force list is asserted on the POST response; a GET /api/forces body is never read, and the `actual` and `sinceMs` fields are not asserted.

FRC-016 verified

Every stream frame carries forces while at least one force is active and omits it when none is; it is never delta-gated; /api/meta advertises "forces": true.

where the docs say so

  • pass TestStreamCarriesForces in server
  • pass TestForceAPI in server

FRC-017 verified

An acceptance test can hold a tag the same way, with force: and unforce: steps.

where the docs say so

  • pass TestForceHoldsAgainstPlantAndLogic in acceptance