""" Sequential Growth Engine — orchestrates Birth and Split events with K6 gating. """ from collections import deque class SequentialGrowthEngine: def __init__(self, max_events_per_step=1, max_births_per_100=5, max_splits_per_100=3, cooldown_steps=100, verbose=False): self.max_events_per_step = max_events_per_step self.max_births_per_100 = max_births_per_100 self.max_splits_per_100 = max_splits_per_100 self.cooldown_steps = cooldown_steps self.verbose = verbose self.queue = deque() self.birth_history = [] self.split_history = [] self.layer_last_event = {} self.total_births = 0 self.total_splits = 0 self.total_rejected = 0 def _recent_count(self, history, step, window=100): return sum(1 for s in history if step - s < window) def can_birth(self, layer_idx, step): if self._recent_count(self.birth_history, step) >= self.max_births_per_100: return False last = self.layer_last_event.get(layer_idx, -1e9) return (step - last) >= self.cooldown_steps def can_split(self, layer_idx, step): if self._recent_count(self.split_history, step) >= self.max_splits_per_100: return False last = self.layer_last_event.get(layer_idx, -1e9) return (step - last) >= self.cooldown_steps def enqueue(self, event): self.queue.append(event) def process_one(self, step): processed = [] for _ in range(self.max_events_per_step): if not self.queue: break found = False for i, event in enumerate(self.queue): if event["type"] == "birth" and self.can_birth(event["layer_idx"], step): e = self.queue[i]; del self.queue[i] self.birth_history.append(step) self.layer_last_event[e["layer_idx"]] = step self.total_births += 1 processed.append(e); found = True; break elif event["type"] == "split" and self.can_split(event["layer_idx"], step): e = self.queue[i]; del self.queue[i] self.split_history.append(step) self.layer_last_event[e["layer_idx"]] = step self.total_splits += 1 processed.append(e); found = True; break if not found: self.total_rejected += 1 break return processed def pending_count(self): return len(self.queue) def stats(self): return { "queued": len(self.queue), "births": self.total_births, "splits": self.total_splits, "rejected": self.total_rejected, }