Skip to content

Verified: Allen-Bradley Logix

Each claim the Allen-Bradley Logix page makes, with the tests that prove it in the last green CI run: 18 of 32 verified. The claims live in docs/claims/logix.yaml.

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

LGX-001 verified

`naut logix import` reads an L5X export directly, on any OS with no Rockwell software, and turns its UDTs into IEC types and its tags into a tag file.

where the docs say so

  • pass TestLogixImportProducesACheckableProject in cmd/naut

LGX-002 verified

Tag descriptions from the offline project are recovered into the imported tag file as `desc:`, which a live CIP browse cannot do.

where the docs say so

  • pass TestLogixImportRecoversDescriptions in cmd/naut
  • pass TestTagsCarryDescriptions in lang/l5x

LGX-003 verified

`naut logix import --scope '*'` imports program-scope tags along with the controller-scope ones.

where the docs say so · The CLI test runs `naut logix import --scope '*'` and finds a program-scope tag (MainProgram_Scratch) beside the controller-scope ones, and checks the default scope leaves it out.

  • pass TestTagsScopes in lang/l5x
  • pass TestLogixImportScopeStarTakesProgramTags in cmd/naut

LGX-004 verified

A Logix UDT imports as an IEC STRUCT: the hidden byte that hosts its BOOLs is dropped and the BOOLs the author wrote are declared; nested UDTs and arrays come across.

where the docs say so

  • pass TestTypesRendersUserUDTs in lang/l5x
  • pass TestLogixImportProducesACheckableProject in cmd/naut

LGX-005 verified

An L5X RLL routine renders as the same ladder model as nautilus `.ld` source: contacts, branches, in-rung blocks and coils.

where the docs say so

  • pass TestLogixGraphEmitsTheLadderModel in cmd/naut
  • pass TestLadderContactsAndCoils in lang/l5x
  • pass TestLadderNestedBranchesAndBlocks in lang/l5x

LGX-006 verified

An instruction nautilus has never seen still draws, as a box with its operands.

where the docs say so

  • pass TestLadderUnknownInstructionsDraw in lang/l5x

LGX-007 verified

Normalizing pins `ExportDate` and the other attributes that move on every export, so two exports of unchanged code compare equal.

where the docs say so

  • pass TestNormalizePinsTheVolatileAttributes in lang/l5x
  • pass TestNormalizeDropsTheCommPath in lang/l5x
  • pass TestNormalizeIgnoresAttributeWrapping in lang/l5x
  • pass TestLogixNormalizeWritesAPinnedExport in cmd/naut

LGX-008 verified

`naut logix normalize --check` compares two exports after normalizing: exports of unchanged code compare equal, and a real change still shows as drift.

where the docs say so

  • pass TestLogixNormalizeChecksDrift in cmd/naut
  • pass TestNormalizeKeepsARealChange in lang/l5x

LGX-009 verified

`naut logix serve` browses the controller over EtherNet/IP at startup and serves every user tag it can decode through the nautilus HTTP API; controller-scope tags keep their names and a program-scope tag is served as `<Program>_<Tag>`; values change when the controller's own logic changes them.

where the docs say so

LGX-010 verified

`naut logix serve` leaves module I/O tags out, and `--tags` narrows what is served with globs such as `Program:MainProgram.*`.

where the docs say so · `naut logix serve` against the in-process emulator with a module I/O tag (Local:1:I) beside user tags: the default serves every user tag and not the module tag, which the emulator does serve when a glob asks for it; `--tags` with one glob and with a comma-separated pair serves exactly the matches.

  • pass TestLogixServeLeavesModuleIOOut in cmd/naut
  • pass TestLogixServeTagsGlobNarrows in cmd/naut

LGX-011 verified

`--l5x` supplies tag descriptions to the served API, since a CIP browse cannot read documentation.

where the docs say so · Without `--l5x` /api/meta has no description; with it, the export's descriptions are served under the served names (MainProgram_StartPB).

  • pass TestLogixServeL5XSuppliesDescriptions in cmd/naut

LGX-012 verified

A write through `naut logix serve` goes to the controller and the frame shows the value the next poll read back, not the value that was sent.

where the docs say so · With one poll at startup and none after, the frame keeps the polled value after a write the controller took, so the request never reaches the frame; and a REAL written as 0.1 shows as the float32 the controller holds, not the 0.1 sent.

  • pass TestWritesReachTheController in logix/facade
  • pass TestTheFrameShowsTheReadBackNotTheRequest in logix/facade (3 of 3 passed)

LGX-013 verified

A write names one value, so a member such as `P101.Run` can be written but a whole UDT cannot; a tag the controller refuses to write returns its refusal.

where the docs say so · Member writes and the whole-UDT refusal are asserted. An out-of-range array index, which the facade passes through, is refused by the (emulated) controller and the reply carries that refusal (CIP status 0x05).

LGX-014 verified

Against a served Logix controller, *Diff with Controller* and *Download* explain that there is no nautilus source and point at `naut logix drift` and `naut logix push`.

where the docs say so

LGX-015 verified

With `NAUTILUS_TOKEN` set, `naut logix serve` requires a bearer token for writes; without it, writes are open to anything that can reach the port.

where the docs say so · `naut logix serve` run with NAUTILUS_TOKEN answers a write with no token or a wrong one with 401 and the controller keeps its value, and takes a write with the bearer token; without NAUTILUS_TOKEN a write from a non-browser client lands.

  • pass TestLogixServeNautilusTokenGuardsWrites in cmd/naut (3 of 3 passed)

LGX-016 partly verified

`naut logix probe` reports each SDK prerequisite (FactoryTalk token, FlexNet feature, CodeMeter entitlement) as its own gate, so one failure does not mask the rest.

where the docs say so · CI shows the CLI printing a passing and a failing gate on separate lines against a fake agent; the real gates are verified on hardware only, and that one failing gate does not mask another is not asserted.

  • pass TestLogixProbePrintsTheRemedyForAFailingGate in cmd/naut
  • skip TestAgentProbeReportsGates in logix/logixd

LGX-017 partly verified

A probe gate that fails prints what to do about it, underneath the failure.

where the docs say so · The CLI half: against a fake agent that attaches a remedy to the failing gate, the remedy is the indented line directly under that gate, before the next gate, and a passing gate carries none. The remedies themselves come from the C# agent (its Remedies table in tools/logixd), and that the real agent attaches one to every failing gate is not asserted by any test, in CI or on hardware.

  • pass TestLogixProbePrintsTheRemedyForAFailingGate in cmd/naut

LGX-018 verified

An agent that is not running is reported as `logixd: unreachable ... connection refused`; a wrong bearer token (HTTP 401) as `logixd: unauthorized: <agent URL> refused the token; check --token or NAUTILUS_LOGIXD_TOKEN against %ProgramData%\logixd\logixd.token on the agent's machine`, and no token at all as `... wants a token and none was sent`.

where the docs say so · Asserted against a fake agent that answers as logixd does (HTTP 401, {"error":"unauthorized"}); that the C# agent sends that 401 is LGX-031, verified on hardware only.

  • pass TestClientUnreachableIsFatalAndNamesTheURL in logix/logixd
  • pass TestLogixAgentReportsAnUnreachableAgentHelpfully in cmd/naut
  • pass TestLogixAgentReportsAWrongToken in cmd/naut
  • pass TestUnauthorizedNamesTheAgentAndTheToken in logix/logixd

LGX-019 partly verified

`naut logix convert` converts ACD to L5X and L5X to ACD.

where the docs say so · CI covers staging and fetch against a fake agent; the actual ACD/L5X conversion is verified on hardware only.

LGX-020 not run in CI

`naut logix build` compiles a project through the SDK, with no controller.

where the docs say so · Verified on hardware only (needs NAUTILUS_LOGIXD_URL); skipped in CI.

LGX-021 verified

`naut logix drift` compares the controller with the repo file and exits 1 on a mismatch, so it works as a CI gate; it requests the same export kind (detailed or basic) as the repo file.

where the docs say so · Against a fake agent standing in for the controller's upload: drift uploads from the given comm path, exits 0 with "no drift" when the controller's export matches the repo file and 1 with "DRIFT" when one setpoint differs, and asks for the repo file's own export kind.

  • pass TestLogixDriftAsksForTheRepoFilesExportKind in cmd/naut (3 of 3 passed)
  • pass TestLogixDriftExitsOneOnAMismatch in cmd/naut (3 of 3 passed)

LGX-022 partly verified

`naut logix browse` lists the controllers FactoryTalk Linx has already discovered, as comm paths with the controller name and catalog number, without scanning the network.

where the docs say so · With a fake agent returning the committed FT Linx configuration, `naut logix browse` prints the comm path, the controller name and its catalog number on one line and asks the agent for nothing but that configuration. That the real agent hands back the FT Linx files it finds is the C# agent's, verified on hardware only.

LGX-023 verified

`naut logix push --accept` or `--finalize` without `--comm-path` is refused rather than landing as unaccepted pending edits.

where the docs say so

  • pass TestLogixPushRefusesOnlineOptionsWithoutACommPath in cmd/naut

LGX-024 partly verified

`--accept` sends the change to the controller; `--finalize` also assembles it if the controller is in Run.

where the docs say so · Option plumbing is CI-tested against a fake agent; the controller behaviour is verified on hardware only.

  • pass TestLogixPushSendsTheChosenOnlineOption in cmd/naut
  • pass TestImportRungsSendsTheOnlineOptionVerbatim in logix/logixd
  • skip TestSDKOnlineRungImport in logix/logixd

LGX-025 partly verified

An online edit takes no project file: it uploads the program the controller is running, imports the rungs into that, and sends it back.

where the docs say so · CI asserts, against a fake agent, that an online push takes one file and uploads from the given comm path; the upload on a real controller is hardware only, and sending the result back is not asserted.

  • pass TestLogixPushSendsTheChosenOnlineOption in cmd/naut
  • skip TestSDKUploadFromController in logix/logixd

LGX-027 partly verified

`download` never changes the controller mode unless explicitly asked.

where the docs say so · Only the Go client is tested: it forwards the caller's ensureProgramMode unchanged. That the agent leaves the mode alone when not asked is in the C# agent, which has no automated tests.

  • pass TestDownloadSendsEnsureProgramModeExplicitly in logix/logixd

LGX-028 not run in CI

`logixd` listening on a routable address requires a token and refuses to start without one.

where the docs say so · Verified on hardware only: the test starts the built agent (LOGIXD_BIN, which builds only beside the Logix Designer SDK) on 0.0.0.0 with no token and expects exit status 2 and the refusal, then with a token expects it to start. Skipped in CI; not yet run (the SDK machine is unavailable).

  • skip TestAgentRefusesARoutableBindWithoutAToken in logix/logixd

LGX-029 not run in CI

`LOGIXD_COMM_ALLOW` is agent-side configuration only, so a request cannot name a controller the operator has not allowed.

where the docs say so · Verified on hardware only: the test starts the built agent with LOGIXD_COMM_ALLOW set and expects an upload from a comm path outside it to be refused 403 forbidden, naming the allowlist. Only the upload endpoint is exercised (the session comm-path endpoint applies the same check). Skipped in CI; not yet run (the SDK machine is unavailable).

  • skip TestAgentRefusesACommPathOutsideItsAllowlist in logix/logixd

LGX-030 not run in CI

Every path the agent touches is confined to `LOGIXD_WORKDIR`, compared after full resolution so traversal is rejected.

where the docs say so · Verified on hardware only (needs NAUTILUS_LOGIXD_URL); skipped in CI.

  • skip TestAgentRefusesToEscapeItsWorkDirectory in logix/logixd

LGX-031 not run in CI

An agent that has a token answers an unauthenticated or wrongly authenticated caller with 401.

where the docs say so · Verified on hardware only (needs a running agent with a token, or the built agent); skipped in CI. TestAgentAnswersAMissingOrWrongTokenWith401 sends both no token and a wrong one, and is not yet run (the SDK machine is unavailable).

LGX-032 not run in CI

The installer refuses to run while plain `DOTNET_ROOT` is set and prints the commands that fix it.

where the docs say so · Verified on hardware only (an elevated Windows session): the test sets DOTNET_ROOT at User scope, runs install.ps1 elevated and expects the refusal, both fix commands and nothing installed. Opt-in (NAUTILUS_LOGIXD_INSTALLER_TEST=1), skipped in CI and not yet run (the Windows SDK machine is unavailable).

LGX-033 partly verified

The mnemonics nautilus writes into neutral text are the short spellings the Logix importer accepts (`GE` `GT` `LE` `LT` `EQ` `NE` `MOVE` `LIMIT`), never the editor captions (`GEQ`, `GRT`, `MOV`, `LIM`).

where the docs say so · Checked against a vocabulary of surveyed exports, not against the SDK importer (SDK acceptance is verified on hardware only).