Pins the pattern semantics of a consumer's include/exclude scope — the
filter over fully-qualified node names (pkg::Sub::Name) that decides which
metadata a source is authoritative for (phase 1 of metadata-source
resolution). * and ** are easy to reinvent slightly differently per port;
this is the same failure mode that produced the cross-port LIKE/ILIKE
divergence fixed in 0.21.6. Every port's runner reads the single committed
cases.json — there is no per-port fixture and no ledger.
cases.json # { cases: [{ name, scope: {include?, exclude?}, expect: [{fqn, matches}] }] }
README.md
- Separator is
::(the package separator). A fully-qualified name is a::-joined sequence of one or more segments. *inside a segment matches any run of characters, but never crosses a::— it is scoped to a single segment.acme::Order*matchesacme::OrderLinebut notacme::deep::OrderLine.- A segment that is exactly
**matches one or more whole segments.acme::**matchesacme::Orderandacme::a::b::Secretbut not the bareacme(zero segments) —**never matches "nothing".**may also appear mid-pattern (acme::**::Order), where it still requires at least one segment between the fixed literals —acme::Orderdoes not matchacme::**::Order(seedouble-star-in-the-middle). - All other pattern characters (including regex metacharacters like
.) are literal — a pattern is never a general regex. includeabsent or empty means "everything is included". Otherwise a name matches if anyincludepattern matches it (union).excludeis applied afterinclude— a name excluded is excluded regardless of whichincludepattern admitted it.excludewith noincludenarrows the "everything" default.- Matching is case-sensitive — a pattern and a name must agree in case
(
acme::Orderdoes not matchacme::orderorACME::Order).
Each port's runner reads cases.json, and for every case: compiles scope
with its native pattern compiler, then for every expect entry asserts
matchesScope(fqn, compiledScope) === matches. All ports assert the same
booleans — single-source, byte-identical expectations.
server/typescript/packages/metadata/src/scope.ts (compileScope /
matchesScope / compilePattern) is the TypeScript reference this corpus was
authored against — moved there from sdk under FR-023 so codegen-ts could use
it without a sdk dependency; @metaobjectsdev/sdk re-exports it unchanged, so
existing importers are unaffected. Other ports are free to implement the same
semantics however is idiomatic (e.g. a native regex engine, or a hand-rolled
segment matcher) as long as every case in this file passes.
- TypeScript:
server/typescript/packages/sdk/test/scope-conformance.test.ts(against the reference implementation above). - Python:
server/python/tests/conformance/test_scope_conformance.py(againstserver/python/src/metaobjects/scope.py, whosematches_scopeusesre.fullmatch— every compiled pattern is already anchored, but a.matchwould still let a trailing-newline-in-the-name case through, whichfullmatchcorrectly refuses). - Java, Kotlin and C# have no runner yet —
scopestays Node-CLI-only (seedocs/features/metadata-sources.md).