dizzy.engine.registry¶
dizzy.engine.registry
¶
The feat-driven app graph — what an engine shell needs to know, read.
DIZZY's thesis is that the design lives in the artifact: <name>.feat.yaml
declares the whole topology (commands, events, procedures, projections,
policies, queries, environment, telemetry). Everything a scheduling shell
needs about an app is therefore derivable — a shell should never hard-code a
command name, an event name, or an environment field.
FeatGraph is that derivation. Given a feat path (found by env var or an
upward search) it resolves every declared name to its generated pydantic class
by DIZZY's own naming convention (classify_image → ClassifyImage in
gen_def.pydantic.commands), and fails loudly when the feat declares
something the generated packages don't provide — a stale-generation check a
hand-maintained command dict cannot make, since a missing entry there is
indistinguishable from a command nobody dispatches.
Resolution is LAZY per section: a producer-only process (enqueue without
building the library) resolves commands and never imports the events
module; a worker resolves both. environment/telemetry need no import
at all — their names alone are the answer.
Costs pyyaml and nothing else. That is deliberate: a worker process installs
DIZZY to get a scheduling shell, and the generator's tree (linkml, openai,
typer) lives behind the gen extra so it never rides along.
FeatGraph
¶
An app's declared topology, with its generated classes resolved.
Construct with :meth:load. Cheap to hold; every resolution is cached.
Source code in dizzy/src/dizzy/engine/registry.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | |
environment
property
¶
Environment field names — what a shell must re-hydrate per command.
Derived, so adding an env shape to the feat needs no shell change.
telemetry
property
¶
Telemetry sink names — the ports a shell may re-route as transport.
commands
cached
property
¶
Command name -> generated pydantic class.
events
cached
property
¶
Event name -> generated pydantic class.
names(section)
¶
The names the feat declares in section, in feat order.
Source code in dizzy/src/dizzy/engine/registry.py
207 208 209 | |
entry(section, name)
¶
One declaration, normalized to a dict.
A bare string is a description-only entry (how the feat spells most commands); a NULL value is a declared-but-unwritten entry, which is normal while drafting — it is present, just empty.
Source code in dizzy/src/dizzy/engine/registry.py
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | |
command_name(command)
¶
The feat name of a command INSTANCE (or class).
Source code in dizzy/src/dizzy/engine/registry.py
283 284 285 286 | |
validate_registered(registered)
¶
Assert an app's registered elements are exactly what the feat declares.
registered maps a topology section to the names the app actually
wired. Replaces the hand-maintained _REGISTERED literal: the feat
side is read, so only the app's own wiring must be reported.
Source code in dizzy/src/dizzy/engine/registry.py
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | |
camel_case(name)
¶
classify_image -> ClassifyImage.
LinkML's camelcase semantics (that generator produced the classes, so
this must match it, not merely resemble it): split on non-word runs and
underscores, upper the first character of each part, keep the rest.
Source code in dizzy/src/dizzy/engine/registry.py
63 64 65 66 67 68 69 70 | |
snake_case(name)
¶
ClassifyImage -> classify_image — the inverse of camel_case.
Source code in dizzy/src/dizzy/engine/registry.py
73 74 75 | |
check_name(name, section, feat_name)
¶
Reject a declared name that does not survive the round trip.
camel_case splits on any non-word run, so classify-image,
classifyImage and classify_image all collapse to ClassifyImage.
Left unchecked, a typo'd feat entry resolves to its NEIGHBOUR's class and
the reverse lookup (which routes commands) silently maps it back to the
wrong name — the stale-generation check would pass on a broken feat. A
name is only well formed if snake_case(camel_case(name)) == name.
Also catches YAML's scalar keys: 123: or on: parse to int/bool and
would otherwise die inside re with no mention of the feat file.
Source code in dizzy/src/dizzy/engine/registry.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
find_feat(start=None)
¶
Locate the app's feat file.
$DIZZY_FEAT_PATH wins. Otherwise walk up from start (default: the
working directory) looking for exactly one *.feat.yaml. This is how a
worker boots knowing only where it is — no app import required.
Source code in dizzy/src/dizzy/engine/registry.py
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | |
graph(feat_path=None, def_package=DEFAULT_DEF_PACKAGE)
¶
Process-wide FeatGraph cache — a worker parses its feat once.
Keyed on the RESOLVED path, not on nothing: an earlier version cached a
single graph, so once any caller had built one, a later $DIZZY_FEAT_PATH
(or a different cwd, since discovery walks up) silently handed back the
first caller's feat. Re-resolving per call is two env reads; parsing is
what the cache is for.
Source code in dizzy/src/dizzy/engine/registry.py
321 322 323 324 325 326 327 328 329 330 331 332 333 334 | |
reset_graph()
¶
Drop the cache — for tests that rewrite a feat file in place.
Source code in dizzy/src/dizzy/engine/registry.py
337 338 339 | |