Content reachability — what was measured, and what was refuted
On 2026-09-01 the question "has the mesh fallen behind the repo?" was investigated against
memex.meshweaver.cloud. The answer turned out to be no — but the investigation surfaced a
different, real defect, and refuted two plausible checks along the way.
This page is the durable record. The invariant itself is pinned by a unit test, not by anything
here: SkillFileParserTest
(ASkillInAPluginPartition_IsItsOwnMainNode). There is deliberately no live-mesh gate — see
Why there is no sentinel below.
The defect: imported, Active, and invisible
get @Hosting/Skill/deployment → Active, version 7, full content
search path:Hosting/Skill/deployment → count: 0
The node is there. It simply cannot be found. The catalog's is:main projection is SQL
n.main_node = n.path, and these nodes carry mainNode: Skill/{id} instead of their own path — so
they are hidden by the same rule that hides _-satellites. Nothing errors, nothing goes red, and
the skill never reaches the composer's /-menu or any query that resolves skills.
Root cause and fix: #1053 /
MeshWeaver#2939, fixed in
#1064. SkillMarkdown.cs mints
new MeshNode(id, SkillNodeType.RootNamespace), freezing the stored, non-nullable MainNode at
Skill/{id}; SkillFileParser.cs then rebases with node with { Namespace = ns } — and a record
with copy does not re-run the MainNode initializer.
The A/B proof is the sibling parser: AgentFileParser.cs constructs with the real namespace, so its
default is right the first time. That is why .md AGENTS are fine and .md SKILLS are not —
and why Hosting/Agent/platform-update resolves while Hosting/Skill/platform-update does not.
Measured blast radius — 7 nodes, not 6
34 declared Skill/Agent nodes across 53 packages, each read twice (once by get, once by
search). 33 existed; 26 were findable. The seven that diverged:
| Node | get |
search |
stored mainNode |
|---|---|---|---|
Hosting/Skill/deployment |
✅ | ❌ | Skill/deployment |
Hosting/Skill/deployment-activity |
✅ | ❌ | Skill/deployment-activity |
Hosting/Skill/instance |
✅ | ❌ | Skill/instance |
Hosting/Skill/platform-update |
✅ | ❌ | Skill/platform-update |
Essentials/Skill/email |
✅ | ❌ | Skill/email |
Store/Skill/ci-policy |
✅ | ❌ | Skill/ci-policy |
RemoteControl/Skill/remote |
✅ | ❌ | Skill/remote |
🚨 RemoteControl/Skill/remote is not listed in #1053 — it was found by this sweep. Verifying
the fix means checking all seven, not the six the issue names.
The set of "get ✅ / search ❌" is EXACTLY the set of mainNode != path — no false
positives, no unexplained cases. That equivalence is what makes a static test a sound substitute
for a live probe: the source already determines the property. Every .json-authored skill
(Hosting/Skill/setup-environment, Store/Skill/plugin, Essentials/Skill/models) is fine,
because a .json node carries its mainNode explicitly. The two conventions coexist inside the
same partitions, which is why this stayed invisible: Hosting/Skill looks half-populated rather
than broken.
Live-only nodes, at risk
Five nodes exist on the mesh that no commit declares. AGENTS.md is explicit that a GitSynced
space is rewritten from main, so these are queued for destruction; they have survived only
because a node newer than the sync's conflict horizon is protected from the prune, and that
protection ends when the horizon advances.
Hosting/Skill/{live-defect-triage,loki-error-triage}andHosting/Agent/{live-defect-triage,loki-error-triage}— being rescued in #1052.Essentials/Skill/og-card— declared by no commit and covered by no open PR. It is a leftover of the 2026-08-28 skills consolidation, which deleted the file while the mesh copy stayed. Unowned as of this writing.
🚫 Two checks were investigated and REJECTED
1. "Commits behind" is NOT measurable from GitHubSyncConfig
A drift check reading lastSyncedAt / lastSyncCommitSha was built, run, and thrown away. It was
wrong, and it would have been worse than no check:
Hosting/_GitSyncrecordedlastSyncedAt: 2026-08-19whilelastSyncCommitShanamed a 2026-08-30 commit — and the partition had in fact imported 118 nodes on 2026-08-31. Reading "13 days stale" off that field condemns a healthy, freshly-imported partition.lastSyncedAtis the two-way sync's CONFLICT HORIZON, deliberately not advanced by an import that preserved server-newer nodes.- Across the 34 provisioned partitions, 33 record the IDENTICAL
lastSyncCommitShawhile theirlastSyncedAtspans 2026-08-06 → 2026-08-31. A field uniform across partitions whose sync times differ by 25 days is not per-partition import evidence either.
🚨 There is no field on GitHubSyncConfig meaning "this partition last successfully imported
commit X". Closing that gap in the platform would be worth doing. Until then, staleness cannot be
measured from outside, and no gate should claim to measure it.
2. A single read path cannot detect this class of defect
The first version of the check asked only get @Hosting/Skill/* — a child listing — and reported
the short answer as proof of absence. That listing goes through the very is:main projection that
has the bug, so it reported seven live nodes as dropped. Six confident false positives, in a tool
built to detect silent failures.
The lesson generalises. AGENTS.md already records that an unreadable list passes every check while verifying nothing. This is its mirror: a list that HIDES rows reports them as absent. Both are the same failure — trusting a query beyond what it can see. Absence reported by a query that shares the defect is not absence.
Detecting the divergence at all required reading the mesh by two independent paths and comparing them. That is a useful diagnostic technique; it is not, as it turned out, something that needs to run on a schedule.
Why there is no sentinel
A scheduled live prober was built for this and then deleted, along with the MESH_READ_TOKEN
secret it needed. The reasoning, recorded because the pull toward "add a monitor" is strong:
- Both defects are code bugs with code fixes, each pinnable by a unit test inside this repo:
#1053 is a
MainNodefix inSkillMarkdown.cs/SkillFileParser.cs, pinned bySkillFileParserTest; core #2942 is a query-union fix inStaticNodeQueryProvider. - The property is determined by source, not by the mesh. The measured equivalence above —
unreachable set ==
mainNode != pathset — means a static test over the parser answers the same question a live probe does, on every PR, with no credential. - A PR gate needing a production token cuts against the standing goal that each repo builds using only itself — no core checkout, no container registry, no live-mesh credential. A smaller true gate beats a larger one gated on a secret nobody provisioned.
What genuinely cannot be expressed statically is the live-only node check (§ Live-only nodes): nothing in the repo can know what someone created directly on a mesh. That is real, and it is the one thing lost by deleting the prober. It is not worth a production credential on a PR gate — a mesh-side concern belongs in a mesh-side tool, and the underlying hazard is better removed by making live edits land in the repo the same session, which AGENTS.md already requires.