Repository navigation
Description
User-visible symptom
On memex.systemorph.com the Agentic Engineering course does not exist: its Store cover renders (root Store/Plugin node, created 2026-08-28 22:40 by system-security), but the partition lists only _GitSync + _Policy. The RiCube demo lesson, all 9 modules, exercises — absent. On memex.meshweaver.cloud the same partition has 21+ visible nodes.
The measurement (all on systemorph, 2026-08-31 09:00–09:25Z)
-
The durable layer HAS the content.
get_versions AgenticEngineering/Introduction→ v1, 2026-08-28T22:40:38Z, "Module 1 — Introduction",Edu/Lesson. The 08-28 install/import DID write the nodes. Butsearch namespace:AgenticEngineeringand the children listing return only the two satellite-routed nodes (_GitSync,_Policy). -
Writes report success and vanish — minimal repro.
create AgenticEngineering/WriteLaneProbe(Markdown) →Created: AgenticEngineering/WriteLaneProbe; version row exists (v1, changedBy rbuergi); the node is absent from the children listing seconds later and stays absent. (Leftover probe: a writer with Delete can remove it at/AgenticEngineering/WriteLaneProbe/Delete.) -
GitSync update can never heal it, and its manifest LATCHES the false green. Four
update/forceruns (activitiesffb5ef21,1b2b7afd,da5acd8a→attempt…-1b0ad8d2,06041aa0→attempt…-cc5c68c5):- attempt 09:06 (fresh fingerprint
e72dee80…after a content upload):Imported 9 node(s), 6 FAILED— the "9" are recorded in the import-manifest as done although they are invisible like everything else; - attempt 09:19 (same fingerprint,
force: true):Imported 0 node(s), 6 FAILED— force does NOT bypass the per-file manifest, so the 365 latched files are never retried. A false-passing write poisons the manifest durably. - Recycling the partition hub (
recycle @AgenticEngineering) before the 4th run changed nothing.
- attempt 09:06 (fresh fingerprint
-
The GitSync wrapper activity false-passes on top. Each wrapper logs
Imported ImportedWithErrors (0 node(s))at Information and endsstatus: Succeeded, while its child attempt activity endsstatus: Warningwith 6 ⚠ lines.ImportedWithErrors+Succeededin one line is the gate-that-cannot-fail shape. -
The 6 hard failures name a missing dependency:
Upsert of 'AgenticEngineering/Training/Event/SlotNN' failed: NodeType 'Systemorph/Event' is not registered— the plugin manifestrequires["Edu@^1.0.0","Publish@^1.0.8","Store@^1.0.0","Systemorph","Video@^1.0.0"], and theSystemorphmodule on this deployment does not provideSystemorph/Event. (Separately: memex-operational training-slot nodes probably should not ride in the course repo at all.) -
The partition index is also missing every 08-28-created partition.
autocomplete @/listsDataModelingbut none ofAdvancedBusinessRules, AgenticBusiness, AgenticEngineering, AgenticOffice, AgenticPrimer, AgenticPrimerDe, Claims, ClaimsDeepfield— even though e.g. AgenticPrimer's CONTENT is fully searchable.@/Agentic→ 0 results.
Reading
The root is a Store/Plugin node with installPaths (11 sections) and homeRootNodeType: Edu/Page. Everything above is consistent with the install-materialization layer shadowing the durable layer for a plugin partition whose install never completed ([static-node-shadows-durable-row #2534 family]): reads answer from the (empty) plugin layer, writes land beneath it, acknowledged and versioned, unreadable. The known siblings each cover a piece (#2534 shadowing, the edu install gate, store root churn); what is NEW here and most dangerous is the write lane confirming success for writes no reader can ever see — the same class as the #2229 write-lane defect and the "fail-closed fallbacks forge correct-looking bugs" rule.
Asks (root-cause order)
- A write into a shadowed/half-installed partition must FAIL, not succeed invisibly — the acknowledgement must come from the layer reads answer from.
- The import manifest must record per-file success only on a read-back-visible write (or at minimum never latch when the partition's install state is incomplete).
- The GitSync wrapper must propagate the attempt's Warning/Failed status and its ⚠ lines (
Succeeded+ImportedWithErrorsmust be impossible). - Complete/repair the AgenticEngineering install on systemorph (and register
Systemorph/Eventor strip the Slot nodes from the course repo). - Top-level partition index: 08-28-created partitions missing from autocomplete while their content is searchable.
Evidence: activity nodes under AgenticEngineering/_Activity/ on systemorph (paths above); version rows for AgenticEngineering/Introduction and AgenticEngineering/WriteLaneProbe.
Activity
rbuergi commentedon Sep 1, 2026
Re-measured on systemorph 2026-09-01 (~14:0xZ) — unchanged, and the stated root cause is falsified
State is exactly as reported, 4 days on
search namespace:AgenticEngineering scope:descendants_GitSync(v1),_Policy(v1), both 2026-08-28get @AgenticEngineering/*get @AgenticEngineering/IntroductionNot foundget_versions AgenticEngineering/Introductionsystem-security,Edu/Lessonget_version AgenticEngineering/Introduction 1state: "Active", fullMarkdownContentget_versions AgenticEngineering/WriteLaneProberbuergi,MarkdownTwo things ruled out by measurement
1. It is NOT the two-read-seams-disagree defect (#2939 / #2970 / Plugins#1053). Both read seams agree the node is absent; it is the version store that disagrees with both. That had to be checked — the disagreeing-seams class is live and confirmed, and it produces a superficially similar "the node is there but you can't see it".
2. It is NOT install-materialization shadowing a Store-plugin partition. This is the important one, and it costs the issue its stated root cause.
The identical outcome exists on memex.meshweaver.cloud, in
sglauser— a plain user partition. NoStore/Pluginroot, noinstallPaths, no install of any kind, nothing to shadow the durable layer with:get_versions sglauser/MeshWeaverInstance/sglauser-local-3→ v1, 2026-08-31T15:44:49Z,system-security,MeshWeaverInstanceget @sglauser/MeshWeaverInstance/sglauser-local-3→Not foundsearch namespace:sglauser scope:descendants→ 3 nodes, all Markdown from April;search nodeType:MeshWeaverInstance→ 22, every one underrbuergi/…Admin/_PluginGrant/sglauser-local-3(3 s later, samesystem-securityidentity, different partition) → readable, v1,ActiveThat is #2915: the registry authenticator cannot read that instance node, so instance-key resolution answers 503 forever with "This is NOT a statement about your key or your grant" — which is true about the key and the grant, and wrong about the word temporarily.
Also ruled out
system-securityand an interactive user (rbuergi) produced it, and the samesystem-securitywrite intoAdminin the same operation landed visibly.rbuergi/MeshWeaverInstance/ci-crm, written 2026-08-28, reads back fine.The partition-index half of point 6 reproduces on memex too:
autocomplete @/sglauser→ 0 results whilesearch namespace:sglauser scope:descendantsreturns its content.autocomplete @/rbuergi→ the partition is listed asrbuergi@systemorph.com.What this changes about the asks
Ask 1 ("a write into a shadowed/half-installed partition must FAIL") is right in spirit but scoped too narrowly — it is not shadowing and not install state. The rule that covers both instances is:
Asks 2 (manifest must record only read-back-visible writes) and 3 (
Succeeded+ImportedWithErrorsmust be impossible) stand unchanged and are independently actionable.Not repaired, deliberately
The root question — why the node row is unreachable while its version row is not — needs the partition schemas inspected on the portal, which the MCP surface cannot do. Do not repair by restoring versions until the write lane is fixed: a restore takes the same write path and can land the same way. Both instances are still live and reproduce on demand, so the evidence has not decayed.
This measurement is committed as
Doc/Architecture/DurableButUnreadable(PR linked below) — the three-seam diagnostic, the two instances, and what each rules out.Nothing was mutated. All queries above are read-only.
rbuergi commentedon Sep 1, 2026
Cross-linking two findings from today, because they are about the same seam
Recording a connection between this issue's measurement and one made independently a few hours earlier, since they constrain each other.
This issue's finding (measured on both portals, now in
Doc/Architecture/DurableButUnreadable): a node's version row is readable while the node row is not, on two unrelated partitions, with both read seams agreeing.sglauseris a plain user partition with noStore/Pluginand no install — which falsifies the plugin-install-materialization root cause this issue originally proposed.The independent finding, from a one-field
patchonProvider/_Policy(memex, 12:27:54Z, recorded on #2896): the write surface reported…and the index then showed the node had gone version 1 → 2. The write had landed. Point reads on that node answered
Unavailable … no verdict within 10sfor several minutes afterwards, whilesearchanswered instantly.Why they belong together. Both are the same asymmetry: the version/index side of a write completes while the node side does not answer. One shows it at write time (a landed write reported as failed); the other shows it at read time (a durable version whose node row is unreachable). If the write lane can acknowledge a version without the node row becoming readable, then "durable but unreadable" is what that state looks like afterwards — which would make these one defect observed at two moments rather than two defects.
That is a hypothesis, not a conclusion — I have not shown that the same mechanism produced both, and the two occurred on different nodes and different partitions. But it is cheap to test and it changes where to look: instrument the write path's two-phase completion rather than hunting the read path for why a row is missing.
It also reinforces the standing warning on this issue: do not repair by restoring versions until the write lane is understood. A restore takes the same path that produced the state, and on the evidence above that path can report failure while succeeding — so a "failed" restore may well have landed, and a retried one may double-write.
rbuergi commentedon Sep 1, 2026
Measurement: this is NOT the same mechanism as #2897 — and the discriminating read is one step
Investigated together with #2897 and #2885 on the hypothesis that all three were one mechanism (the
partition's payload outgrew the transport, so the delivery carrying the write could never land).
That hypothesis is falsified for this issue. #2897/#2885 are one mechanism; #2899 is a different
one that happened to be measured in the same window.
The decisive measurement (systemorph, read-only, 2026-09-01)
get_versions AgenticEngineering/Introductionsystem-security,Edu/Lessonget @AgenticEngineering/IntroductionNot found: AgenticEngineering/Introductionsearch namespace:AgenticEngineering scope:descendants_GitSync(22:40:22),_Policy(22:40:31)The two surfaces read different tables.
get_versionsreads the node history, written by adatabase trigger on the row itself.
getand everyscope:childrenlisting read thecurrent-state row through the live query path.
So the accurate statement of the symptom is not "371 durable nodes nobody can read" but:
What that rules out
listing with unusable content (view renders empty). It cannot remove a node from a children
listing, and it cannot make a point read answer
Not found. The 6NodeType 'Systemorph/Event' is not registeredfailures are a real, separate problem (they are the 6 that did report failure),but they are not what hides the other 365.
2026-08-28 22:40. Message delivery to the AgenticEngineering message hub exceeds the Orleans 100 MB MaxMessageBodySize and cannot be delivered #2897's five 142 MB frames are 2026-08-31 09:06 — three days later, and
inside the remediation attempt, not the original write. The oversized frame is a consequence of
re-importing this course, not the reason its first import went invisible.
per-activation, so a rebuilt hub re-derives the same missing announcement. Recycling changing
nothing is evidence for this mechanism, not against it.
The mechanism, and where it lives
The durable write and the mesh-wide announcement are two separate steps. The row goes to
storage;
IMeshChangeFeedseparately tells the running mesh the path exists. Everything thatdecides reachability keys off the announcement, not the row:
PathResolutionServicecaches path resolution — a path cached as a miss stays a miss, sorouting answers
No node found at '…'for the life of the process.scope:childrenlisting runs its SQL once, atInitial, and re-queries only on achange notification that passes the relevance gate; consumers share that snapshot via
Replay(1). One lost notification freezes the listing permanently — which is exactly why a pointread and a listing can disagree.
MeshNodeTypeSource's class documentation already names this the #817/#824 announce-loss class.Ranked candidates, all code-cited, for where the announcement was lost here. The storage backend
is in
MeshWeaver.Plugins, so most of these are fixed there, not in core:public.top_level_indexis never rebuilt on partition CREATE. It is a materialized view.Its only rebuild call sites are the run-once migration Job and
DeletePartition.EnsureSchemaAsyncregisters the new schema insearchable_schemasand stops. This isitem 6 of this issue, exactly — every partition created after the last migration is durable and
permanently absent from
@/autocomplete. The comment atPostgreSqlCrossSchemaQueryProvider.csclaiming it is rebuilt on create is false in the code.n.state != 2. Every query hard-filters to Active. A row persisted atTransient/Newisversioned, historied, acknowledged — and invisible to every query, with no log line.
n.main_node != n.path. NoteIntroductionv1 carriesmainNode: AgenticEngineering/Introductionwhile
_PolicycarriesmainNode: AgenticEngineering; anyis:mainlisting filters on this.GenerateChildrenClauseemitsn.namespace = @scopeNs— theonly text equality in that generator that is not case-folded, while schema routing lowercases
and
PathMatcherisOrdinalIgnoreCasethroughout.description/category/icon/display_order/… while the history trigger still writes a row —literally "durably versioned, no announcement".
failed broadcast; the cross-process pg_notify route silently increments a discard counter.
A separate defect found on the way, worth its own issue: the two
ExcludedSchemaslists areinverted on
agentandauth— the runtime list excludesauthand deliberately keepsagent; the migration's list does the opposite. Every deploy wipes the registry and repopulates itin the state each side documents as a bug, until the runtime's next 30 s sync corrects it.
Confirmed as stated in this issue
The two asks that need no further diagnosis are confirmed by this measurement and should stand:
acknowledgement — otherwise a false-passing write latches the manifest and
forcecan neverretry it (this is what makes the loss permanent and invisible to the repair tool);
Succeeded+ImportedWithErrorsin one wrapper activity must be impossible.Conserved
The full field guide — the discriminating measurement, both mechanisms, and the rules that follow —
is committed as a doc page rather than left in this thread:
Doc/Architecture/AcknowledgedButInvisibleWrites(PR linked below).This issue stays open. The core-side half (the transport bound, #2897) is fixed in that PR; the
announce-loss half diagnosed here is not, and its fix belongs in the storage backend.
rbuergi commentedon Sep 2, 2026
Re-measured 2026-09-02 (read-only): the write lane is not the defect
The decisive probe.
autocomplete @/AgenticEngineering/Introductionreturns the node and sixof its children, with correct names and node types (
Edu/Lesson,Edu/Quiz,Edu/Page,Edu/CourseInvite,Markdown). A row no reader can see cannot be returned by autocomplete, so the371 nodes are durably present and reachable. The write landed. The read seam is what fails.
@/AgenticEngineering/likewise listsTDD,Slides,RiCube,Trainees,Training,DemoAgent,Exercises,Slides/S01…S39.Two hypotheses died on evidence that could have gone the other way — recording them so nobody
spends the day again:
get_version AgenticEngineering/WriteLaneProbe 1mainNode == path, node invisibleis:main/n.main_node = n.pathfilter (#2939)get_version AgenticEngineering/_Policy 1mainNode != path, node visiblesearch namespace:AgenticPrimer scope:descendants_Accessshape (Public — Viewer+Anonymous — Viewer, nothing else)Also, contra the issue text and the doc:
_GitSyncand_Policyare not satellite-routed.SatelliteTableMapping.IsSatellitePathmatches the exact segment list, which does not includethem — they are ordinary
mesh_nodesrows in the same table as the 371 invisible ones. So atable-routing split cannot explain the split in visibility.
What survives, 5 of 5 cases including one that could have falsified it: a row in that partition
passes the read filter iff its
main_nodeis the partition rootAgenticEngineering— which isexactly the prefix its two grants project at (
COALESCE(main_node, namespace)inrebuild_user_effective_permissions) and exactly the column the per-schema access clause folds thecaller's effective permissions against (
n.main_node, notn.path). Settling it needs threecolumns read on that portal, against
agenticprimeras the working control:Hypotheses (a) and (b) are both ruled out. (a) transport/#2897: a refusal is loud and terminal
and leaves no version row, and the frames post-date the import by three days; #3018 is merged and
the symptom is unchanged. (b) the untyped-content degrade (#2952/#3006): a degrade leaves the node
in the listing with unusable content, and
get_versionreturns fully-typed content here.One producer of this class was in core and is fixed — #3035
StaticNodeStorageAdapterwas the one of six serve seams that did not honourMeshNode.IsDefinitionOnly, and it is the seamPersistenceServicereads. Because the staticprovider is fixed-namespace (first provider band) and read-only (absent from the write chain),
ReadandWritedisagreed about which provider owns the path and only the write side was everasked: acknowledged, version row written, unreadable forever. #3035 fixes it and adds
AcknowledgedWriteIsReadableTest, which pins the invariant the platform had no test for — a writethe storage layer acknowledged must be readable back through the seam readers use — and fails
against the pre-fix code with this exact signature.
#3035 deliberately does not close this issue. It is a different producer from the one live here,
and closing would bury 371 still-unreadable nodes.
Full RCA is committed at
Doc/Architecture/DurableButUnreadable(this repo,src/MeshWeaver.Documentation/Data/Architecture/DurableButUnreadable.md) — the core mechanism, thefalsifications above, the resolution of all three hypotheses, and the named residual.
Still open here, untouched: repairing the partition, and the GitSync wrapper activity reporting
Succeededover a child that endedWarning. On the latter — the sibling half is already fixed(
GitHubSyncService.MayAdvanceBaseline, #2229 item C); the status fold was left alone deliberatelybecause
Finish(v, override)isMAX(floor, fold)with dual writers that split-brain, and anunstudied change to terminal-status semantics inside a gate is worse than a named open item.
test(#2899): seal the awaits with .Await()
Merge pull request #3035 from Systemorph/fix/2899-write-lane-false-pass