An Activity node ({node}/_Activity/{id}) is the record of one run: a script, an import, a sync.
Its page is ActivityViews.Overview in MeshWeaver.Graph.Views, and the code cell's output pane
is the sibling Progress area built from the same pieces.
What was wrong
A script that sent a mail and returned a dictionary rendered as:
- the title System, although a person had started it — a script run records no
ActivityLog.User; - a chip reading
ScriptExecution · Succeeded, an enum pair; started 10/03/2026 07:55 · ended 10/03/2026 07:55— an ambiguous date, no duration;- the headline
System.Collections.Generic.Dictionary2[System.String,System.Object]above✓ Done`, and the same type name again as the last log line; - nothing at all of what the run returned (recipients, sent, the link to the message);
- an accent Re-run button as the page's only call to action — on a run that had sent mail.
The type name had one cause: the kernel logged returnValue.ToString() for every result that was
not a control, and the page's headline was "the latest log line".
The page now
In the order a reader asks:
- Header — status chip in the shared vocabulary (
StatusGlyph: ✓ Done / ✗ Failed / …), what ran in words (Humanize(category)), then who · when · how long. Who falls back from the log's user to the node's creator before it says "System". The time is the viewer's zone, writtenyyyy-MM-dd HH:mm. - Origin — a link to the hub that ran it (
ActivityLog.HubPath). - Status line — only while running (the live bar) or when the run did not succeed (the loud headline). A succeeded run says so once, in the chip.
- Actions — the activity's DURABLE actions (
ActivityLog.Actions, see below), when it recorded any. - Result — the returned control when the kernel still holds it; otherwise
BuildResult(ActivityLog.ReturnValue): one row per property, names in words, a URL as a link named by its host, booleans as ✓ / ✗, empty values omitted, long opaque values cut atResultValueLimit, at mostResultRowLimitrows. A scalar renders nothing here — its log line is the output. - Log — one row per message with the time it was logged. A line that is nothing but a CLR
type name (
IsTypeNameNoise) is dropped, so runs recorded before the kernel fix read cleanly too. - Re-run / Cancel — Re-run is a plain button: re-running repeats the run's side effects.
The code cell's output pane (Progress) gets the same result rows, without the header and the
per-line time.
Durable actions — what an activity still offers after its run
A control a script returns reaches the page through the execution hub's live area dictionary, which
is empty again once that hub unloads; the JSON on ActivityLog.ReturnValue is hollow for a
container control. So a historical activity cannot reopen a returned card. An activity that must
keep offering something — Open QR card after a link publication — records an
ActivityActionReference with hub.RecordActivityAction(…) (platform contract:
Action-Link Contracts), and the page renders those from the
NODE (ActivityViews.ActionRows → BuildActions, a deferred view of its own beside the output):
- One button per action, navigating to its stored local target. Nothing about it depends on the kernel, the execution hub or the assembly generation that wrote it, so it reads the same during the run, after the hub unloaded, after a host restart and after a module refresh.
- The structural verdict decides first (
ActivityActionReference.Availability()): a reference written by a newer contract, of a kind this build does not open, or whose target is not a page on this site is shown as a disabled button with the reason — and carries no address into the page. - A reference that names a handler (
HandlerKey/HandlerVersion) is offered only while this portal's live handler chain resolves that key and version (HandlerAvailability); otherwise it reads Not available on this portal. A rule written — or a package installed — while the page is open turns it on, with no recycle. - Revoked, expired and unauthorized are decided by the page the target opens, which re-checks on every visit: the stored reference is an address, never a grant.
- The caption is the catalog's text for the stored
LabelKeyin the viewer's language, else the stored English; the row's own sentences are a module text table (ActivityActionTexts, English and German). A state word this build does not know is shown verbatim and never treated as available.
Pinned in ActivityDurableActionsTest, whose live arms render an activity on whose hub no kernel
ever ran.
The rule
A returned value is rendered from ActivityLog.ReturnValue, never from ToString(). The
kernel (KernelExecutor.OutputLine, platform) logs a return value only when it describes itself —
a scalar, a string, a record — and logs nothing for a value whose ToString() is its type name.
A script that wants its result on the page returns an object with named properties, or a control.
Every builder named above is a pure function of the ActivityLog, pinned in
ActivityProgressViewTest without a layout host.