Skip to content

A hold nothing can recompute still renders as the live reason — a frozen heldReason beside a fresh lastCheckedAt #3812

Closed

Description

@rbuergi

A hold nothing can recompute still renders as the live reason

UpdatePolicyContent.IsHeld(tag) answers "is there a hold record for this tag". Both production
readers use it to answer a different question — "is this why the install is not moving right
now"
— and those stopped being the same question the moment a check could decline to evaluate.

Measured on memex, get @Admin/UpdatePolicy, 2026-09-09 10:42Z:

heldAt          : 2026-09-07T22:27:17Z
heldTag         : 3.0.0-ci.8057
lastCheckedAt   : 2026-09-09T10:41:24Z          <- 36 h later
lastCheckVerdict: "updates are disabled on this install (Admin/UpdatePolicy = None);
                   the registry was not listed."

HeldAt/HeldReason are written only by RecordHold, which runs only when a candidate is
actually evaluated. LastCheckedAt is written by RecordCheck on every check. Under
UpdatePolicyKind.None the check records "updates are disabled" and never evaluates — so the hold
is never revisited, never cleared, and the fresh LastCheckedAt beside it makes a two-day-old
record read as a current verdict.

#3795 (merged today) sharpens this: under policy None the BuildCompletion /
ModuleSetProposed triggers are now filtered out before they check, so the hold is frozen harder
than it was.

It has already caused one misdiagnosis

#3706 was filed on this exact frozen record. Its headline — "their retired floors hold every
self-update on memex forever"
— read three floor lines as a live verdict. They were computed at
2026-09-07 22:27Z; #3648 (floors become advisory) merged 00:22Z and #3651 (only measured
unloadability holds) merged 01:10Z the next morning. The quoted evidence predates its own fix by
two hours, and nothing in the record says so. See
#3706 (comment).

Where it surfaces

reader line what it says
UpdatePolicySettingsTab.cs:211 if (content.IsHeld(tag)) renders ui.updateHeld — "this install is not moving because…" — with the stale reason quoted underneath
PlatformUpdateStatus.cs:99 policy.IsHeld(latest) || blocked returns UpdateHeld on the About surface

The tab does print ui.updateHeldAt, so the date is on screen — but it reads as when the hold
started
, not as the last moment anything checked. A reader has no way to tell a live hold from a
frozen one.

The actual reason this install is not moving is already recorded, one field away:
updates are disabled on this install (Admin/UpdatePolicy = None).

What correct looks like

The record is fine — a durable note of the last evaluation is worth keeping. The presentation is
what conflates a record with a verdict.

  1. A predicate that distinguishes them, on the content itself (it already carries Policy): a hold
    is operative only while the checker that wrote it would still clear it.
  2. The tab renders a non-operative hold as history — "when last checked on «date», «tag» was
    held because …"
    — and states the current reason (updates are disabled) as the current reason.
    New keys go in both strings.en.json and strings.de.json.
  3. PlatformUpdateStatus.Derive stops returning UpdateHeld off a non-operative note. A Red combo
    verification
    is a recorded fact and keeps holding — the existing comment already draws exactly
    that line ("the recorded verdict is the fact; IsHeld is the poller's note about it"); this
    extends it to the case where the note can no longer be refreshed.

🚨 Not "clear the hold when updates are disabled" — that destroys the last real evaluation, which is
the only diagnostic an operator has when they turn updates back on.

Found while correcting #3706.

Activity

  1. rbuergi commented on Sep 9, 2026

    @rbuergi
    ContributorAuthor

    Fixed by #3815, merged. Closing by hand — the merge queue does not fire Closes links, which is how SocialMedia#155 and #3488 both sat open on landed fixes today.

    Verified on origin/main, not on the PR:

    UpdatePolicyNodeType.cs   IsHoldOperative        present
    strings.{en,de}.json      updateHoldHistorical   present in BOTH catalogues
    

    A frozen hold now renders as history — "This is a record, not a current verdict… nothing has re-checked {tag} since «date»" — and PlatformUpdateStatus.Derive no longer answers UpdateHeld off a note nothing can refresh. A Red combo verification still holds: that is a recorded fact about the build, not a note about the poller.

    🚨 The record itself is deliberately not cleared when updates are switched off — it is the only diagnostic an operator has before switching them back on. Only the framing changed.

    Follow-up owed in the other repository, declared on the PR: npm run sync:i18n -- --ref <the merge sha> in MeshWeaver.Plugins, to carry the two keys into the React mirror. The mirror compares against a pinned core commit, so nothing reds until someone runs it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions