Namespace Resolution
When a pipe references a concept or another pipe, MTHDS resolves that reference through a well-defined set of rules. Understanding these rules is essential for working with multi-bundle packages and cross-package dependencies.
Three Forms of Reference
Every reference to a concept or pipe uses one of three forms:
| Form | Syntax | Example |
|---|---|---|
| Bare | name |
ContractClause, extract_clause |
| Domain-qualified | domain_path.name |
legal.contracts.NonCompeteClause, scoring.compute_score |
| Package-qualified | alias->domain_path.name |
acme->legal.ContractClause, docproc->extraction.extract_text |
How References Are Parsed
Cross-package references (-> syntax): The string is split on the first ->. The left part is the package alias, the right part is parsed as a domain-qualified or bare reference.
Domain-qualified references (. syntax): The string is split on the last .. The left part is the domain path, the right part is the local code (concept code or pipe code).
Disambiguation between concepts and pipes in a domain-qualified reference relies on casing:
snake_casefinal segment → pipe code (e.g.,scoring.compute_score)PascalCasefinal segment → concept code (e.g.,scoring.WeightedScore)
This is unambiguous because concept codes and pipe codes follow mutually exclusive casing conventions.
Resolution Order for Bare References
Bare Concept References
When resolving a bare concept code like ContractClause:
- Native concepts — check if it matches a native concept code (
Text,Image, etc.). Native concepts always take priority. - Current bundle — check concepts declared in the same
.mthdsfile. - Same domain, other bundles — if the bundle is part of a package, check concepts in other bundles that declare the same domain.
- Error — if not found in any of the above.
Bare concept references do not fall through to other domains or other packages.
Bare Pipe References
When resolving a bare pipe code like extract_clause:
- Current bundle — check pipes declared in the same
.mthdsfile. - Same domain, other bundles — if the bundle is part of a package, check pipes in other bundles that declare the same domain.
- Error — if not found.
Bare pipe references do not fall through to other domains or other packages.
Resolution of Domain-Qualified References
When resolving domain_path.name (e.g., legal.contracts.extract_clause):
- Look in the named domain within the current package.
- If not found: error.
Domain-qualified references are explicit about which domain to look in. They do not fall through to dependencies.
Resolution of Package-Qualified References
When resolving alias->domain_path.name (e.g., docproc->extraction.extract_text):
- Identify the dependency by the alias. The alias must match a key in the
[dependencies]section of the consuming package'sMETHODS.toml. - Look in the named domain of the resolved dependency package.
- If not found: error.
Visibility rules for cross-package pipe references:
- The referenced pipe must be exported by the dependency package (listed in its
[exports]section or declared asmain_pipein a bundle header). - If the pipe is not exported, the reference fails with a visibility error.
Concepts are always public. No visibility check is needed for cross-package concept references.
Visibility Within a Package
When a package has a METHODS.toml manifest:
- Same-domain references — always allowed. A pipe in
legal.contractscan reference any other pipe inlegal.contracts. - Cross-domain references (within the same package) — the target pipe must be exported. A pipe in
scoringreferencinglegal.contracts.extract_clauserequires thatextract_clauseis listed in[exports.legal.contracts]or is themain_pipeof a bundle in that domain. - Bare references — always allowed (they resolve within the same domain).
When no manifest is present (standalone bundle), all pipes are treated as public.
A Concrete Example
Package A depends on Package B with alias scoring_lib.
Package B's manifest (METHODS.toml):
[package]
address = "github.com/mthds/scoring-lib"
version = "0.5.0"
description = "Scoring utilities"
[exports.scoring]
pipes = ["compute_weighted_score"]
Package B's bundle (scoring.mthds):
domain = "scoring"
main_pipe = "compute_weighted_score"
[concept.ScoreResult]
description = "A weighted score result"
[pipe.compute_weighted_score]
type = "PipeLLM"
description = "Compute a weighted score"
inputs = { item = "Text" }
output = "ScoreResult"
prompt = "Compute a weighted score for: $item"
[pipe.internal_helper]
type = "PipeLLM"
description = "Internal helper (not exported)"
inputs = { data = "Text" }
output = "Text"
prompt = "Process: $data"
Package A's bundle (analysis.mthds):
domain = "analysis"
[pipe.analyze_item]
type = "PipeSequence"
description = "Analyze using scoring dependency"
inputs = { item = "Text" }
output = "Text"
steps = [
{ pipe = "scoring_lib->scoring.compute_weighted_score", result = "score" },
{ pipe = "summarize", result = "summary" },
]
Resolution of scoring_lib->scoring.compute_weighted_score:
->detected — split into aliasscoring_liband remainderscoring.compute_weighted_score.- Look up
scoring_libin Package A's[dependencies]— found. - Parse remainder: split on last
.→ domainscoring, pipe codecompute_weighted_score. - Look in domain
scoringof Package B — pipe found. - Visibility check:
compute_weighted_scoreis in[exports.scoring]— accessible. - Resolution succeeds.
If Package A tried scoring_lib->scoring.internal_helper:
Steps 1–4 would succeed (the pipe exists), but the visibility check would fail — internal_helper is not in [exports.scoring] and is not main_pipe. This is a visibility error.
Cross-package concept references work the same way but skip the visibility check, since concepts are always public:
[concept.DetailedScore]
description = "An extended score with additional analysis"
refines = "scoring_lib->scoring.ScoreResult"
Resolution Flowchart
Given a reference string R:
1. Does R contain "->"?
YES → Split into (alias, remainder).
Look up alias in [dependencies].
Parse remainder as domain-qualified or bare ref.
Resolve in the dependency's namespace.
For pipes: check export visibility.
NO → Continue to step 2.
2. Does R contain "."?
YES → Split on last "." into (domain_path, local_code).
Resolve in domain_path within current package.
NO → R is a bare name. Continue to step 3.
3. Is R a concept code (PascalCase)?
YES → Check native concepts → current bundle → same domain.
NO → R is a pipe code (snake_case).
Check current bundle → same domain.
4. Not found? → Error.
See Also
- Specification: Namespace Resolution Rules — the normative, formal definition of all resolution rules.
- Domains — how domains organize concepts and pipes.
- The Package System: Exports & Visibility — how packages control what they expose.