{#- The node's own facts — time, what the run read, what it found, what it ran with — as the **one** block both pages render (ADR-0044 decision 8, questions §4.8 answered: the container gets the detail page it never had, built by reuse rather than as a second surface). The leaf detail page owned all of this and the container owned none of it: `/status/` is a dashboard *of the children*, so a container's `config` was stored by two checks in the tree and rendered by nothing, and its run facts had nowhere to land. Same partial on both pages, so the two can no longer drift. Five cards, in the order a reader wants them: **when** it ran, **what it read** (`record` — the reading, where the run kept one, ADR-0085), **how it has read over time** (the curves that stand on this node, where any do, ADR-0097), **what it found** (`report` — the run's outputs), **what it ran with** (`config` — its inputs). Report before config on purpose: the outputs are why you opened the page, the inputs are the reference beside them. Those two are Markdown through the hardened renderer (ADR-0018) — checks author them with `config_markdown()`, and rendering that bullet list as literal text was a leftover from before the renderer landed. The record is data, not Markdown, and is shown in the one list a line's record is shown in (`_record_list.html`). Context: ``node`` (a StatusSnapshot), ``branch`` (its path), ``since`` (the start of the current own-status period, or None) and ``node_curves`` (the curves that stand on the node, or None — and allowed to be absent, for a caller that has no engine to ask). Never included by the kiosk, which keeps none of this. -#} {%- from '_record_list.html' import record_list %} {%- from '_series.html' import curve %}

Time

{#- Observation time (ADR-0027). No timestamp means no check has ever written this node — say so, rather than inventing an instant. With a timestamp but no recorded transition of its own (``since`` is None) there is no period to state either, so report the single observation. A status that still holds is stated by when it began and when it was last observed, on two lines, also where the two are one instant (ADR-0099 decision 1). Where the tree did not see the period begin — a first reading, or a beginning lost before the tree kept it — it began *before* a bound, the furthest back the tree can vouch that nothing changed, which History's row for the period states too (ADR-0102 decision 3). A period that a pin's end began says so — *since …, when its maintenance ended* — because the node began to show its status then, which is not when its check began to read it; an edit of a pin begins no period, so a pinned node holds *since* its pin was set (decisions 6 and 8). So does one that a line's pin began: *when a line was silenced*, *when a line's maintenance ended* (ADR-0107 decision 3). The words are `_began`'s, in `app.py`, and the Copy document writes the same. It read *from … until …*, and the second instant was the latest reading, never an end: an active failure read as one that had stopped, and a node read once in its period as *from 19:32:39 until 19:32:39*. *Until* belongs to a period that has ended, which the History tab lists. The period is bounded by the **own**-status event log, so it names the own status: on a container the rolled-up code is a statement about the children, and the children are on the same page saying it themselves. A container that declares nothing has no own status for a period to name — its `UNDEFINED` is the roll-up's to skip, and its page heads with what it rolls up to — so it states the observation, as a node with no transition of its own does: the route hands it no ``since``. That is decided once, in `_since_of`, from the node before a filter takes its children away, and the Copy document takes its period from the same place, so the two cannot differ. A leaf's `UNDEFINED` is its own, and keeps its period. **A period is stated wherever there is one** (ADR-0115 decision 6): a pinned node that no check has written has shown *maintenance* since its pin, and *Not yet observed* alone would say nothing of that. The sentence is for a node with neither an observation nor a period. -#} {% if since %}

Status {{ node.own_code.name.lower() }} since {% if since.before %}before {% endif %}{{ since.at | localtime }} {%- if since.began %}, {{ since.began }}{% endif %}

{% if node.timestamp is not none %}

Last observed {{ node.timestamp | localtime }}

{% endif %} {% elif node.timestamp is none %}

Not yet observed.

{% else %}

Observed {{ node.timestamp | localtime }}.

{% endif %} {#- The run facts (ADR-0044 decisions 2 and 4), present exactly where this node carries them — the sole owning check's mount and the unwritten ancestors above it. This is where **wall time** surfaces: stored since the run-object slice, rendered nowhere until this header. The next update stays **absolute** here, as on the grid. §10.5 of the working note reserved the relative "in 4m" for this header, on the grounds that the reader is looking deliberately and the stale banner is directly above — but that argument needs a *live* page, and this partial is on one page that polls and one that does not. A relative form on the leaf page would go on claiming "in 4m" for as long as the tab is open, which is the same freeze the absolute form was chosen to survive. One partial, one form, and the safe one wins. -#} {% if node.run and node.run.next_run_at %}

Next update {{ node.run.next_run_at | localtime }}

{% endif %} {% if node.run and node.run.wall_seconds is not none %}

Last run took {{ node.run.wall_seconds | elapsed }}

{% endif %} {#- The period where there is one, and the **tolerance** where there is not (ADR-0081). "Checked every" is a claim that a subject was read on that interval, and it is only true of a check: the instance's own nodes are recorded state re-asserted on the scheduler tick and readiness measured its trust store once, at startup, so the line used to say "Checked every 1s" about something nothing checks. Such a node carries no period at all now — nor does a paced unit, which has none to carry — and what both do carry is the freshness they promise, which is the fact a reader of either wants and the one the server actually applied. One rule, both kinds, no discriminator: a node with a period shows it, a node without shows what it promises instead. -#} {% if node.frequency_seconds %}

Checked every {{ node.frequency_seconds | duration }}

{% elif node.stale_after_seconds %}

Goes stale after {{ node.stale_after_seconds | tolerance }}

{% endif %} {#- How often this node changed its mind lately. It sits next to the History button because it is the same question asked in one number, and it is **not** on a card: a card says what a node is now, and churn is history. A subject that flaps is the case the escalation counter deliberately does not catch — every recovery clears that counter — so without this there is no number anywhere that says *this thing is flapping*, only a list of events to count by eye. Suppressed transitions are in it: a check flapping underneath a pin is exactly what is worth seeing, which is the opposite of what the History list wants. -#} {% if node.changes %}

{{ node.changes }} status {{ "change" if node.changes == 1 else "changes" }} in the last hour

{% endif %} {#- The dependency graph, from whichever end this node stands at. Both sentences are about **reachability**, which is why they sit here with the freshness facts rather than on a status card: neither is a claim about how the subject is doing. Being shielded is the more urgent of the two — the node is not reaching the level above, and an operator who does not know that will read a quiet parent as good news — so it is said in the node's own words and links to the thing to go and look at. The other direction is the risk the feature carries: one dependency can quiet dozens, and a number that says how many is the only thing standing between that and a silence nobody can account for. -#} {%- if node.shielded_by %}

Reached through {{ node.shielded_by }}, which is failing — nothing from here reaches the level above until it answers.

{%- endif %} {%- if dependents %} {%- set reached = dependents | length %}

{{ reached }} {{ "check is" if reached == 1 else "checks are" }} reached through this{% if node.code.name == 'ERROR' %}, and not reaching the level above while it is failing{% endif %}.

{%- endif %} {#- The History page is a tab of its own now (ADR-0097 decision 3), beside Status and Series under the node's title; this card keeps the numbers that ask the same question, and no second way there. -#}
{% if node.record %} {#- **What this run measured** (ADR-0085): the reading the node's code, lines and children are derived from, and the object it was taken on. The same list the entry records are shown in, so one place decides what a field is and one says how it reads: its times in the configured timezone, everything else as stored. A card above says what the node *is now*; this says what was *read*. It is data and never a claim: anything that should alarm is a reason. -#}

Measured

{%- if node.subject %}

On {{ node.subject }}

{%- endif %} {{ record_list(node.record, "mb-0") }}
{% endif %} {%- set here = node_curves if node_curves is defined else none %} {%- if here %} {#- **How it has read over time** (ADR-0097 decision 2): the curves that stand on this node — an aspect's own, or a check's own node's for a measure that names no other — beside its status, its reasons and its configuration. The rest, and the readings they were drawn from, are on the Series view; every reading is on the History page. A polled branch page renders it again, curves and nothing more. -#}

Series

{%- for c in here.curves %} {{ curve(c) }} {%- endfor %}

{%- if here.source == branch -%} Beside every curve beneath this node on its Series view; every reading is on its History page. {%- else -%} Drawn from the readings of {{ here.source }} — beside the rest on its Series view, every reading on its History page. {%- endif -%}

{%- endif %} {% if node.report %} {#- What the run **found** (ADR-0044 decision 6) — the roster, the scope, the enumeration — and never a status claim: anything that should alarm is a reason, and this field must not become a second, quieter reason channel. Never on a card either: volume is exactly what `reason_cap` exists to keep off the grid. -#}

Report

{{ node.report | markdown }}
{% endif %} {% if node.config %}

Configuration

{{ node.config | markdown }}
{% endif %}