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:
- it TERMINATES the synchronization stream for the path (
[SYNC_STREAM] OnError), and - 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.log — 93 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:
Store/Installer—Localizer.RegisterAppRecordprobes withMeshQueries.FindNode(the index, empty-on-absent) and then either creates or heals;RemoveAppRecorddoes the same before deleting.AppTileRefresh.WriteRecord's node-stream leg runs only for a record the plan READ, so it is never a pre-existence write, and its per-viewer and mesh-wide sweeps readpath:{viewer}/_App scope:children.- Core's logon-time icon adoption and the home grid read
scope:childrentoo; the grid paints from query rows and never opens a per-tile stream. - The home grid's drag-to-arrange writes only paths that came back from its own listing.
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.