glitchlings 0.2.5__cp312-cp312-win_amd64.whl → 0.9.3__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. glitchlings/__init__.py +36 -17
  2. glitchlings/__main__.py +0 -1
  3. glitchlings/_zoo_rust/__init__.py +12 -0
  4. glitchlings/_zoo_rust.cp312-win_amd64.pyd +0 -0
  5. glitchlings/assets/__init__.py +180 -0
  6. glitchlings/assets/apostrofae_pairs.json +32 -0
  7. glitchlings/assets/ekkokin_homophones.json +2014 -0
  8. glitchlings/assets/hokey_assets.json +193 -0
  9. glitchlings/assets/lexemes/academic.json +1049 -0
  10. glitchlings/assets/lexemes/colors.json +1333 -0
  11. glitchlings/assets/lexemes/corporate.json +716 -0
  12. glitchlings/assets/lexemes/cyberpunk.json +22 -0
  13. glitchlings/assets/lexemes/lovecraftian.json +23 -0
  14. glitchlings/assets/lexemes/synonyms.json +3354 -0
  15. glitchlings/assets/mim1c_homoglyphs.json.gz.b64 +1064 -0
  16. glitchlings/assets/pipeline_assets.json +29 -0
  17. glitchlings/attack/__init__.py +53 -0
  18. glitchlings/attack/compose.py +299 -0
  19. glitchlings/attack/core.py +465 -0
  20. glitchlings/attack/encode.py +114 -0
  21. glitchlings/attack/metrics.py +104 -0
  22. glitchlings/attack/metrics_dispatch.py +70 -0
  23. glitchlings/attack/tokenization.py +157 -0
  24. glitchlings/auggie.py +283 -0
  25. glitchlings/compat/__init__.py +9 -0
  26. glitchlings/compat/loaders.py +355 -0
  27. glitchlings/compat/types.py +41 -0
  28. glitchlings/conf/__init__.py +41 -0
  29. glitchlings/conf/loaders.py +331 -0
  30. glitchlings/conf/schema.py +156 -0
  31. glitchlings/conf/types.py +72 -0
  32. glitchlings/config.toml +2 -0
  33. glitchlings/constants.py +59 -0
  34. glitchlings/dev/__init__.py +3 -0
  35. glitchlings/dev/docs.py +45 -0
  36. glitchlings/dlc/__init__.py +17 -3
  37. glitchlings/dlc/_shared.py +296 -0
  38. glitchlings/dlc/gutenberg.py +400 -0
  39. glitchlings/dlc/huggingface.py +37 -65
  40. glitchlings/dlc/prime.py +55 -114
  41. glitchlings/dlc/pytorch.py +98 -0
  42. glitchlings/dlc/pytorch_lightning.py +173 -0
  43. glitchlings/internal/__init__.py +16 -0
  44. glitchlings/internal/rust.py +159 -0
  45. glitchlings/internal/rust_ffi.py +432 -0
  46. glitchlings/main.py +123 -32
  47. glitchlings/runtime_config.py +24 -0
  48. glitchlings/util/__init__.py +29 -176
  49. glitchlings/util/adapters.py +65 -0
  50. glitchlings/util/keyboards.py +311 -0
  51. glitchlings/util/transcripts.py +108 -0
  52. glitchlings/zoo/__init__.py +47 -24
  53. glitchlings/zoo/assets/__init__.py +29 -0
  54. glitchlings/zoo/core.py +301 -167
  55. glitchlings/zoo/core_execution.py +98 -0
  56. glitchlings/zoo/core_planning.py +451 -0
  57. glitchlings/zoo/corrupt_dispatch.py +295 -0
  58. glitchlings/zoo/ekkokin.py +118 -0
  59. glitchlings/zoo/hokey.py +137 -0
  60. glitchlings/zoo/jargoyle.py +179 -274
  61. glitchlings/zoo/mim1c.py +106 -68
  62. glitchlings/zoo/pedant/__init__.py +107 -0
  63. glitchlings/zoo/pedant/core.py +105 -0
  64. glitchlings/zoo/pedant/forms.py +74 -0
  65. glitchlings/zoo/pedant/stones.py +74 -0
  66. glitchlings/zoo/redactyl.py +44 -175
  67. glitchlings/zoo/rng.py +259 -0
  68. glitchlings/zoo/rushmore.py +359 -116
  69. glitchlings/zoo/scannequin.py +18 -125
  70. glitchlings/zoo/transforms.py +386 -0
  71. glitchlings/zoo/typogre.py +76 -162
  72. glitchlings/zoo/validation.py +477 -0
  73. glitchlings/zoo/zeedub.py +33 -86
  74. glitchlings-0.9.3.dist-info/METADATA +334 -0
  75. glitchlings-0.9.3.dist-info/RECORD +80 -0
  76. {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/entry_points.txt +1 -0
  77. glitchlings/zoo/_ocr_confusions.py +0 -34
  78. glitchlings/zoo/_rate.py +0 -21
  79. glitchlings/zoo/reduple.py +0 -169
  80. glitchlings-0.2.5.dist-info/METADATA +0 -490
  81. glitchlings-0.2.5.dist-info/RECORD +0 -27
  82. /glitchlings/{zoo → assets}/ocr_confusions.tsv +0 -0
  83. {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/WHEEL +0 -0
  84. {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/licenses/LICENSE +0 -0
  85. {glitchlings-0.2.5.dist-info → glitchlings-0.9.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,98 @@
1
+ """Impure execution dispatch for Gaggle orchestration.
2
+
3
+ This module handles the actual execution of glitchling plans, including
4
+ Rust FFI calls and Python fallback execution. It is the impure counterpart
5
+ to core_planning.py.
6
+
7
+ **Design Philosophy:**
8
+
9
+ This module is explicitly *impure* - it invokes compiled Rust functions
10
+ and executes Python corruption functions with side effects. All Rust
11
+ dispatch for Gaggle orchestration flows through this module.
12
+
13
+ The separation allows:
14
+ - Pure planning logic to be tested without Rust
15
+ - Clear boundaries between plan construction and execution
16
+ - Mocking execution for integration tests
17
+
18
+ See AGENTS.md "Functional Purity Architecture" for full details.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from typing import TYPE_CHECKING, cast
24
+
25
+ from glitchlings.internal.rust_ffi import compose_glitchlings_rust
26
+
27
+ if TYPE_CHECKING:
28
+ from .core_planning import ExecutionPlan, PipelineDescriptor
29
+
30
+
31
+ # ---------------------------------------------------------------------------
32
+ # Plan Execution
33
+ # ---------------------------------------------------------------------------
34
+
35
+
36
+ def execute_plan(
37
+ text: str,
38
+ plan: ExecutionPlan,
39
+ master_seed: int,
40
+ ) -> str:
41
+ """Execute an orchestration plan against input text.
42
+
43
+ This function dispatches plan steps to either the Rust pipeline or
44
+ Python fallback execution as appropriate.
45
+
46
+ Args:
47
+ text: Input text to transform.
48
+ plan: Execution plan from build_execution_plan().
49
+ master_seed: Master seed for Rust pipeline.
50
+
51
+ Returns:
52
+ Transformed text after all plan steps complete.
53
+ """
54
+ # Fast path: all glitchlings support pipeline
55
+ if plan.all_pipeline and plan.step_count == 1:
56
+ descriptors = list(plan.steps[0].descriptors)
57
+ return compose_glitchlings_rust(text, descriptors, master_seed)
58
+
59
+ # Hybrid path: mix of pipeline batches and individual fallbacks
60
+ result = text
61
+
62
+ for step in plan.steps:
63
+ if step.is_pipeline_step:
64
+ # Execute the batch through the Rust pipeline
65
+ descriptors = list(step.descriptors)
66
+ result = compose_glitchlings_rust(result, descriptors, master_seed)
67
+ elif step.fallback_glitchling is not None:
68
+ # Execute single glitchling via Python fallback
69
+ result = cast(str, step.fallback_glitchling.corrupt(result))
70
+
71
+ return result
72
+
73
+
74
+ def execute_descriptors(
75
+ text: str,
76
+ descriptors: list[PipelineDescriptor],
77
+ master_seed: int,
78
+ ) -> str:
79
+ """Execute a list of pipeline descriptors through Rust.
80
+
81
+ This is a thin wrapper over compose_glitchlings_rust for cases
82
+ where the caller has already constructed descriptors directly.
83
+
84
+ Args:
85
+ text: Input text to transform.
86
+ descriptors: Pipeline descriptors for each glitchling.
87
+ master_seed: Master seed for Rust pipeline.
88
+
89
+ Returns:
90
+ Transformed text.
91
+ """
92
+ return compose_glitchlings_rust(text, descriptors, master_seed)
93
+
94
+
95
+ __all__ = [
96
+ "execute_plan",
97
+ "execute_descriptors",
98
+ ]
@@ -0,0 +1,451 @@
1
+ """Pure orchestration planning functions.
2
+
3
+ This module contains the deterministic, side-effect-free logic for building
4
+ glitchling execution plans. It converts glitchling metadata into structured
5
+ plans that can be executed by the impure dispatch layer.
6
+
7
+ **Design Philosophy:**
8
+
9
+ All functions in this module are *pure* - they perform plan construction
10
+ based solely on their inputs, without side effects. They do not:
11
+ - Import or invoke Rust FFI
12
+ - Read configuration files
13
+ - Create RNG instances
14
+ - Perform I/O of any kind
15
+
16
+ The separation allows:
17
+ - Plan verification without Rust dependencies
18
+ - Unit testing of orchestration logic in isolation
19
+ - Clear boundaries between planning and execution
20
+
21
+ See AGENTS.md "Functional Purity Architecture" for full details.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from collections.abc import Mapping, Sequence
27
+ from dataclasses import dataclass
28
+ from typing import Any, Protocol, TypedDict, Union, cast, runtime_checkable
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Type Definitions
32
+ # ---------------------------------------------------------------------------
33
+
34
+
35
+ class PlanSpecification(TypedDict):
36
+ """Raw mapping describing glitchling orchestration metadata."""
37
+
38
+ name: str
39
+ scope: int
40
+ order: int
41
+
42
+
43
+ class PipelineOperationPayload(TypedDict, total=False):
44
+ """Typed mapping describing a Rust pipeline operation."""
45
+
46
+ type: str
47
+
48
+
49
+ class PipelineDescriptor(TypedDict):
50
+ """Typed mapping representing a glitchling's Rust pipeline descriptor."""
51
+
52
+ name: str
53
+ operation: PipelineOperationPayload
54
+ seed: int
55
+
56
+
57
+ PlanEntry = Union["GlitchlingProtocol", Mapping[str, Any]]
58
+
59
+
60
+ @runtime_checkable
61
+ class GlitchlingProtocol(Protocol):
62
+ """Protocol describing the glitchling attributes needed for planning."""
63
+
64
+ name: str
65
+ level: Any # AttackWave enum
66
+ order: Any # AttackOrder enum
67
+ seed: int | None
68
+
69
+ def pipeline_operation(self) -> PipelineOperationPayload | None:
70
+ """Return the Rust pipeline descriptor or None."""
71
+ ...
72
+
73
+ def corrupt(self, text: Any) -> Any:
74
+ """Apply corruption to text (may handle str or Transcript)."""
75
+ ...
76
+
77
+
78
+ # ---------------------------------------------------------------------------
79
+ # Plan Specification Normalization
80
+ # ---------------------------------------------------------------------------
81
+
82
+
83
+ @dataclass(slots=True)
84
+ class NormalizedPlanSpec:
85
+ """Concrete representation of orchestration metadata consumed by Rust.
86
+
87
+ This dataclass normalizes glitchling metadata into a form suitable for
88
+ the Rust orchestration planner. It can be constructed from either a
89
+ Glitchling instance or a raw mapping specification.
90
+ """
91
+
92
+ name: str
93
+ scope: int
94
+ order: int
95
+
96
+ @classmethod
97
+ def from_glitchling(cls, glitchling: GlitchlingProtocol) -> NormalizedPlanSpec:
98
+ """Create a plan spec from a Glitchling instance.
99
+
100
+ Args:
101
+ glitchling: A glitchling with name, level, and order attributes.
102
+
103
+ Returns:
104
+ Normalized plan specification.
105
+ """
106
+ return cls(glitchling.name, int(glitchling.level), int(glitchling.order))
107
+
108
+ @classmethod
109
+ def from_mapping(cls, mapping: Mapping[str, Any]) -> NormalizedPlanSpec:
110
+ """Create a plan spec from a raw mapping.
111
+
112
+ Args:
113
+ mapping: Dictionary with 'name', 'scope', and 'order' keys.
114
+
115
+ Returns:
116
+ Normalized plan specification.
117
+
118
+ Raises:
119
+ ValueError: If required fields are missing or invalid.
120
+ """
121
+ try:
122
+ name = str(mapping["name"])
123
+ scope_value = int(mapping["scope"])
124
+ order_value = int(mapping["order"])
125
+ except KeyError as exc:
126
+ raise ValueError(f"Plan specification missing required field: {exc.args[0]}") from exc
127
+ except (TypeError, ValueError) as exc:
128
+ raise ValueError("Plan specification fields must be coercible to integers") from exc
129
+
130
+ return cls(name, scope_value, order_value)
131
+
132
+ @classmethod
133
+ def from_entry(cls, entry: PlanEntry) -> NormalizedPlanSpec:
134
+ """Create a plan spec from either a Glitchling or mapping.
135
+
136
+ Args:
137
+ entry: A Glitchling instance or raw specification mapping.
138
+
139
+ Returns:
140
+ Normalized plan specification.
141
+
142
+ Raises:
143
+ TypeError: If entry is neither a Glitchling nor a mapping.
144
+ """
145
+ if isinstance(entry, GlitchlingProtocol):
146
+ return cls.from_glitchling(entry)
147
+ if not isinstance(entry, Mapping):
148
+ message = "plan_glitchlings expects Glitchling instances or mapping specifications"
149
+ raise TypeError(message)
150
+ return cls.from_mapping(entry)
151
+
152
+ def as_mapping(self) -> PlanSpecification:
153
+ """Convert to a raw mapping for Rust consumption.
154
+
155
+ Returns:
156
+ Dictionary with name, scope, and order keys.
157
+ """
158
+ return {"name": self.name, "scope": self.scope, "order": self.order}
159
+
160
+
161
+ def normalize_plan_entries(entries: Sequence[PlanEntry]) -> list[NormalizedPlanSpec]:
162
+ """Normalize a collection of orchestration plan entries.
163
+
164
+ Args:
165
+ entries: Sequence of Glitchling instances or raw specifications.
166
+
167
+ Returns:
168
+ List of normalized plan specifications.
169
+ """
170
+ return [NormalizedPlanSpec.from_entry(entry) for entry in entries]
171
+
172
+
173
+ def normalize_plan_specs(specs: Sequence[Mapping[str, Any]]) -> list[NormalizedPlanSpec]:
174
+ """Normalize raw plan specification mappings.
175
+
176
+ Args:
177
+ specs: Sequence of raw specification mappings.
178
+
179
+ Returns:
180
+ List of normalized plan specifications.
181
+ """
182
+ return [NormalizedPlanSpec.from_mapping(spec) for spec in specs]
183
+
184
+
185
+ # ---------------------------------------------------------------------------
186
+ # Pipeline Descriptor Construction
187
+ # ---------------------------------------------------------------------------
188
+
189
+
190
+ @dataclass(slots=True)
191
+ class PipelineDescriptorModel:
192
+ """In-memory representation of a glitchling pipeline descriptor.
193
+
194
+ This model captures the data needed to invoke a glitchling through
195
+ the Rust pipeline: its name, computed seed, and operation payload.
196
+ """
197
+
198
+ name: str
199
+ seed: int
200
+ operation: PipelineOperationPayload
201
+
202
+ def as_mapping(self) -> PipelineDescriptor:
203
+ """Convert to a dictionary for Rust consumption.
204
+
205
+ Returns:
206
+ Dictionary with name, operation, and seed keys.
207
+ """
208
+ return {"name": self.name, "operation": self.operation, "seed": self.seed}
209
+
210
+
211
+ def build_pipeline_descriptor(
212
+ glitchling: GlitchlingProtocol,
213
+ *,
214
+ master_seed: int | None,
215
+ derive_seed_fn: Any, # Callable[[int, str, int], int]
216
+ ) -> PipelineDescriptorModel | None:
217
+ """Materialise the Rust pipeline descriptor for a glitchling when available.
218
+
219
+ This is a pure function that constructs the descriptor data without
220
+ invoking Rust. The actual Rust dispatch happens in core_execution.
221
+
222
+ Args:
223
+ glitchling: The glitchling to build a descriptor for.
224
+ master_seed: Master seed for the enclosing Gaggle.
225
+ derive_seed_fn: Function to derive child seeds from master seed.
226
+ Signature: (master_seed: int, name: str, index: int) -> int
227
+
228
+ Returns:
229
+ PipelineDescriptorModel if the glitchling supports pipeline execution,
230
+ None otherwise.
231
+
232
+ Raises:
233
+ RuntimeError: If seed cannot be determined for a pipeline-enabled glitchling.
234
+ """
235
+ operation = glitchling.pipeline_operation()
236
+ if operation is None:
237
+ return None
238
+
239
+ if not isinstance(operation, Mapping):
240
+ raise TypeError("Pipeline operations must be mappings or None")
241
+
242
+ operation_payload = dict(operation)
243
+ operation_type = operation_payload.get("type")
244
+ if not isinstance(operation_type, str):
245
+ message = f"Pipeline operation for {glitchling.name} is missing a string 'type'"
246
+ raise RuntimeError(message)
247
+
248
+ seed = glitchling.seed
249
+ if seed is None:
250
+ index = getattr(glitchling, "_gaggle_index", None)
251
+ if index is None or master_seed is None:
252
+ raise RuntimeError(
253
+ "Glitchling %s is missing deterministic seed configuration" % glitchling.name
254
+ )
255
+ seed = derive_seed_fn(master_seed, glitchling.name, index)
256
+
257
+ payload = cast(PipelineOperationPayload, operation_payload)
258
+ return PipelineDescriptorModel(glitchling.name, int(seed), payload)
259
+
260
+
261
+ # ---------------------------------------------------------------------------
262
+ # Execution Plan Construction
263
+ # ---------------------------------------------------------------------------
264
+
265
+
266
+ @dataclass(slots=True, frozen=True)
267
+ class ExecutionStep:
268
+ """A single step in the execution plan.
269
+
270
+ Represents either a batch of pipeline descriptors (for Rust execution)
271
+ or a single glitchling for fallback Python execution.
272
+
273
+ Attributes:
274
+ descriptors: List of pipeline descriptors for batch Rust execution.
275
+ Empty when this step is a fallback.
276
+ fallback_glitchling: Glitchling to execute via Python when
277
+ pipeline execution is not available. None when using pipeline.
278
+ """
279
+
280
+ descriptors: tuple[PipelineDescriptor, ...]
281
+ fallback_glitchling: GlitchlingProtocol | None
282
+
283
+ @property
284
+ def is_pipeline_step(self) -> bool:
285
+ """Return True if this step uses the Rust pipeline."""
286
+ return len(self.descriptors) > 0
287
+
288
+ @property
289
+ def is_fallback_step(self) -> bool:
290
+ """Return True if this step uses Python fallback."""
291
+ return self.fallback_glitchling is not None
292
+
293
+
294
+ @dataclass(slots=True, frozen=True)
295
+ class ExecutionPlan:
296
+ """Complete execution plan for a Gaggle's text corruption.
297
+
298
+ The plan consists of ordered steps that can be either:
299
+ - Pipeline batches: Multiple glitchlings executed together via Rust
300
+ - Fallback steps: Single glitchlings executed via Python
301
+
302
+ Consecutive pipeline-enabled glitchlings are batched together to
303
+ minimize tokenization overhead.
304
+
305
+ Attributes:
306
+ steps: Ordered sequence of execution steps.
307
+ all_pipeline: True if all glitchlings support pipeline execution.
308
+ """
309
+
310
+ steps: tuple[ExecutionStep, ...]
311
+ all_pipeline: bool
312
+
313
+ @property
314
+ def step_count(self) -> int:
315
+ """Return the number of execution steps."""
316
+ return len(self.steps)
317
+
318
+ @property
319
+ def pipeline_step_count(self) -> int:
320
+ """Return the number of pipeline batch steps."""
321
+ return sum(1 for step in self.steps if step.is_pipeline_step)
322
+
323
+ @property
324
+ def fallback_step_count(self) -> int:
325
+ """Return the number of fallback steps."""
326
+ return sum(1 for step in self.steps if step.is_fallback_step)
327
+
328
+
329
+ def build_execution_plan(
330
+ apply_order: Sequence[GlitchlingProtocol],
331
+ *,
332
+ master_seed: int | None,
333
+ derive_seed_fn: Any, # Callable[[int, str, int], int]
334
+ ) -> ExecutionPlan:
335
+ """Build an execution plan that batches consecutive pipeline-supported glitchlings.
336
+
337
+ This is a pure function that analyzes glitchlings and constructs an
338
+ optimal execution plan. The plan batches consecutive pipeline-enabled
339
+ glitchlings to reduce tokenization overhead, while isolating fallback
340
+ glitchlings that require Python execution.
341
+
342
+ Args:
343
+ apply_order: Ordered sequence of glitchlings to execute.
344
+ master_seed: Master seed for seed derivation.
345
+ derive_seed_fn: Function to derive child seeds.
346
+
347
+ Returns:
348
+ ExecutionPlan containing ordered execution steps.
349
+
350
+ Example:
351
+ If glitchlings A, B (pipeline), C (fallback), D, E (pipeline):
352
+ Plan: [(A, B descriptors), (C fallback), (D, E descriptors)]
353
+ """
354
+ steps: list[ExecutionStep] = []
355
+ current_batch: list[PipelineDescriptor] = []
356
+
357
+ for glitchling in apply_order:
358
+ descriptor = build_pipeline_descriptor(
359
+ glitchling,
360
+ master_seed=master_seed,
361
+ derive_seed_fn=derive_seed_fn,
362
+ )
363
+ if descriptor is not None:
364
+ current_batch.append(descriptor.as_mapping())
365
+ else:
366
+ # Flush any accumulated batch before the fallback item
367
+ if current_batch:
368
+ steps.append(ExecutionStep(tuple(current_batch), None))
369
+ current_batch = []
370
+ # Add the fallback step
371
+ steps.append(ExecutionStep((), glitchling))
372
+
373
+ # Flush any remaining batch
374
+ if current_batch:
375
+ steps.append(ExecutionStep(tuple(current_batch), None))
376
+
377
+ all_pipeline = len(steps) == 1 and steps[0].fallback_glitchling is None if steps else True
378
+
379
+ return ExecutionPlan(tuple(steps), all_pipeline)
380
+
381
+
382
+ # ---------------------------------------------------------------------------
383
+ # Plan Validation Helpers
384
+ # ---------------------------------------------------------------------------
385
+
386
+
387
+ def validate_plan_coverage(
388
+ plan: Sequence[tuple[int, int]],
389
+ expected_count: int,
390
+ ) -> set[int]:
391
+ """Validate that an orchestration plan covers all expected indices.
392
+
393
+ Args:
394
+ plan: Sequence of (index, seed) tuples from Rust planner.
395
+ expected_count: Number of glitchlings that should be covered.
396
+
397
+ Returns:
398
+ Set of missing indices (empty if plan is complete).
399
+ """
400
+ covered = {index for index, _ in plan}
401
+ expected = set(range(expected_count))
402
+ return expected - covered
403
+
404
+
405
+ def extract_plan_ordering(plan: Sequence[tuple[int, int]]) -> list[int]:
406
+ """Extract the execution order from an orchestration plan.
407
+
408
+ Args:
409
+ plan: Sequence of (index, seed) tuples.
410
+
411
+ Returns:
412
+ List of indices in execution order.
413
+ """
414
+ return [index for index, _ in plan]
415
+
416
+
417
+ def extract_plan_seeds(plan: Sequence[tuple[int, int]]) -> dict[int, int]:
418
+ """Extract the seed assignments from an orchestration plan.
419
+
420
+ Args:
421
+ plan: Sequence of (index, seed) tuples.
422
+
423
+ Returns:
424
+ Dictionary mapping index to assigned seed.
425
+ """
426
+ return {index: seed for index, seed in plan}
427
+
428
+
429
+ __all__ = [
430
+ # Types
431
+ "PlanSpecification",
432
+ "PipelineOperationPayload",
433
+ "PipelineDescriptor",
434
+ "PlanEntry",
435
+ "GlitchlingProtocol",
436
+ # Normalization
437
+ "NormalizedPlanSpec",
438
+ "normalize_plan_entries",
439
+ "normalize_plan_specs",
440
+ # Descriptors
441
+ "PipelineDescriptorModel",
442
+ "build_pipeline_descriptor",
443
+ # Execution planning
444
+ "ExecutionStep",
445
+ "ExecutionPlan",
446
+ "build_execution_plan",
447
+ # Validation
448
+ "validate_plan_coverage",
449
+ "extract_plan_ordering",
450
+ "extract_plan_seeds",
451
+ ]