The app-tile stamp, and the record that may not exist

A point read or write of a mesh node that does not exist yet is a framework defect, not a slow no-op. This page is the worked example: what the Edu course rail does with the learner's home tile, why the obvious shape was wrong, and the shape every other reader of an optional node should copy.

What the stamp is

When a learner installs a course, the Store mints an Apps-band record at {viewer}/_App/{packageId} — the tile on their home. CourseAppTile keeps that tile telling the truth: every page open re-stamps the name with · opened/total and moves content.openPath to the page they are on, so the tile both SAYS where they are and RESUMES there. EduCourseNavigationProvider prepares that write on the render turn and runs it after the visit-dwell, behind the visit and solved markers it counts.

The defect (#1595)

The record exists only once the course is installed, and a course page is routinely opened by someone who never installed it: the published original, a preview, a shared link, and every run of the Education e2e suite. The old shape called the write unconditionally and leaned on the transform declining:

// ❌ the shape that looks harmless and is not
host.Workspace.GetMeshNodeStream(CourseAppTile.RecordPath(viewer, courseSlug))
    .Update(record => record is null ? record! : CourseAppTile.Refreshed(record, …) ?? record);

The transform is not where the cost is. A point access to an absent path makes the owner answer a routing NotFound, and that answer does two things beyond failing this one write:

  1. it TERMINATES the synchronization stream for the path ([SYNC_STREAM] OnError), and
  2. it opens MeshNodeStreamCache's storm-breaker window on the path — a window that fast-fails reads AND writes to it until the exponential backoff elapses.

So the read armed a suppression mechanism aimed at the very path the installer was about to write, and the breaker cannot tell the read that tripped it from the write that follows.

What it looked like from outside

MeshWeaver.Education run 34434475115, shard 1/4, mesh-diagnostics/portal.log93 No node found at … lines, reproduced identically in run 34340974054 on the same portal digest (3.0.0-ci.8079). Four lines per attempt:

warn RoutingGrain        [ROUTE] NotFound: No node found at 'e2e-admin/_App/DataModeling'.
warn SynchronizationStream [SYNC_STREAM] OnError … (Owner=e2e-admin/_App/DataModeling)
warn MeshNodeStreamHandle  [UpdateRemote] ERROR hub=cache/… target=e2e-admin/_App/DataModeling
warn MeshNodeStreamCache   [UpdateQueue] FAILED path=e2e-admin/_App/DataModeling seq=917

…and then, 88 seconds later, Node created at e2e-admin/_App/DataModeling by system-security. Same shape for e2e-admin/_App/AgenticPrimer and e2e-get-datamodeling/_App/DataModeling.

Read as chatter, 93 warnings. Read for what they are, a suppression window on the install's own target, opened by the feature that most wants the install to succeed. It is not what makes any given e2e shard red (that is MeshWeaver.Education#309) and it appears in equal quantity on green runs — "not the cause of that red" is not "harmless".

Why a catch would have been worse than the noise

Swallowing the DeliveryFailureException hides the fault and leaves the breaker open, so the read goes on suppressing the write. Lowering the log level, retrying, delaying the read or pre-flighting with a Query for the exact path all share the same defect: the NotFound is still minted. The gate is the fix because the NotFound is never MINTED.

The shape

Two halves, in this order — the rule is a query answers WHETHER the node is there, the owner's stream answers WHAT it says:

StampWhenInstalled(
    TileExists(mesh, viewer, tilePath),                       // EXISTENCE — the index
    () => AsCaller(access, caller, () =>                      // CONTENT — the owner's stream
        hub.GetMeshNodeStream(tilePath)
            .Update(record => record is null ? record! : refresh(record) ?? record)
            .Take(1)
            .Select(_ => Unit.Default)));

Three things about it are load-bearing.

The gate is an EXACT-path query (path:{x}, no scope: qualifier ⇒ QueryScope.Exact), whose contract for an absent path is zero rows, no error. It reads the index: no routing NotFound, no breaker window. It resolves on the query's OWN complete-snapshot frame (Initial, or the Reset that re-states it), never on a quiet-window timer — a probe resolved on a timer answers "missing" for a node that exists (Systemorph/MeshWeaver#1246). The index trails the store, so "the index has seen it" implies "the store has it"; a stale negative costs exactly one skipped stamp, and the next page open re-asks. That is safe here precisely because the target id is deterministic — a stale negative on a per-attempt id would produce duplicate data instead (MeshWeaver#2229).

The gate's read is STAMPED with the viewer. The record is in the viewer's own partition, and an unstamped MeshQueryRequest resolves Anonymous through the storage hub's own AccessService, whose RLS validators drop every node in a private space — so it answers EMPTY for a node the viewer plainly owns (#406). An unstamped gate would have silently stopped stamping every tile on the mesh, which is why the type's tests pin both directions of the gate against a real record.

The write is CALLED behind the gate, so it must carry the render turn's identity. .Update(…) reads the ambient AccessContext synchronously, at the call — for the transform, for the outbound patch and for the pipeline — and the query pool's thread carries none. AsCaller re-opens the captured context with Observable.Create + a synchronous using around both the factory call and its Subscribe, closed by the thread that opened it (never Observable.Using, which restores on the terminating thread and latches a foreign identity on the subscriber — MeshWeaver#1790).

…and this is why gating the SUBSCRIPTION would not have been enough

A cross-hub .Update(…) is not deferred: MeshNodeStreamHandle.UpdateQueued evaluates IMeshNodeStreamCache.Update(path, …) eagerly, and MeshNodeStreamCache.UpdateRaw enqueues on the path's serial queue there and then. What has to be withheld is therefore the call, not the subscribe. A second, latent bug fell out of the same fact: the provider built the tile write on the render turn and subscribed it after the dwell, so the documented order ("the tile is re-stamped AFTER the marker landed") held for the OBSERVATION only — the write had already been posted. With the write built behind the gate, the order the chain claims is the order that happens, and a page the reader merely paged through no longer touches the record at all.

The controls, in both directions

An absence test goes vacuous silently, so each direction here has a control that fails if the other side is broken. All of them live in Edu/Module's Tests area.

Case What fails if it is wrong
pure StampWhenInstalled_NeverCallsTheWrite_WhenTheRecordIsAbsent the write factory is invoked ⇒ a point access happens ⇒ a NotFound is minted
pure StampWhenInstalled_CallsTheWrite_WhenTheRecordIsThere the control for the row above — a gate hard-wired to "absent" passes that one and fails this
pure StampWhenInstalled_ReadsTheGateOnce a live gate turns one page open into a stream of stamps
pure FoldPresence_IsAuthoritativeOnAFrame_AndSilentOnAnUnrelatedDelta the gate latches a stale answer off a delta
pure AsCaller_HoldsTheScopeAcrossTheCallAndTheSubscribe the write runs as nobody (RLS denies) or latches an identity on the subscriber
live Live_TheGateAnswersBothWays both directions on a real mesh: a never-created path still reports ABSENCE, a real record still reports PRESENCE
live Live_AnAbsentTileIsNeverTouched stamping an uninstalled course errors, or brings the record into being
live Live_AnInstalledTileIsStamped the control for the row above — a stamp that had simply stopped working would pass it

The live cases drive EduCourseNavigationProvider.StampTile, the same composition the provider wires — a control that exercised a re-assembled copy would prove nothing about the code the portal runs.

Hosted scheduler regression — 10 September 2026

The hosted Edu/Module Tests area on Plugins PR #1625 reported 106/107 passed: only StampWhenInstalled_ReadsTheGateOnce failed, observing zero write calls and zero emissions. Its enumerable ToObservable() fixture scheduled notifications on CurrentThreadScheduler; inside the hosted area's active trampoline, the synchronous assertion ran before those queued notifications. The native runner's bare-thread execution had hidden this fixture error.

Running the same test inside an active trampoline reproduced the exact failure locally: 341 native Edu cases passed and this one failed. The fixture now emits the same true, true, false sequence inline through Observable.Create. The exact one-call/one-emission assertion remains, and the native test explicitly establishes the hosted scheduler context when needed. Production stamping and access code are unchanged.

An isolated local hosted fixture also reproduced the original failure by invoking this one case through the existing ModuleTestsArea.Render: zero of one passed, with the same zero calls and emissions. After the fixture correction, all 342 native Edu cases passed with zero failures or skips; 37 additional cases require a mesh. The full compile gate passed all 89 NodeTypes. The corrected case then passed 1/1 in the isolated hosted fixture, using the exact imported Edu/Module Source and Test nodes and the existing ModuleTestsArea.Render, with no copied implementation or extra cases. Its compiled fixture was PreviewEduTests_Host/v17-s0acade9-9e8b3eaab871.dll, status Ok, on framework s0acade9d318075ad94ad248aae875495. The learner's existing plan and notes were unchanged.

Main's independently landed PR #1627 made the same inline-fixture correction. The integration retains that explanation together with this test's explicit hosted-scheduler context, so future native execution exercises the environment that exposed the defect.

Deliberately not asserted: that the un-gated shape still errors. That would pin a platform behaviour rather than this repo's, and it would report a platform improvement as this repo's defect. The discrimination lives in the pure call/no-call pair, which cannot break that way.

Where else the same rule applies

Every other writer and reader of {viewer}/_App/{packageId} in this repo already had it, which is why this was the only site to fix:

The general statement of the rule is core's Doc/Architecture/CqrsAndContentAccess"An OPTIONAL node", and MeshNodeBindingExtensions is the framework's own implementation of this same gate for node-bound form controls.

Reconnecting…
The server was updated. Reloading the page to pick up the latest version.