diff --git a/src/MeshWeaver.Graph/Configuration/CodeQueryResolver.cs b/src/MeshWeaver.Graph/Configuration/CodeQueryResolver.cs
index e10dddf2a3..bc543af2a3 100644
--- a/src/MeshWeaver.Graph/Configuration/CodeQueryResolver.cs
+++ b/src/MeshWeaver.Graph/Configuration/CodeQueryResolver.cs
@@ -25,8 +25,10 @@ namespace MeshWeaver.Graph.Configuration;
/// - A namespace:X value with no / (e.g. bare Source
/// or Test) is rebased onto the NodeType's own path so the defaults
/// read as "my own Source / Test folder".
-/// - Every emitted query is ANDed with nodeType:Code so non-code
-/// children never leak in.
+/// - A query that does not already name a node type is ANDed with
+/// nodeType:Code, so non-code children never leak in. One that names its
+/// own (nodeType:Scope, say) is left as authored — the filter is a
+/// DEFAULT, not an override.
///
///
public static class CodeQueryResolver
diff --git a/test/MeshWeaver.Hosting.Monolith.Test/SourceDiscoveryUnavailableTest.cs b/test/MeshWeaver.Hosting.Monolith.Test/SourceDiscoveryUnavailableTest.cs
index 701f03dc9a..94b96d3428 100644
--- a/test/MeshWeaver.Hosting.Monolith.Test/SourceDiscoveryUnavailableTest.cs
+++ b/test/MeshWeaver.Hosting.Monolith.Test/SourceDiscoveryUnavailableTest.cs
@@ -259,16 +259,38 @@ public sealed class StarvedSourceQueryProvider : IMeshQueryProvider
/// produces it
/// (namespace:{selfPath}/Source scope:subtree nodeType:Code).
///
- /// 🚨 Matched on the namespace: FORM, not on the bare path, so only source
- /// DISCOVERY starves. Node creation and single-node reads under the same subtree use
- /// path:-shaped queries and must keep working — otherwise the test could not put a
- /// healthy source node in the mesh in the first place, and "the code is fine, the read is
- /// not" would be unprovable. Note the type's /Test query is deliberately NOT starved:
- /// one leg dies while the other answers, which is precisely the PARTIAL source set that used
- /// to reach Roslyn.
+ /// 🚨 Matched on the namespace: FORM **and** nodeType:Code, so only source
+ /// DISCOVERY starves. Node creation and single-node reads under the same subtree must keep
+ /// working — otherwise the test could not put a healthy source node in the mesh in the first
+ /// place, and "the code is fine, the read is not" would be unprovable. Note the type's
+ /// /Test query is deliberately NOT starved: one leg dies while the other answers, which
+ /// is precisely the PARTIAL source set that used to reach Roslyn.
+ ///
+ /// 🚨 The nodeType:Code half is load-bearing, and its absence was a real flake
+ /// (shard 1, 2026-08-13). The SECURITY layer reads its policy and grants with
+ /// namespace:-shaped queries over the SAME subtree —
+ /// namespace:…/Source id:_Policy nodeType:PartitionAccessPolicy and
+ /// namespace:…/Source/_Access nodeType:AccessAssignment — so a marker that matched the
+ /// namespace alone starved those too, and the CreateNode at the top of this test hung
+ /// (observed: Executing(CreateNodeRequest, 33014ms)) until the 30 s assertion gave up.
+ /// It passed whenever those security queries were already cached and failed when they were
+ /// cold, which is why it reproduced on a CI shard and never locally (10/10 green).
+ /// CodeQueryResolver appends nodeType:Code to a source query that does not already
+ /// name a node type, and this type declares no Sources — so its discovery runs the
+ /// DEFAULT query (namespace:{path}/Source scope:subtree) and does carry the clause, while
+ /// the security queries carry node types of their own. That separates them here. (A type whose
+ /// declared source query named some OTHER node type would not be starved by this marker; nothing
+ /// in this suite does, and the starve is asserted to still bite — see the test's own proof.)
///
private const string StarveMarker = "namespace:SourceUnavailableTest/StarvedSourceType/Source";
+ ///
+ /// The discriminator that keeps the starve to SOURCE DISCOVERY — see the note on
+ /// . Without it the security policy/grant reads over the same
+ /// namespace starve as well, and node creation into that subtree hangs.
+ ///
+ private const string SourceDiscoveryMarker = "nodeType:Code";
+
///
public string Name => nameof(StarvedSourceQueryProvider);
@@ -280,7 +302,8 @@ public IObservable> Query(
MeshQueryRequest request, JsonSerializerOptions options)
{
var starve = request.EffectiveQueries
- .Any(q => q?.Contains(StarveMarker, StringComparison.OrdinalIgnoreCase) == true);
+ .Any(q => q?.Contains(StarveMarker, StringComparison.OrdinalIgnoreCase) == true
+ && q.Contains(SourceDiscoveryMarker, StringComparison.OrdinalIgnoreCase));
return starve
? Observable.Throw>(new TimeoutException(
"No response received for SubscribeRequest within 00:01:00 — the owning "