fragment = "workspace-registry"
[aliases]
registry_source = """
source ~ '**/lang:rs/module:/^(build|command|event|local|mod|ports|runtime|state)$/'
OR source ~ '**/lang:rs/module:/^(build|command|event|local|mod|ports|runtime|state)$/**'
OR source ~ '**/module:registry'
OR source ~ '**/module:registry/**'
OR source ~ '**/dir:registry/**'
"""
registry_local = """
source ~ '**/lang:rs/module:local'
OR source ~ '**/lang:rs/module:local/**'
OR source ~ '**/module:registry/module:local'
OR source ~ '**/module:registry/module:local/**'
OR source ~ '**/dir:registry/module:local'
OR source ~ '**/dir:registry/module:local/**'
"""
consumer_target = """
target ~ '**/external_pkg:code_moniker_cli/**'
OR target ~ '**/external_pkg:ratatui/**'
"""
local_resource_impl_target = "target.name =~ ^(LocalSourceCatalog|LocalSourceCatalogOptions|LocalCodeIndex|LocalCodeIndexOptions|LocalLinkage|LocalChangeOverlay|LocalResourceCache)$"
workspace_ref = """
kind = 'imports_symbol'
OR kind = 'imports_module'
OR kind = 'uses_type'
OR kind = 'calls'
OR kind = 'method_call'
OR kind = 'implements'
"""
[[refs.where]]
id = "registry-is-consumer-independent-port-catalog"
severity = "error"
expr = """
$registry_source
AND ($workspace_ref)
=> NOT $consumer_target
"""
message = "`workspace::registry` is a workspace port catalog; it must not import consumer-facing models."
rationale = """
WorkspaceRegistry is the public catalog of workspace ports. It is consumed by extract, stats,
check, UI, MCP, and manifest, so it must not depend on any consumer representation such as
terminal widgets, LMNAV, or CLI command models.
Topology:
+--------------------+
| WorkspaceRuntime |
| owns resources |
| owns state/jobs |
| publishes versions |
+---------+----------+
|
v
+--------------------+
| WorkspaceRegistry |
| catalog of ports |
+---------+----------+
|
+-------------------------------+-------------------------------+
| | |
v v v
+------------------+ +------------------+ +------------------+
| Command ports | | Query ports | | Event ports |
| trigger work | | read facts | | subscribe |
+--------+---------+ +--------+---------+ +--------+---------+
| | |
v v v
+------------------+ +------------------+ +------------------+
| WorkspaceCommand | | WorkspaceFacts | | WorkspaceEvent |
| scope_uri | | scope_uri | | scope_uri |
| command_id | | generation | | generation |
| kind | | canonical data | | kind |
+------------------+ +------------------+ +------------------+
^ |
| | invalidates / signals
| v
+--------------------+
| Consumer adapters |
| build local reps |
+---------+----------+
|
+-----------------------------+-----------------------------+
| | |
v v v
+------------+ +------------+ +------------+
| extract | | ui | | mcp |
| output rows| | panels/nav | | LMNAV |
+------------+ +------------+ +------------+
v v v
+------------+ +------------+ +------------+
| stats | | check | | manifest |
| reports | | diagnostics| | deps output|
+------------+ +------------+ +------------+
Event contract:
- `WorkspaceCommand` carries `scope_uri`, `command_id`, and command kind.
- `WorkspaceFacts` are read through query ports and carry `scope_uri` plus `generation`.
- `WorkspaceEvent` carries `scope_uri`, `generation`, and event kind.
- Events are signals only. They do not carry changed symbols, references, or consumer view
models. A consumer checks whether the event scope overlaps its own scope, then rereads
canonical facts through the query ports it composes.
"""
[[refs.where]]
id = "registry-does-not-own-runtime-resource-implementations"
severity = "error"
expr = """
$registry_source
AND NOT $registry_local
AND ($workspace_ref)
=> NOT $local_resource_impl_target
"""
message = "`workspace::registry` runtime code depends on ports; local implementation assembly stays in `registry::local`."
rationale = """
The registry is not a replacement god object. It names the ports that consumers compose; the
runtime owns scheduling and snapshot publication, while filesystem/source discovery,
extraction, code indexing, linkage, changes, and cache behavior stay behind their ports.
Only `registry::local` may assemble local implementations. If runtime/build code imports
`Local*` implementations directly, the catalog collapses back into a wired runtime bundle.
"""