Every Contract carries WorkspaceID and ProjectID slugs along
with RepoPrefix. The matcher (Match) buckets contracts by the
tuple (EffectiveWorkspace, EffectiveProject, ID, Role) before
pairing — providers and consumers in different workspaces or
different projects never pair, no matter how identical their IDs
look.
EffectiveWorkspace/EffectiveProject fall back to RepoPrefix when
the explicit slug is empty. The "missing → repo-name" default
preserves backwards compatibility for callers that haven't started
populating slugs yet — single-repo single-project setups still pair
correctly.
The boundary is what makes gortex contracts check for tuck not
spuriously pair with personal even when both define
POST /api/auth/login.
Explicit shared workspace (cross-repo pairing)
To pair providers and consumers across repositories that are part of
one logical service, declare the same workspace slug in each repo's
.gortex.yaml:
With matching workspace + project, contracts in tuck-api and
tuck-app pair as a CrossRepo: true link. Different project
slugs (e.g. services/api vs services/worker in a monorepo) make
the match drop to orphans by design.
Wrapper inlining
InlineWrappers walks consumer contracts whose path is a single
parameter placeholder (the signature of a request(path, ...)
helper) and re-extracts each caller as its own consumer contract
with the literal path. Inlined contracts inherit the caller's
WorkspaceID/ProjectID — without that, the inlined consumer
would default to its repo's bucket and miss its provider when the
two repos share an explicit workspace.