Cross-Namespace Resolution: stratt:// & choco://
grace intermediate 6 min read
ELI5
Two postal services share routing. STRATT delivers in town (units). Choco delivers next door (docs and API specs). A central post office (NamespaceRegistry) reads the prefix on every parcel and hands it to the right courier. A missing courier or a missing parcel both look the same to the sender: FM-02.
Technical Deep Dive
Source: architecture/CROSS-NAMESPACE-MAP.md, config/namespaces.yaml, packages/graph/src/{namespace,choco-resolver,resolve,dag}.ts.
Registered Schemes
| Scheme | Trust | Paths | Resolution |
|---|---|---|---|
stratt:// | implicit | 11 domains | Local UnitRegistry |
choco:// | trusted (declared) | docs, api | ChocoBridgeResolver |
Import Permission Matrix
| Importer (stratt://) | choco://docs/* | choco://api/* |
|---|---|---|
task | yes | yes |
chain | yes | no |
supply | yes | no |
role | no | no |
rule | no | no |
Resolver Modes
| Mode | Trigger | Source |
|---|---|---|
| filesystem (current) | CHOCO_RESOLVE_MODE=filesystem + CHOCO_LOCAL_PATH | Local Choco repo |
| HTTP (future) | CHOCO_RESOLVE_MODE=http + CHOCO_API_ENDPOINT | GET /resolve?uri={uri} |
Resolution Sequence
sequenceDiagram autonumber participant Unit as Importer Unit participant CI as stratt ci participant Reg as NamespaceRegistry participant Local as UnitRegistry participant Choco as ChocoBridgeResolver Unit->>CI: imports: [stratt://..., choco://...] loop each import URI CI->>Reg: lookup(scheme) alt scheme = stratt Reg->>Local: resolve(uri) Local-->>Reg: ResolvedUnit | null else scheme = choco Reg->>Choco: resolve(uri) alt mode = filesystem Choco->>Choco: read CHOCO_LOCAL_PATH else mode = http Choco->>Choco: GET CHOCO_API_ENDPOINT/resolve end Choco-->>Reg: ResolvedUnit | null end Reg-->>CI: result alt result == null CI-->>Unit: FM-02 broken import (blocking) else result.trusted == false CI-->>Unit: warning (non-blocking) else CI->>CI: insert synthetic node into DAG end endDAG Implications
flowchart LR A["stratt://dev/chain/sol-1-boot@0.1.0"] -->|imports| B["stratt://dev/task/intake-parse@0.1.0"] A -->|imports| C["choco://docs/api/users@1.0.0"] C -->|synthetic node| D["ResolvedUnit trusted=true"] B -->|imports| E["stratt://shared/supply/style-guide@0.1.0"] style C fill:#fef3c7,stroke:#f59e0b style D fill:#fef3c7,stroke:#f59e0bCross-namespace blast radius includes foreign dependents: deprecating stratt://shared/supply/style-guide notifies any choco:// page that imported it.
Key Terms
NamespaceRegistry→packages/graph/src/namespace.ts; matches scheme to resolver instance.BridgeResolver→ Interface intypes.ts;resolve(uri) → ResolvedUnit | null.ResolvedUnit.trusted→ False until the foreign fingerprint has been independently verified.
Q&A
Q: Why are role and rule forbidden from importing choco://?
A: Roles and rules are pure governance primitives — they should be self-contained and not depend on documentation that can drift. Allowing it would couple identity/policy to external content.
Q: What does a null return from the resolver trigger? A: FM-02. The CI pipeline blocks the build until the import is fixable.
Q: Is HTTP-mode resolution deployed today?
A: No. CHOCO_API_ENDPOINT is reserved; the active path is filesystem mode against ~/code/workspace/choco-hq/.
Examples
A dev/task/api-codegen task imports choco://api/rest/auth@2.0.0. Resolution: NamespaceRegistry → ChocoBridgeResolver → reads ${CHOCO_LOCAL_PATH}/api/rest/auth/2.0.0.yaml. Returned ResolvedUnit is inserted as a synthetic DAG node, contributing to the task’s blast radius and import-resolution check during stratt ci.
neighbors on the map
- Layer Architecture L0–L6 deciding which package a new feature belongs in
- Nine Failure Modes (FM-01..FM-09) interpreting a `stratt ci` failure
- strat:// URI Scheme writing a unit import statement