Finds
Things I found building quicue.ca — a CUE framework where everything is a projection of one typed dependency graph.
It's one value
Every resource declares what it is (@type) and what it needs (depends_on). Both are struct-as-set:
"dns-internal": {
"@type": {LXCContainer: true, DNSServer: true, CriticalInfra: true}
depends_on: {"pve-node1": true}
host: "pve-node1"
container_id: 100
}
{Key: true} as a set works because CUE merges structs. No duplicates, O(1) membership, composition is unification.
From 30 resources and two fields, cue export produces 72+ projections: deployment plans, rollback sequences, blast radius, 654 resolved CLI commands, Jupyter notebooks, Rundeck jobs, a wiki, JSON-LD, Hydra, DCAT, N-Triples, SHACL shapes, ODRL policies, D3 data, DOT, Mermaid. One evaluation, no pipeline.
Type overlap as dispatch
Standard tools — Docker, Proxmox, Kubernetes, Ansible, Vault, ArgoCD — all expose typed operations on resources. Good CLI specs, uniform shape. The binding logic is one comprehension:
// patterns/bind.cue
let _matched = [
for tname, _ in provider.types
if resource["@type"][tname] != _|_ {tname},
]
if len(_matched) > 0 {
(pname): (#BindActions & {
"registry": provider.registry
"resource": resource
}).actions
}
A provider declares types: {LXCContainer: true}. A resource declares "@type": {LXCContainer: true, DNSServer: true}. Binding is resource["@type"][tname] != _|_.
That DNS server matches Proxmox (serves LXCContainer) and PowerDNS (serves DNSServer) simultaneously. No registration, no interface declaration.
Provider swapping is a type-set change. Replace LXCContainer with DockerContainer and Docker binds instead of Proxmox — the set intersection changed, so the dispatch changed. This is why 33 providers work without 33 special cases.
Transitive closure from unification
"What are ALL the ancestors of this resource?" In a procedural language, that's BFS. In CUE:
// patterns/graph.cue
_ancestors: {
[_]: true
if _hasDeps {
for d, _ in _deps {
(d): true
resources[d]._ancestors
}
}
}
Six lines. Declares a struct shape, adds direct parents, unifies with each parent's ancestors. CUE resolves the fixpoint — the struct expands until merging produces no new keys, then stops.
I wrote "include your parents' ancestors" and CUE figured out the termination. The code credits the "rogpeppe pattern." Whether this was designed for or emergent, it lets you write graph algorithms as value declarations.
Every query is already computed
Once _ancestors exists, impact analysis is one comprehension:
// patterns/graph.cue
affected: {
for rname, r in Graph.resources
if r._ancestors[Target] != _|_ {(rname): true}
}
"Which resources have Target in their ancestor set?" That's the entire implementation of "what breaks if this goes down."
Blast radius wraps it and adds rollback ordering. Criticality ranking counts downstream dependents. SPOF detection finds nodes whose failure cascades widest. Each is a comprehension over the same _ancestors.
There is no query planner, no index, no runtime. cue export produces every answer at eval time.
Consequence: if every answer is known at build time, the API is a file server. The project serves 654 pre-computed JSON files from a CDN. No server, no database. CUE comprehensions enumerate all possible queries, so the static API is just those answers as files.
Constraints are values
Instead of assertions that check output, I write CUE values that must unify with the output:
// examples/devbox/verify.cue
package devbox
validate: valid: true
infra: roots: {"docker": true}
deployment: layers: [{layer: 0, resources: ["docker"]}, ...]
impact_docker: affected: {
for name, _ in _resources if name != "docker" {
"\(name)": true
}
}
Same package as the computation. If the graph produces validate: valid: false, unification with true is bottom. cue vet fails. No assertion framework — the language is one.
The charter module generalizes this: declare what "done" looks like (required resources, gates, type coverage), and #GapAnalysis computes the delta. The gap is the remaining work. The backlog is a CUE value.
The W3C stack is more projections
The same graph produces a full semantic web pipeline. Each W3C format is one more CUE definition over the same resources:
| Format | What it produces | W3C spec |
|---|---|---|
| JSON-LD | @graph with typed IRIs, dependsOn links, @context |
JSON-LD 1.1 |
| Hydra | Role-scoped API docs: supportedOperation from bound actions |
Hydra Core |
| DCAT 3 | dcat:Catalog with dcat:Dataset per resource |
DCAT 3 |
| N-Triples | One triple per line — rdf:type, dependsOn edges |
RDF 1.1 |
| SHACL | Node shapes from the type registry — validates RDF data | SHACL |
| ODRL | Machine-readable access policies per resource | ODRL 2.2 |
| ActivityStreams | Change feeds — deploy→as:Create, shutdown→as:Delete |
AS 2.0 |
No converters, no export pipelines. Each takes #InfraGraph, produces the target vocabulary's JSON-LD shape. They compose because they share input. They're correct because CUE validates structure at eval time.
Inside CUE, comprehensions are the query layer. Outside CUE — when the data joins external systems — SPARQL and triplestores add value. The N-Triples and JSON-LD exports are the bridge.
Package scoping as a knowledge base
CUE packages are directory-scoped. We use this for a multi-graph knowledge base:
.kb/
├── manifest.cue # Topology via #KnowledgeBase
├── decisions/ # PROV-O
├── insights/ # Web Annotation
├── patterns/ # SKOS
└── rejected/ # PROV-O
Each subdirectory is an independent CUE package. A schema violation in decisions/ can't poison patterns/. The directory structure is the ontology. The root manifest declares which graphs exist and what W3C vocabulary each maps to.
We didn't build a knowledge base framework. We organized files into directories and let CUE's module system handle the isolation.
It works across domains
Same #InfraGraph, same #ImpactQuery, same #Charter — four domains:
| Domain | Graph | Shape |
|---|---|---|
| IT infrastructure | 30 resources, 33 providers, 654 commands | Service topology |
| Construction PM | 18 CMHC deep retrofit work packages | Project delivery |
| Energy efficiency | 17-service Greener Homes platform | Platform topology |
| Real estate | Transaction pipeline, compliance tracker | Workflow graph |
A resource is a typed node with dependencies. Whether it's a Linux container or a construction work package doesn't matter — the patterns compute the same things: depth, ancestors, impact, deployment order, critical path.
The PM sees schedule phases. The platform engineer sees deployment layers. Same code, same cue export.
github.com/quicue/quicue.ca | demo | static API | docs | kg spec