# The unit address space

> Every point a unit publishes under Process.Model.Unit, its type and meaning, which points are writable commands, and what a Logic script may read from it.

Every unit publishes its run data as ordinary [Logic](logic) addresses under
`Process.<Model>.<Unit>`, so dashboards, Logic expressions, the embedded OPC UA server and
the agent reach it with no extra plumbing. The branch is browsed on the Logic page under
"From other pages" ([From other pages](logic-from-other-pages)) and in every address
picker. Renaming a model, unit, channel or metadata field replaces the corresponding
addresses and rewrites live textual references; recorded files keep the names frozen when
they were written. The segments are the sanitized names: a unit called "Unit 1" of the
model "Climatic chamber" is addressed as `Process.Climatic_chamber.Unit_1`.

| Branch | What it exposes | Writable |
| --- | --- | --- |
| `Channels.<Channel>` | The live bound value of each channel, typed as the channel declares. | A writable channel (Write only or Read and write role) is a writable point through the write funnel; a source a run holds refuses every other writer. |
| `Procedure.<point>` | The run state, one scalar per point (table below). | No. |
| `Commands.<command>` | `Start`, `Hold`, `Resume`, `Stop`, `Abort` and `Comment`. | Yes: writing dispatches (table below). |
| `Next.<point>` | The staging area the next Start consumes. | Manual metadata fields only. |
| `Productivity.Today.<branch>` and `Productivity.Rolling.<branch>` | The unit's productivity projection for each period. | No. |

## Channels {#channels}

A channel point reads the value behind the unit's binding, projected to the channel's data
type, and reads as a gap when the channel is unbound or its source is unavailable. In a
Logic script the point is a read-only typed projection of the bound tag or variable, never
the tag itself: `Value`, `ValueObject`, `ValueRaw`, `ValueScaled`, `ValueCalibrated`,
`ValueLimited`, `ValueRounded`, the conversions `ValueToBool()`, `ValueToInteger()`,
`ValueToReal()`, `ValueToString()` and `ValueToDateTime()`, the quality `State()`, the
stamps `SourceTimeStamp()` and `ApplicationTimeStamp()`, `Refresh()`, `Name` and
`EngineeringUnit`. The pipeline members answer for a tag binding; a variable binding
answers the value and the application stamp.

## Procedure {#procedure}

Every point is computed from the live run and reads with good quality; a point that has
nothing to say reads a gap.

| Point | Type | Meaning |
| --- | --- | --- |
| `Status` | Text | `Preparing` while the unit is reserved and no run exists yet, `Idle` while nothing owns it, otherwise the run state: `Running`, `Held`, `Saving`, `Completed`, `Aborted`, `Failed`. |
| `Running` | Boolean | Strictly the Running state; never true for preparation, Held, Saving or finalization. |
| `Busy` | Boolean | The whole occupied span: reservation, Running, Held, Saving and the final close of the run file. |
| `Verdict` | Text | `OK`, `NOK`, `Indeterminate` or `None`. The judged evidence stays readable after the run ends until the next run starts. |
| `Mode` | Text | The active run's mode, `Instant`, `Temporal` or `Controlled`; a single command (snapshot, evaluate now) reports too. Gap when idle. |
| `ActiveProcedure` | Text | The active run's name ("Procedure · Unit"). Gap when idle. |
| `SegmentIndex` | Integer | The temporal profile's current segment, 0-based. Gap without a profile. |
| `CycleIndex` | Integer | The current cycle, 0-based. Gap when idle. |
| `CycleCount` | Integer | The total cycles of the run (1 for a single pass). Gap when idle. |
| `Cycle` | Text | "2 / 10" for a cyclic run; a gap when the run is not cyclic, so a bound readout shows the gap mark instead of a misleading single pass. |
| `FailedCycles` | Integer | Cycles judged NOK so far. Gap when the run is not cyclic. |
| `SamplesEvaluated`, `SamplesOut`, `SamplesUnavailable`, `SamplesInvalid` | Integer | The evaluation's evidence counters, updated atomically by the evaluation engine. Gap without judged evidence. |
| `Elapsed` | Decimal | Seconds since the run started. Gap when idle. |
| `StartedAt` | Date and time | When the active run started. Gap when idle. |

## Commands {#commands}

Reading a command point answers "can this execute now", so a bound Button disables itself;
writing it dispatches the command through the run console, journaled with the writing
surface's source and recorded with the identity of whoever pressed. A command is a service
call, never a queued point write.

| Point | Reads true when | Writing |
| --- | --- | --- |
| `Start` | The unit is not busy, the runtime accepts operations, the interlock is Normal and a procedure is staged. | Starts the staged procedure with the staged metadata. |
| `Hold` | A run is Running and its procedure is Temporal. | Freezes the window. |
| `Resume` | A run is Held and the interlock is Normal. | Releases the hold. |
| `Stop` | A run is Running. | Ends the run as Completed. |
| `Abort` | A run is Running or Held. | Ends the run as Aborted. |
| `Comment` | Never: the point has no reading. | Appends the written text as a comment to the active run, or as a post-run note on the unit's latest finished run when it is idle. A unit with no run at all refuses ("The unit has no run to comment on."), and so does empty text. |

Every command reads false while the station is refusing writes (the runtime stopped).

## Next {#next}

| Point | Type | Meaning |
| --- | --- | --- |
| `Next.Procedure` | Text | The staged procedure's name. Read-only here: staging is done on the Run card or with the Procedure picker component. |
| `Next.<Field>` | Text | One point per metadata field the staged procedure prompts; the branch reshapes when the unit is re-staged, and a field of another procedure reads a gap. A manual (text or numeric) field is a writable staging point, which is what an Input component bound to it writes. A sequential field is a read-only prediction of the identifier the counter would compose now; reading never reserves it. |

Staging is station-wide, in-memory and transient: it resets when the application starts
and is consumed, not cleared, by Start.

## Productivity {#productivity}

Two periods, `Today` (since local midnight) and `Rolling` (the window declared on the model
or the unit), each with three branches ([Productivity](process-productivity)):

| Branch | Points | Type |
| --- | --- | --- |
| `Summary` | `ProductivityPercent`, `YieldPercent`, `TypicalElapsedSeconds` | Decimal; a gap until the denominator exists. |
| `Summary` | `Finalized`, `OK`, `NOK`, `Indeterminate`, `Unclassified`, `Aborted`, `Failed` | Integer counts. |
| `Outputs.<key>` | `Quantity`, `RatePerHour` | Decimal; one key per named quantity, or per productive procedure when the model declares no quantity. |
| `Procedures.<key>` | `Quantity`, `RatePerHour` and the summary points above | As above, per productive procedure. |

Keys derive from the stable id and the frozen output unit, not from the display name, so a
rename never moves an expression. Every point is read-only, and the projection is read
from the history index, never from run files.

## What a script may do {#what-a-script-may-do}

Logic variable, alarm and action scripts may **read** everything here: channel values, run
state, command readiness, staged values and productivity points. They cannot dispatch a
command, write a staging field or append a comment; those writes belong to the explicit
command consumers: the operating panels, dashboard Buttons, Inputs and the Procedure
picker, the unit automation and the agent tools.
