You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A PluginCatalog node over a local node-repo checkout lists nothing — BuildSource never selects the node-repo source, and the content has no format field #3384
Split out of #3359 (its fix option 3), where it was found and measured — it is its own defect and reaches every checkout-served source, not only the self-registry mode.
What happens
A PluginCatalog node created over a local node-repo checkout (sourceRepoPath: /plugin-repos/Education, the format memex-local mounts and NodeRepoPackageSource reads) creates fine, its Catalog area activates, and it renders "No installable packages found."
Why
CatalogLayoutAreas.BuildSource builds the area's source with
and never passes nodeRepo: true, so a LOCAL path falls through to GitPackageSource — the package.json format — which lists nothing for a node-repo tree. The factory's own comment names the outcome ("before this, a local path silently fell through to the package.json source below and listed nothing"). PluginCatalogContent carries only SourceRepoPath / SourceRef / SourceSubdir / Description — no format field — so a catalog node cannot select the node-repo source even deliberately.
Consequence
The documented human fallback for a stale install — "a human opening the catalog page … offers the same Update" — is unreachable for every checkout-served source. On a self-registry memex-local there is no catalog page at all out of the box (it seeds no PluginCatalog node), and creating one by hand does not help until this is fixed. #3359's fix (the mounted checkouts reconcile on every boot) removes the need for the fallback in that mode; this issue is what stands between an operator and the catalog page over any local checkout.
Fix shape
Either a Format member on PluginCatalogContent (node-repo default, package-json opt-in — the same knob PluginCatalog:Sources:N:Format already has), or detect the node-repo shape (a depth-2 <Folder>/index.json with a root nodeType — the predicate memex-local's is_node_repo and NodeRepoPackageSource already share) in BuildSource. Then memex-local can seed one PluginCatalog node per mounted repo so the page exists on a fresh install.
Measured on 2026-09-05 by the #3359 investigation (two catalog nodes over /plugin-repos/Education and /plugin-repos/Plugins, both empty).
Fixed on main by #3387 (the merge queue does not fire Closes links here, so closing by hand after
verifying the code actually landed):
$ git show origin/main:src/MeshWeaver.PluginCatalog/PackageSources.cs | grep -c IsNodeRepoFormat → 3
$ git show origin/main:src/MeshWeaver.PluginCatalog/PluginCatalogContent.cs | grep -c Format → 3
PluginCatalogContent now carries Format — same values and same node-repo default as the PluginCatalog:Sources:N:Format configuration knob — and both readers resolve it through the one
shared rule PackageSources.IsNodeRepoFormat. The browse view stops taking nodeRepo's false
default, and PluginUpdateWatcher stops hardcoding true, so the two readers of a catalog node can
no longer disagree about the same repository.
CatalogSourceFormatGuard pins it mechanically: every FromRepo call site must pass IsNodeRepoFormat(...), with a floor on the number of call sites so a renamed factory fails loudly
rather than reporting a clean tree, plus a self-test that the matcher sees both a hardcoded and a
resolved call including one split across lines. Verified it can fail — restoring both pre-fix call
sites reddens it and names CatalogLayoutAreas.cs:410 and PluginUpdateWatcher.cs:169 exactly.
Also corrected FromRepo's own summary, which claimed "A local path always uses the git-CLI
package.json source" — untrue since the local node-repo source landed, and the sentence that made
this defect easy to miss.
Activity
rbuergi commentedon Sep 6, 2026
Fixed on
mainby #3387 (the merge queue does not fireCloseslinks here, so closing by hand afterverifying the code actually landed):
PluginCatalogContentnow carriesFormat— same values and samenode-repodefault as thePluginCatalog:Sources:N:Formatconfiguration knob — and both readers resolve it through the oneshared rule
PackageSources.IsNodeRepoFormat. The browse view stops takingnodeRepo'sfalsedefault, and
PluginUpdateWatcherstops hardcodingtrue, so the two readers of a catalog node canno longer disagree about the same repository.
CatalogSourceFormatGuardpins it mechanically: everyFromRepocall site must passIsNodeRepoFormat(...), with a floor on the number of call sites so a renamed factory fails loudlyrather than reporting a clean tree, plus a self-test that the matcher sees both a hardcoded and a
resolved call including one split across lines. Verified it can fail — restoring both pre-fix call
sites reddens it and names
CatalogLayoutAreas.cs:410andPluginUpdateWatcher.cs:169exactly.Also corrected
FromRepo's own summary, which claimed "A local path always uses the git-CLIpackage.json source" — untrue since the local node-repo source landed, and the sentence that made
this defect easy to miss.
🤖 Filed from Claude Code.