# Logic

> The Logic page, its Address space column, the folders, the command bar, the sweep and the write funnel behind every panel, and the three permissions that decide what the page draws.

Logic is the third entry of the navigation rail. It opens for any role holding **View logic**, and its header reads "Define variables (derived or writable values) and actions (scripts that write them), composed over the address space." It is a master-detail page ([how the pages work](app-conventions)): a column headed **Address space** on the left, a command bar and a detail panel on the right. Everything you edit here autosaves as you type; there is no Save button anywhere on the page.

## In this area {#in-this-area}

| Page | What it covers |
| --- | --- |
| [The address space](logic-address-space) | The seven reserved roots, how an address is spelled and sanitized, the filter box, and the three ways to enter an address. |
| [Variables](logic-variables) | The variable editor: identity and address, the Expression and Memory kinds, the Value card, Set value. |
| [Expressions](logic-expressions) | The expression language, the read surface of a point, the rules the evaluator enforces, the script editor. |
| [Actions](logic-actions) | The action editor, what a script may write, every validation message, Run and Enable/Disable. |
| [Triggers](logic-triggers) | The trigger editor and the interval scheduler. |
| [Alarms](logic-alarms) | The alarm editor, the state machine, annunciation, Acknowledge and Ack all. |
| [From other pages](logic-from-other-pages) | The System, Server, Connector and Process roots, the point panel, and the notice naming the page that edits them. |

The **Assets** root of the same column is a group of its own: [Assets](logic-assets) covers Images, Icons, Colors, Symbols and Connection types.

## The Address space column {#the-address-space-column}

The column lists the roots of the address space under two captions. **Defined here** holds what this page creates and edits: **Variables**, **Alarms**, **Actions**, **Triggers** and **Assets**. **From other pages** holds what it only shows: **System**, **Server**, **Connector** and **Process**. Every root under the first caption carries a count (Variables and Alarms count their definitions, Actions and Triggers theirs, Assets the sum of its five categories), and the Alarms root, every alarm folder and every alarm row carry a colored dot with the worst priority they hold that is active or awaiting acknowledge; the dot clears the moment the alarm is answered.

The tree is lazy: a branch loads when you expand it. Live values are never drawn in the tree; the detail panel of the selected node shows them, refreshed twice a second.

| Control | What it does |
| --- | --- |
| Filter… | Narrows the tree to rows whose name contains the text, case-insensitively. A folder survives when any descendant matches and opens to its matches; the Assets root narrows to the categories whose name matches, or comes whole when only its own name matches; an address-space root whose own name matches stays listed and loads its branch when expanded, while the Actions and Triggers sections list only the rows that match. |
| New… (column footer) | Opens the create menu: **New variable**, **New action**, **New trigger**, **New alarm**, then **New folder** with one destination per section (Variables, Alarms, Actions, Triggers). Everything made here lands at the root of its section under the first free name of the `Variable1`, `Action1`, `Trigger1`, `Alarm1` or `Folder1` series and opens for editing. Drawn only for a role with **Configure logic**; greyed with the reason while the station is locked. |
| Expand all / Collapse all | Open every branch (loading each level as it opens) or close everything back to the roots. |
| Right-click | On a section root, one of your folders or a definition row: selects the row and opens its menu (below). Nothing opens on a node from another page. |

The right-click menu carries, depending on the row and the role: **New variable / New action / New trigger / New alarm** (into the folder or root you clicked), **New folder** (not offered on a folder already three levels deep), **Acknowledge** (alarm rows, Operate logic), **Move to** (a submenu with the section root and every folder the row may be filed into), **Copy**, **Delete**, and on a folder **Rename folder** and **Remove folder**. A role without Configure logic sees no menu at all, except the Acknowledge entry of an alarm row when it holds Operate logic.

The detail area is empty until you select something: "Select a node to inspect it: variables, actions, triggers and alarms open their editor. Create one with New."

## The command bar {#the-command-bar}

The bar draws the verbs of the selected node. What the role never permits is not drawn; what the situation refuses right now stays drawn, greyed, with the reason in its tooltip: "Configuration is locked while a Unit is running." during an engineering operation, "Runtime stopped" while the station runs read-only.

| Selection | Leading cluster | Trailing (danger) cluster |
| --- | --- | --- |
| One of your folders | New variable / action / trigger / alarm (the kind its section holds), New folder (greyed "This folder is already as deep as folders nest." at the depth cap), Rename folder | Remove folder |
| A variable | Copy | Delete variable |
| An action | Run, Enable or Disable, Copy | Delete action |
| A trigger | Enable or Disable, Copy | Delete trigger |
| An alarm | Acknowledge, Enable or Disable, Copy | Delete alarm |
| The Alarms root | Ack all | |
| Assets, Images | Import image… | |
| Assets, Icons | New user icon | |
| Assets, Colors | New color | |
| Assets, Symbols | New user symbol, Import symbol…, Copy chat instruction | |
| A System, Server, Connector or Process node | The [edited-elsewhere notice](logic-from-other-pages#the-edited-elsewhere-notice) and its Open button | |

**Copy** duplicates the selected definition to the root of its section, under the source's own name when that is free and otherwise `Name (2)`, `Name (3)` and so on, and opens the copy for editing; a copied alarm starts at Normal, a copied trigger starts unscheduled, a copied action has no run recorded. **Enable** and **Disable** flip the definition's Enabled flag through the same autosave as any field. Every **Delete** asks first ("Delete 'X'? … This cannot be undone.") and reports "Deleted." in the action feed; deleting a variable or an alarm leaves every expression, script, condition and dashboard binding that named its address unresolved, which [Validation](validation) lists.

## Folders {#folders}

Each of the four sections can be organized into folders. A folder belongs to one section and holds only that section's items; it nests three levels deep at most. A folder is organization only: it has no permission, no evaluation and no state.

For **Variables** and **Alarms** the folder chain composes the address: a variable in `Forno` reads `Variables.Forno.Setpoint`, one in its `Zona1` subfolder `Variables.Forno.Zona1.Setpoint`. One level of one section is a single segment namespace shared by its folders and its definitions: two folders may each hold a `Setpoint`, but nothing filed at the same level may sanitize to the same segment, and the editor refuses such a name as you type, naming the address already taken. **Actions** and **Triggers** are referenced by identity, so their folders organize the tree only and their panels show a location line instead of an address.

| Command | What happens |
| --- | --- |
| New folder | Creates an empty folder named `FolderN` and opens its name field on the tree row; leaving the field empty or unchanged keeps that name. |
| Rename folder | Opens the name field on the row. Every address below the folder moves with it, every reference is rewritten, and the feed says how many ("Folder renamed; 3 references updated."). |
| Move to | Files a folder or a definition under another folder of the same section, or back at the section root; addresses and references follow. The list offers only the legal destinations: never the folder itself, one of its own subfolders, another section, or a level where its subfolders would pass the depth cap. |
| Remove folder | Asks first, stating what moves: "Its 3 items move to Variables; nothing is deleted. References to the addresses that move are updated." The items and subfolders are re-filed one level up; the removal is refused when two of them would collide at the destination. |

## The sweep and the queue {#the-sweep-and-the-queue}

A runtime sweep runs every 100 ms on one sequential logic queue: it evaluates every expression variable, then every enabled alarm condition, in that order, so a condition reads this sweep's variable values. Action runs, memory writes, tag writes and acknowledgements ride the same queue, so a script never interleaves a sweep or another script. A separate scan, also every 100 ms, fires due [triggers](logic-triggers) onto the queue. Consumers (dashboards, channels, this page) read the published state; nothing on this page triggers an evaluation by hand.

## Writing values {#writing-values}

Every write goes through one funnel, whatever started it: a script's assignment or `Write(...)`, the **Set value** field of a memory variable, a dashboard control, a Process recipe, the agent, an external OPC UA client writing a public node. The funnel refuses a value that is not finite or cannot convert to the target's type, refuses a source that a running recipe or an interlock holds (naming the holder), journals the write as old value to new value under its source (Operator, MCP, the run), and applies it on the logic queue. A write whose source is an action is the exception: it goes to the [detailed capture](events-console#detailed-capture) only, never to the Events console, because a script that writes on every sweep produces values by the thousand and would bury the station's news under them. What the console carries of an action is its failures. A tag write takes the engineering value and reverses the tag's [conversion pipeline](connector-value-pipeline) to the raw value the device takes. The details are on [Variables](logic-variables#set-value) and [Actions](logic-actions#what-an-action-may-write).

## Permissions and locks {#permissions-and-locks}

| Permission | What it allows here |
| --- | --- |
| View logic | Opening the page and reading everything on it, the live values included. |
| Configure logic | Creating, editing, renaming, moving, copying, enabling, disabling and deleting variables, actions, triggers, alarms and folders, and curating the asset library. |
| Operate logic | Writing a memory value, running an action, acknowledging alarms, here, on dashboards and on the Events page. |

A role with View logic only reads the whole page: the editors are inert under a note ("Your role can view Logic but cannot configure it (variables, actions, triggers, alarms and assets).") and no configure or operate verb is drawn. A role with Operate but not Configure keeps Run, Acknowledge, Ack all and Set value live. While a Process unit holds the station, the page shows the engineering-lock notice and every configure verb and editor field is greyed; Run, Acknowledge and Set value stay available. While the runtime is stopped, both configure and operate refuse with "Runtime stopped"; the tree and the panels stay readable but carry no live data. The catalog of bits is on [Permissions](users-permissions).

## What the page does not do {#what-the-page-does-not-do}

There is no Save and no Undo: a keystroke is a persisted change (the feed says "Saved."), and a refused save reloads the field to what the station holds. Definitions the agent creates or deletes through its own tools do not refresh an open column by themselves; the branch is re-read when this page next creates, copies or deletes in that section. Alarm history, the Events console and dashboards live on their own pages.
