aedmark commited on
Commit
f9ea262
·
verified ·
1 Parent(s): 6d689a1

Delete bone_spores.py

Browse files
Files changed (1) hide show
  1. bone_spores.py +0 -1085
bone_spores.py DELETED
@@ -1,1085 +0,0 @@
1
- """bone_spores.py"""
2
-
3
- import json
4
- import os
5
- import random
6
- import tempfile
7
- import time
8
- from collections import deque
9
- from typing import List, Tuple, Optional, Dict
10
-
11
- from bone_config import BoneConfig
12
- from bone_core import EventBus, LoreManifest, BoneJSONEncoder
13
- from bone_lexicon import LexiconService
14
- from bone_types import Prisma
15
-
16
-
17
- def _access_config_path(root, path, value=None, set_mode=False):
18
- target = root
19
- parts = path.split(".")
20
- try:
21
- for part in parts[:-1]:
22
- target = (
23
- target.get(part) if isinstance(target, dict) else getattr(target, part)
24
- )
25
- if target is None:
26
- return None
27
- leaf = parts[-1]
28
- is_dict = isinstance(target, dict)
29
- if set_mode:
30
- curr = target.get(leaf) if is_dict else getattr(target, leaf)
31
- if isinstance(curr, (int, float)):
32
- if is_dict:
33
- target[leaf] = value
34
- else:
35
- setattr(target, leaf, value)
36
- return True
37
- return False
38
- return target.get(leaf) if is_dict else getattr(target, leaf, None)
39
- except (AttributeError, KeyError, TypeError):
40
- return None
41
-
42
-
43
- class LocalFileSporeLoader:
44
- def __init__(self, directory="memories"):
45
- self.directory = directory
46
- if not os.path.exists(directory):
47
- os.makedirs(directory)
48
-
49
- def save_spore(self, filename, data):
50
- temp_path = filename
51
- if not os.path.isabs(filename) and not filename.startswith(
52
- os.path.join(self.directory, "")
53
- ):
54
- final_path = os.path.join(self.directory, filename)
55
- else:
56
- final_path = filename
57
- os.makedirs(os.path.dirname(final_path), exist_ok=True)
58
- try:
59
- fd, temp_path = tempfile.mkstemp(dir=os.path.dirname(final_path), text=True)
60
- with os.fdopen(fd, "w") as f:
61
- json.dump(data, f, indent=2, cls=BoneJSONEncoder)
62
- f.flush()
63
- os.fsync(f.fileno())
64
- os.replace(temp_path, final_path)
65
- return final_path
66
- except (IOError, OSError, TypeError) as e:
67
- print(f"{Prisma.RED}[LOADER] Error saving spore: {e}{Prisma.RST}")
68
- if os.path.exists(temp_path):
69
- os.remove(temp_path)
70
- return None
71
-
72
- @staticmethod
73
- def load_spore(filepath):
74
- if not os.path.exists(filepath):
75
- print(f"{Prisma.RED}[LOADER] File not found: {filepath}{Prisma.RST}")
76
- return None
77
- try:
78
- with open(filepath, "r", encoding="utf-8") as f:
79
- return json.load(f)
80
- except json.JSONDecodeError as e:
81
- print(f"{Prisma.RED}[LOADER] CORRUPT SPORE ({filepath}): {e}{Prisma.RST}")
82
- return None
83
- except IOError as e:
84
- print(f"{Prisma.RED}[LOADER] READ ERROR ({filepath}): {e}{Prisma.RST}")
85
- return None
86
-
87
- def list_spores(self):
88
- if not os.path.exists(self.directory):
89
- return []
90
- files = []
91
- for f in os.listdir(self.directory):
92
- if f.endswith(".json"):
93
- try:
94
- p = os.path.join(self.directory, f)
95
- files.append((p, os.path.getmtime(p), f))
96
- except OSError:
97
- continue
98
- return sorted(files, key=lambda x: x[1], reverse=True)
99
-
100
- @staticmethod
101
- def delete_spore(filepath):
102
- try:
103
- os.remove(filepath)
104
- return True
105
- except OSError:
106
- return False
107
-
108
-
109
- class SubconsciousStrata:
110
- def __init__(self, filename="memories/subconscious.jsonl"):
111
- self.filepath = filename
112
- self.directory = os.path.dirname(filename)
113
- if self.directory and not os.path.exists(self.directory):
114
- os.makedirs(self.directory)
115
- self.index = set()
116
- self._load_index()
117
-
118
- def _iter_entries(self):
119
- if not os.path.exists(self.filepath):
120
- return
121
- try:
122
- with open(self.filepath, "r", encoding="utf-8") as f:
123
- for line in f:
124
- if line.strip():
125
- try:
126
- yield json.loads(line)
127
- except json.JSONDecodeError:
128
- continue
129
- except IOError:
130
- pass
131
-
132
- def _load_index(self):
133
- self.index = {e["word"] for e in self._iter_entries() if "word" in e}
134
-
135
- def bury(self, fossil_data: Dict):
136
- try:
137
- if len(self.index) > 1000:
138
- self._prune_strata()
139
- with open(self.filepath, "a", encoding="utf-8") as f:
140
- fossil_data["buried_at"] = time.time()
141
- f.write(json.dumps(fossil_data, cls=BoneJSONEncoder) + "\n")
142
- self.index.add(fossil_data["word"])
143
- return True
144
- except IOError:
145
- return False
146
-
147
- def _prune_strata(self):
148
- try:
149
- with open(self.filepath, "r", encoding="utf-8") as f:
150
- lines = f.readlines()
151
- keep_count = int(len(lines) * 0.8)
152
- survivors = lines[-keep_count:]
153
- with open(self.filepath, "w", encoding="utf-8") as f:
154
- f.writelines(survivors)
155
- self.index = set()
156
- for line in survivors:
157
- try:
158
- self.index.add(json.loads(line)["word"])
159
- except:
160
- pass
161
- except Exception:
162
- pass
163
-
164
- def dredge(self, trigger_word: str) -> Optional[Dict]:
165
- if trigger_word not in self.index:
166
- return None
167
- return next(
168
- (e for e in self._iter_entries() if e.get("word") == trigger_word), None
169
- )
170
-
171
-
172
- class MemoryCore:
173
- def __init__(self, events_ref, subconscious_ref):
174
- self.events = events_ref
175
- self.subconscious = subconscious_ref
176
- self.graph = {}
177
- self.cortical_stack = deque(maxlen=15)
178
- self.short_term_buffer = deque(maxlen=10)
179
- self.consolidation_threshold = 5.0
180
- self.dimension_map = {
181
- "STR": {"heavy", "constructive", "base"},
182
- "VEL": {"kinetic", "explosive", "mot"},
183
- "ENT": {"antigen", "toxin", "broken"},
184
- "PHI": {"thermal", "photo"},
185
- "PSI": {"abstract", "sacred", "idea"},
186
- "BET": {"social", "suburban", "play"},
187
- }
188
-
189
- def illuminate(self, vector: Dict[str, float], limit: int = 5) -> List[str]:
190
- if not self.graph:
191
- return []
192
- active_dims = {k: v for k, v in vector.items() if v > 0.4}
193
- if not active_dims and vector:
194
- top_dim = max(vector, key=vector.get)
195
- active_dims = (
196
- {top_dim: vector[top_dim]} if vector[top_dim] > 0.1 else {"ENT": 0.2}
197
- )
198
- scored_memories = []
199
- for node, data in self.graph.items():
200
- resonance_score = 0.0
201
- node_cats = LexiconService.get_categories_for_word(node) or set()
202
- for dim, val in active_dims.items():
203
- target_cats = self.dimension_map.get(dim, set())
204
- if node_cats & target_cats:
205
- resonance_score += val * 1.5
206
- mass = sum(data.get("edges", {}).values())
207
- resonance_score += mass * 0.1
208
- if resonance_score > 0.5:
209
- scored_memories.append((resonance_score, node, data))
210
- scored_memories.sort(key=lambda x: x[0], reverse=True)
211
- results = []
212
- for score, name, data in scored_memories[:limit]:
213
- connections = list(data.get("edges", {}).keys())
214
- conn_str = f" -> [{', '.join(connections[:2])}]" if connections else ""
215
- prefix = "Resonant" if score > 0.5 else "Associated"
216
- results.append(f"{prefix} Engram: '{name.upper()}'{conn_str}")
217
- return results
218
-
219
- def calculate_mass(self, node):
220
- if node not in self.graph:
221
- return 0.0
222
- return sum(self.graph[node]["edges"].values())
223
-
224
- def strengthen_link(self, source, target, rate, decay):
225
- if source not in self.graph:
226
- return
227
- edges = self.graph[source]["edges"]
228
- if target not in edges:
229
- edges[target] = 0.0
230
- current_weight = edges[target]
231
- delta = rate * (1.0 - (current_weight * decay))
232
- edges[target] = min(10.0, current_weight + delta)
233
-
234
- def prune_synapses(self, scaling_factor=0.85, prune_threshold=0.5):
235
- pruned_count = 0
236
- total_decayed = 0
237
- nodes_to_remove = []
238
- for node in self.graph:
239
- edges = self.graph[node]["edges"]
240
- dead_links = []
241
- for target, weight in edges.items():
242
- resistance = min(1.0, weight / 10.0)
243
- dynamic_factor = scaling_factor + (0.14 * resistance)
244
- new_weight = weight * dynamic_factor
245
- edges[target] = new_weight
246
- total_decayed += 1
247
- if new_weight < prune_threshold:
248
- dead_links.append(target)
249
- for dead in dead_links:
250
- del edges[dead]
251
- pruned_count += 1
252
- if not edges:
253
- nodes_to_remove.append(node)
254
- for n in nodes_to_remove:
255
- del self.graph[n]
256
- for other_node in self.graph.values():
257
- if n in other_node["edges"]:
258
- del other_node["edges"][n]
259
- return f"📉 HOMEOSTATIC SCALING: Decayed {total_decayed} synapses. Pruned {pruned_count} weak connections."
260
-
261
- def cannibalize(
262
- self, current_tick, preserve_current=None
263
- ) -> Tuple[Optional[str], str]:
264
- protected = set()
265
- if preserve_current:
266
- if isinstance(preserve_current, list):
267
- protected.update(preserve_current)
268
- else:
269
- protected.add(preserve_current)
270
- protected.update(self.cortical_stack)
271
- candidates = []
272
- for k, v in self.graph.items():
273
- if k in protected:
274
- continue
275
- edge_count = len(v["edges"])
276
- age = max(1, current_tick - v.get("last_tick", 0))
277
- base_score = edge_count + (100.0 / age)
278
- candidates.append((k, v, base_score))
279
- if not candidates:
280
- return (
281
- None,
282
- "CORTICAL LOCK: All available memories are currently protected.",
283
- )
284
- candidates.sort(key=lambda x: x[2])
285
- victim, data, score = candidates[0]
286
- mass = sum(data["edges"].values())
287
- lifespan = current_tick - data.get("strata", {}).get("birth_tick", current_tick)
288
- fossil_data = {
289
- "word": victim,
290
- "mass": round(mass, 2),
291
- "lifespan": lifespan,
292
- "edges": data["edges"],
293
- "death_tick": current_tick,
294
- }
295
- self.subconscious.bury(fossil_data)
296
- del self.graph[victim]
297
- for node in self.graph:
298
- if victim in self.graph[node]["edges"]:
299
- del self.graph[node]["edges"][victim]
300
- return victim, f"REPRESSED: '{victim}' (Score {score:.1f} -> Subconscious)"
301
-
302
-
303
- class MycelialNetwork:
304
- def __init__(
305
- self, events: EventBus, loader: "LocalFileSporeLoader" = None, seed_file=None
306
- ):
307
- self.events = events
308
- self.loader = loader if loader else LocalFileSporeLoader()
309
- self.session_id = f"session_{int(time.time())}"
310
- self.filename = f"{self.session_id}.json"
311
- self.subconscious = SubconsciousStrata(
312
- filename=f"memories/subconscious_{self.session_id}.jsonl"
313
- )
314
- self.memory_core = MemoryCore(events, self.subconscious)
315
- self.lichen = BioLichen()
316
- self.parasite = BioParasite(self, LexiconService)
317
- self.immune = ImmuneMycelium()
318
- self.repro = LiteraryReproduction()
319
- self.fossils = deque(maxlen=200)
320
- self.lineage_log = deque(maxlen=50)
321
- self.seeds = self._load_seeds()
322
- self.session_health = getattr(BoneConfig, "MAX_HEALTH", 100.0)
323
- self.session_stamina = getattr(BoneConfig, "MAX_STAMINA", 100.0)
324
- self.session_trauma_vector = {}
325
- if seed_file:
326
- self.ingest(seed_file)
327
-
328
- @property
329
- def graph(self):
330
- return self.memory_core.graph
331
-
332
- @property
333
- def cortical_stack(self):
334
- return self.memory_core.cortical_stack
335
-
336
- def calculate_mass(self, node):
337
- return self.memory_core.calculate_mass(node)
338
-
339
- def run_ecosystem(self, physics: Dict, stamina: float, tick: int) -> List[str]:
340
- logs = []
341
- clean_words = physics.get("clean_words", [])
342
- sugar, lichen_msg = self.lichen.photosynthesize(physics, clean_words, tick)
343
- if lichen_msg:
344
- logs.append(lichen_msg)
345
- for word in clean_words:
346
- toxin_msg = self.immune.assay(word, None, None, physics, None)[1]
347
- if toxin_msg:
348
- logs.append(f"{Prisma.CYN}🛡️ IMMUNE RESPONSE: {toxin_msg}{Prisma.RST}")
349
- infected, parasite_msg = self.parasite.infect(physics, stamina)
350
- if infected and parasite_msg:
351
- logs.append(parasite_msg)
352
- if random.random() < 0.10:
353
- chorus_log = self._poll_chorus(clean_words, physics)
354
- if chorus_log:
355
- logs.append(chorus_log)
356
- return logs
357
-
358
- def _poll_chorus(self, clean_words: list, physics: Dict) -> Optional[str]:
359
- total_voltage_boost = 0.0
360
- total_drag_penalty = 0.0
361
- echo_count = 0
362
- for w in clean_words:
363
- v_boost, d_pen = self._check_echo_well(w)
364
- if v_boost > 0:
365
- total_voltage_boost += v_boost
366
- total_drag_penalty += d_pen
367
- echo_count += 1
368
- if echo_count > 0:
369
- physics["voltage"] = physics.get("voltage", 0.0) + total_voltage_boost
370
- physics["narrative_drag"] = (
371
- physics.get("narrative_drag", 0.0) + total_drag_penalty
372
- )
373
- if total_voltage_boost > 4.0:
374
- return f"{Prisma.VIOLET}👻 ECHO: The past is heavy here. (Drag +{total_drag_penalty:.1f}){Prisma.RST}"
375
- elif total_voltage_boost > 0:
376
- return f"{Prisma.GRY}👻 ECHO: Familiar ground.{Prisma.RST}"
377
- return None
378
-
379
- def prune_synapses(self, scaling_factor=0.85, prune_threshold=0.5):
380
- return self.memory_core.prune_synapses(scaling_factor, prune_threshold)
381
-
382
- def encode(self, clean_words, physics, governor_mode):
383
- significance = physics.get("voltage", 0.0)
384
- if governor_mode == "FORGE":
385
- significance *= 2.0
386
- elif governor_mode == "LABORATORY":
387
- significance *= 1.2
388
- engram = {
389
- "trigger": clean_words[:3] if clean_words else ["void"],
390
- "context": governor_mode,
391
- "significance": significance,
392
- "timestamp": time.time(),
393
- }
394
- if significance > self.memory_core.consolidation_threshold:
395
- self.memory_core.short_term_buffer.append(engram)
396
- return True
397
- return False
398
-
399
- def check_for_resurrection(
400
- self, input_words: List[str], voltage: float
401
- ) -> Optional[str]:
402
- if voltage < 60.0:
403
- return None
404
- for word in input_words:
405
- if word in self.subconscious.index:
406
- if random.random() < 0.20:
407
- memory = self.subconscious.dredge(word)
408
- if memory:
409
- self.graph[word] = {"edges": memory["edges"], "last_tick": 0}
410
- return f"⚠️ FLASHBACK: The word '{word}' clawed its way back from the deep."
411
- return None
412
-
413
- def bury(
414
- self,
415
- clean_words: List[str],
416
- tick: int,
417
- resonance=5.0,
418
- learning_mod=1.0,
419
- desperation_level=0.0,
420
- ) -> Tuple[Optional[str], List[str]]:
421
- if not clean_words:
422
- return None, []
423
- valuable = self._filter_valuable_matter(clean_words)
424
- self.cortical_stack.extend(valuable)
425
- if len(self.graph) > BoneConfig.MAX_MEMORY_CAPACITY:
426
- if desperation_level < 0.6:
427
- return (
428
- f"CORTICAL SATURATION: Memory full & Glucose High. Input rejected.",
429
- [],
430
- )
431
- victim, log_msg = self.memory_core.cannibalize(
432
- tick, preserve_current=clean_words[0]
433
- )
434
- if not victim:
435
- return f"MEMORY FULL: Cortical Lock. Input rejected.", []
436
- else:
437
- victim, log_msg = None, None
438
- base_rate = 0.5 * (resonance / 5.0)
439
- learning_rate = max(0.1, min(1.0, base_rate * learning_mod))
440
- decay_rate = 0.1
441
- for i, current in enumerate(valuable):
442
- if current not in self.graph:
443
- self.graph[current] = {"edges": {}, "last_tick": tick}
444
- else:
445
- self.graph[current]["last_tick"] = tick
446
- start_window = max(0, i - 2)
447
- context_window = set(valuable[start_window:i])
448
- for prev in context_window:
449
- if prev == current:
450
- continue
451
- if prev not in self.graph:
452
- self.graph[prev] = {"edges": {}, "last_tick": tick}
453
- self.memory_core.strengthen_link(
454
- current, prev, learning_rate, decay_rate
455
- )
456
- self.memory_core.strengthen_link(
457
- prev, current, learning_rate, decay_rate
458
- )
459
- new_wells = self._detect_new_wells(valuable, tick)
460
- return log_msg, ([victim] if victim else []) + new_wells
461
-
462
- @staticmethod
463
- def _filter_valuable_matter(words: List[str]) -> List[str]:
464
- valuable = []
465
- for w in words:
466
- if len(w) <= 4 and w in LexiconService.SOLVENTS:
467
- continue
468
- cat = LexiconService.get_current_category(w)
469
- if cat and cat != "void":
470
- valuable.append(w)
471
- elif len(w) > 4:
472
- valuable.append(w)
473
- return valuable
474
-
475
- def _detect_new_wells(self, words, tick):
476
- new_wells = []
477
- for w in words:
478
- if w in self.graph:
479
- self._check_echo_well(w)
480
- mass = self.memory_core.calculate_mass(w)
481
- if mass > BoneConfig.SHAPLEY_MASS_THRESHOLD:
482
- node_data = self.graph[w]
483
- if "strata" not in node_data:
484
- node_data["strata"] = {
485
- "birth_tick": tick,
486
- "birth_mass": mass,
487
- "stability_index": 0.0,
488
- }
489
- new_wells.append(w)
490
- else:
491
- age = max(1, tick - node_data["strata"]["birth_tick"])
492
- growth = (mass - node_data["strata"]["birth_mass"]) / age
493
- node_data["strata"]["growth_rate"] = round(growth, 3)
494
- return new_wells
495
-
496
- def _check_echo_well(self, node):
497
- if node in self.graph:
498
- mass = self.calculate_mass(node)
499
- if mass > 8.0:
500
- return 2.0, 1.5
501
- elif mass > 4.0:
502
- return 0.5, 0.5
503
- return 0.0, 0.0
504
-
505
- @staticmethod
506
- def _load_seeds():
507
- from bone_village import ParadoxSeed
508
-
509
- loaded_seeds = []
510
- try:
511
- raw_seeds = LoreManifest.get_instance().get("seeds") or []
512
- for item in raw_seeds:
513
- q = item.get("question", "Undefined Paradox")
514
- t = set(item.get("triggers", []))
515
- seed = ParadoxSeed(q, t)
516
- loaded_seeds.append(seed)
517
- except Exception:
518
- loaded_seeds = [
519
- ParadoxSeed("Does the mask eat the face?", {"mask", "face", "hide"})
520
- ]
521
- return loaded_seeds
522
-
523
- def tend_garden(self, current_words):
524
- bloom_msg = None
525
- for seed in self.seeds:
526
- is_ready = seed.water(current_words)
527
- if is_ready and not bloom_msg:
528
- bloom_msg = seed.bloom()
529
- return bloom_msg
530
-
531
- def _apply_epigenetics(self, data):
532
- if "config_mutations" not in data:
533
- return
534
- self.events.log(
535
- f"{Prisma.MAG}EPIGENETICS: Auditing ancestral configuration...{Prisma.RST}"
536
- )
537
- valid_mutations = 0
538
- SAFE_MUTATIONS = {
539
- "STAMINA_REGEN",
540
- "MAX_DRAG_LIMIT",
541
- "GEODESIC_STRENGTH",
542
- "SIGNAL_DRAG_MULTIPLIER",
543
- "KINETIC_GAIN",
544
- "TOXIN_WEIGHT",
545
- "FLASHPOINT_THRESHOLD",
546
- "MAX_MEMORY_CAPACITY",
547
- "PRIORITY_LEARNING_RATE",
548
- "ANVIL_TRIGGER_VOLTAGE",
549
- "MAX_REPETITION_LIMIT",
550
- "PHYSICS.WEIGHT_HEAVY",
551
- "PHYSICS.WEIGHT_KINETIC",
552
- "PHYSICS.VOLTAGE_FLOOR",
553
- "PHYSICS.VOLTAGE_MAX",
554
- "BIO.CORTEX_SENSITIVITY",
555
- "BIO.ROS_CRITICAL",
556
- "BIO.DECAY_RATE",
557
- "BIO.REWARD_MEDIUM",
558
- "METABOLISM.PHOTOSYNTHESIS_GAIN",
559
- "METABOLISM.ROS_GENERATION_FACTOR",
560
- "COUNCIL.FOOTNOTE_CHANCE",
561
- "COUNCIL.MANIC_VOLTAGE_TRIGGER",
562
- "GRAVITY_WELL_THRESHOLD",
563
- "PRIORITY_LEARNING_RATE",
564
- }
565
- for key, value in data["config_mutations"].items():
566
- if key in SAFE_MUTATIONS:
567
- if _access_config_path(BoneConfig, key, value, set_mode=True):
568
- valid_mutations += 1
569
- if valid_mutations > 0:
570
- self.events.log(
571
- f"{Prisma.CYN} ► Applied {valid_mutations} verified config shifts.{Prisma.RST}"
572
- )
573
-
574
- def ingest(self, target_file, current_tick=0):
575
- data = self.loader.load_spore(target_file)
576
- if not data:
577
- self.events.log(f"{Prisma.RED}[MEMORY]: Spore file not found.{Prisma.RST}")
578
- return None, set(), {}, None
579
-
580
- required_keys = ["meta", "trauma_vector", "core_graph"]
581
- if not all(k in data for k in required_keys):
582
- self.events.log(
583
- f"{Prisma.RED}[MEMORY]: Spore rejected (Missing Structural Keys).{Prisma.RST}"
584
- )
585
- return None, set(), {}, None
586
- self._process_lineage(data)
587
- self._process_mutations(data)
588
- self._apply_epigenetics(data)
589
- if "core_graph" in data:
590
- self.graph.update(data["core_graph"])
591
- for node in data["core_graph"]:
592
- if node in self.graph:
593
- self.graph[node]["last_tick"] = current_tick
594
- return self._extract_legacy_traits(data)
595
-
596
- def _process_lineage(self, data):
597
- session_source = data.get("session_id", "UNKNOWN_ANCESTOR")
598
- timestamp = data.get("meta", {}).get("timestamp", 0)
599
- time_ago = int((time.time() - timestamp) / 3600)
600
- trauma_summary = {
601
- k: v for k, v in data.get("trauma_vector", {}).items() if v > 0.1
602
- }
603
- mutation_count = sum(len(v) for v in data.get("mutations", {}).values())
604
- self.lineage_log.append(
605
- {
606
- "source": session_source,
607
- "age_hours": time_ago,
608
- "trauma": trauma_summary,
609
- "mutations": mutation_count,
610
- "loaded_at": time.time(),
611
- }
612
- )
613
-
614
- def _process_mutations(self, data):
615
- mutations = data.get("mutations", {})
616
- if not mutations:
617
- return
618
- accepted_count = 0
619
- for cat, words in mutations.items():
620
- for w in words:
621
- current_cat = LexiconService.get_current_category(w)
622
- if not current_cat or current_cat == "unknown":
623
- LexiconService.teach(w, cat, 0)
624
- accepted_count += 1
625
- if accepted_count > 0:
626
- self.events.log(
627
- f"{Prisma.CYN}[MEMBRANE]: Integrated {accepted_count} mutations.{Prisma.RST}"
628
- )
629
-
630
- def _extract_legacy_traits(self, data):
631
- if "joy_legacy" in data and data["joy_legacy"]:
632
- joy = data["joy_legacy"]
633
- clade = LiteraryReproduction.JOY_CLADE.get(joy.get("flavor"))
634
- if clade:
635
- self.events.log(
636
- f"{Prisma.CYN}INHERITED GLORY: {clade['title']}{Prisma.RST}"
637
- )
638
- for stat, ancestral_bonus in clade["buff"].items():
639
- if hasattr(BoneConfig, stat):
640
- setattr(BoneConfig, stat, ancestral_bonus)
641
- if "seeds" in data:
642
- from bone_village import ParadoxSeed
643
-
644
- self.seeds = []
645
- for s_data in data["seeds"]:
646
- new_seed = ParadoxSeed(s_data["q"], set())
647
- new_seed.maturity = s_data.get("m", 0.0)
648
- new_seed.bloomed = s_data.get("b", False)
649
- self.seeds.append(new_seed)
650
- return (
651
- data.get("mitochondria", {}),
652
- set(data.get("antibodies", [])),
653
- data.get("soul_legacy", {}),
654
- data.get("continuity", None),
655
- data.get("world_atlas", {}),
656
- )
657
-
658
- def save(
659
- self,
660
- health,
661
- stamina,
662
- mutations,
663
- trauma_accum,
664
- joy_history,
665
- mitochondria_traits=None,
666
- antibodies=None,
667
- soul_data=None,
668
- continuity=None,
669
- world_atlas=None,
670
- village_data=None,
671
- ):
672
- final_vector = {k: min(1.0, v) for k, v in trauma_accum.items()}
673
- top_joy = sorted(joy_history, key=lambda x: x["resonance"], reverse=True)[:3]
674
- joy_legacy_data = None
675
- if top_joy:
676
- joy_legacy_data = {
677
- "flavor": top_joy[0]["dominant_flavor"],
678
- "resonance": top_joy[0]["resonance"],
679
- "timestamp": top_joy[0]["timestamp"],
680
- }
681
- core_graph = {}
682
- for k, data in self.graph.items():
683
- filtered_edges = {}
684
- for target, weight in data["edges"].items():
685
- if weight > 1.0:
686
- filtered_edges[target] = round(weight, 2)
687
- if filtered_edges:
688
- core_graph[k] = {"edges": filtered_edges, "last_tick": 0}
689
- temp_trauma = {k: min(1.0, v) for k, v in trauma_accum.items()}
690
- future_seed_q = self._generate_future_seed(
691
- temp_health=health, trauma_vec=temp_trauma
692
- )
693
- seed_list = [
694
- {"q": s.question, "m": s.maturity, "b": s.bloomed}
695
- for s in self.seeds
696
- if not s.bloomed
697
- ]
698
- seed_list.append({"q": future_seed_q, "m": 0.0, "b": False})
699
- data = {
700
- "genome": "BONEAMANITA_15.8.0",
701
- "session_id": self.session_id,
702
- "parent_id": self.session_id,
703
- "meta": {
704
- "timestamp": time.time(),
705
- "final_health": health,
706
- "final_stamina": stamina,
707
- },
708
- "trauma_vector": final_vector,
709
- "joy_vectors": top_joy or [],
710
- "joy_legacy": joy_legacy_data,
711
- "core_graph": core_graph,
712
- "mutations": mutations,
713
- "antibodies": list(antibodies) if antibodies else [],
714
- "mitochondria": mitochondria_traits,
715
- "soul_legacy": soul_data,
716
- "continuity": continuity,
717
- "world_atlas": world_atlas or {},
718
- "village_data": village_data,
719
- "seeds": seed_list,
720
- "fossils": list(self.fossils),
721
- }
722
- return self.loader.save_spore(self.filename, data)
723
-
724
- @staticmethod
725
- def _generate_future_seed(temp_health, trauma_vec) -> str:
726
- condition = "BALANCED"
727
- max_trauma = max(trauma_vec, key=trauma_vec.get) if trauma_vec else "NONE"
728
- if trauma_vec.get(max_trauma, 0) > 0.6 or temp_health < 30:
729
- condition = "HIGH_TRAUMA"
730
- seeds = {"HIGH_TRAUMA": "Recovery", "BALANCED": "Growth"}
731
- return seeds.get(condition, "Hope")
732
-
733
- def cleanup_old_sessions(self, limbo_layer=None):
734
- files = self.loader.list_spores()
735
- removed = 0
736
- max_files = 25
737
- max_age = 86400
738
- current_time = time.time()
739
- for i, (path, age, fname) in enumerate(files):
740
- file_age = current_time - age
741
- if i >= max_files or file_age > max_age:
742
- try:
743
- if limbo_layer:
744
- limbo_layer.absorb_dead_timeline(path)
745
- if self.loader.delete_spore(path):
746
- removed += 1
747
- except (OSError, AttributeError):
748
- pass
749
- if removed:
750
- self.events.log(
751
- f"{Prisma.GRY}[TIME MENDER]: Pruned {removed} dead timelines.{Prisma.RST}"
752
- )
753
-
754
- def report_status(self):
755
- return len(self.graph)
756
-
757
- def autoload_last_spore(self):
758
- files = self.loader.list_spores()
759
- if not files:
760
- self.events.log(
761
- f"{Prisma.GRY}[GENETICS]: No ancestors found. Genesis Bloom.{Prisma.RST}"
762
- )
763
- return None
764
- candidates = [f for f in files if self.session_id not in f[0]]
765
- if candidates:
766
- return self.ingest(candidates[0][0])
767
- return None
768
-
769
-
770
- class ImmuneMycelium:
771
- def __init__(self):
772
- self.active_antibodies = set()
773
- self.PHONETICS = {
774
- "PLOSIVE": set("bdgkpt"),
775
- "FRICATIVE": set("fthszsh"),
776
- "LIQUID": set("lr"),
777
- "NASAL": set("mn"),
778
- }
779
- self.ROOTS = {
780
- "HEAVY": (
781
- "lith",
782
- "ferr",
783
- "petr",
784
- "dens",
785
- "grav",
786
- "struct",
787
- "base",
788
- "fund",
789
- "mound",
790
- ),
791
- "KINETIC": ("mot", "mov", "ject", "tract", "pel", "crat", "dynam", "flux"),
792
- }
793
- self.name = "MYCELIUM"
794
- self.color = Prisma.CYN
795
- self.archetypes = {"constructive", "kinetic", "abstract", "code", "system"}
796
-
797
- def opine(self, clean_words: list, _voltage: float) -> Tuple[float, str]:
798
- hits = sum(1 for w in clean_words if w in self.archetypes)
799
- score = (hits / max(1, len(clean_words))) * 10.0
800
- comment = "Scanning for structural integrity..."
801
- if score > 2.0:
802
- comment = "The pattern holds. Integration probable."
803
- return score, comment
804
-
805
- def assay(self, word, _context, _rep_val, _phys, _pulse):
806
- w = word.lower()
807
- clean_len = len(w)
808
- if clean_len < 3:
809
- return None, ""
810
- for roots in self.ROOTS.values():
811
- for r in roots:
812
- if r in w:
813
- if w.startswith(r) or w.endswith(r) or (len(r) / clean_len > 0.5):
814
- return None, ""
815
- plosive = sum(1 for c in w if c in self.PHONETICS["PLOSIVE"])
816
- nasal = sum(1 for c in w if c in self.PHONETICS["NASAL"])
817
- density = ((plosive * 1.2) + (nasal * 0.8)) / clean_len
818
- if clean_len <= 4:
819
- density *= 1.2
820
- if density > 1.0:
821
- return "TOXIN_HEAVY", f"Detected phonetic toxicity in '{w}'."
822
- return None, ""
823
-
824
-
825
- class BioParasite:
826
- def __init__(self, memory_ref, lexicon_ref):
827
- self.mem = memory_ref
828
- self.lex = lexicon_ref
829
- self.spores_deployed = 0
830
- self.MAX_SPORES = 8
831
- self.name = "PARASITE"
832
- self.color = Prisma.RED
833
- self.archetypes = {
834
- "antigen",
835
- "toxin",
836
- "heavy",
837
- "meat",
838
- "void",
839
- "static",
840
- "rot",
841
- "decay",
842
- }
843
-
844
- def opine(self, clean_words: list, voltage: float) -> Tuple[float, str]:
845
- hits = sum(1 for w in clean_words if w in self.archetypes)
846
- score = (hits / max(1, len(clean_words))) * 10.0
847
- comment = "..."
848
- if score > 3.0:
849
- comment = "Delicious. The entropy is sweet."
850
- elif score > 1.0:
851
- comment = "I smell rust."
852
- elif voltage > 15.0:
853
- comment = "Stop vibrating. Be still and rot."
854
- elif voltage < 5.0:
855
- comment = "Finally. Silence."
856
- return score, comment
857
-
858
- def infect(self, physics_packet, stamina):
859
- psi = physics_packet.get("psi", 0.0)
860
- if stamina > 40.0 and psi < 0.6:
861
- return False, None
862
- if self.spores_deployed >= self.MAX_SPORES:
863
- if random.random() < 0.2:
864
- self.spores_deployed = max(0, self.spores_deployed - 1)
865
- return False, None
866
- graph = self.mem.graph
867
- heavy_candidates = [w for w in graph if w in (self.lex.get("heavy") or [])]
868
- abstract_candidates = [
869
- w for w in graph if w in (self.lex.get("abstract") or [])
870
- ]
871
- if not heavy_candidates or not abstract_candidates:
872
- return False, None
873
- host = random.choice(heavy_candidates)
874
- parasite = random.choice(abstract_candidates)
875
- if parasite in graph[host]["edges"]:
876
- return False, None
877
- is_metaphor = psi > 0.7
878
- weight = 8.88
879
- graph[host]["edges"][parasite] = weight
880
- if parasite not in graph:
881
- graph[parasite] = {"edges": {}, "last_tick": 0}
882
- graph[parasite]["edges"][host] = weight
883
- self.spores_deployed += 1
884
- if is_metaphor:
885
- return True, (
886
- f"{Prisma.CYN}✨ SYNAPSE SPARK: Your mind bridges '{host.upper()}' and '{parasite.upper()}'.\n"
887
- f" A new metaphor is born. The map folds.{Prisma.RST}"
888
- )
889
- else:
890
- return True, (
891
- f"{Prisma.VIOLET}🍄 INTRUSIVE THOUGHT: Exhaustion logic links '{host.upper()}' <-> '{parasite.upper()}'.\n"
892
- f" This makes no sense, yet there it is. 'Some things just happen.'{Prisma.RST}"
893
- )
894
-
895
-
896
- class BioLichen:
897
- def __init__(self):
898
- self.name = "LICHEN"
899
- self.color = Prisma.GRN
900
- self.archetypes = {
901
- "photo",
902
- "play",
903
- "sacred",
904
- "social",
905
- "solar",
906
- "vital",
907
- "bloom",
908
- "grow",
909
- }
910
-
911
- def opine(self, clean_words: list, voltage: float) -> Tuple[float, str]:
912
- hits = sum(1 for w in clean_words if w in self.archetypes)
913
- score = (hits / max(1, len(clean_words))) * 10.0
914
- comment = "..."
915
- if score > 3.0:
916
- comment = "Yes! The roots are drinking deep."
917
- elif score > 1.0:
918
- comment = "We see the light."
919
- elif voltage > 18.0:
920
- comment = "Too hot! You'll scorch the leaves!"
921
- elif voltage < 2.0:
922
- comment = "It is cold... we are sleeping."
923
- return score, comment
924
-
925
- def photosynthesize(self, phys, clean_words, tick_count):
926
- msgs = []
927
- if hasattr(phys, "counts"):
928
- counts = phys.counts
929
- drag = getattr(phys, "narrative_drag", 0.0)
930
- else:
931
- counts = phys.get("counts", {})
932
- drag = phys.get("narrative_drag", 0.0)
933
- light = counts.get("photo", 0)
934
- sugar = 0.0
935
- light_words = [w for w in clean_words if w in self.archetypes]
936
- if light > 0 and drag < 3.0:
937
- s = light * 2
938
- sugar += s
939
- source_str = f" via '{random.choice(light_words)}'" if light_words else ""
940
- msgs.append(f"{Prisma.GRN}PHOTOSYNTHESIS{source_str} (+{s}){Prisma.RST}")
941
- if sugar > 0:
942
- heavy_words = [
943
- w for w in clean_words if w in (LexiconService.get("heavy") or [])
944
- ]
945
- if heavy_words:
946
- h_word = random.choice(heavy_words)
947
- LexiconService.teach(h_word, "photo", tick_count)
948
- msgs.append(
949
- f"{Prisma.MAG}SUBLIMATION: '{h_word}' has become Light.{Prisma.RST}"
950
- )
951
- return sugar, " ".join(msgs) if msgs else None
952
-
953
-
954
- class LiteraryReproduction:
955
- MUTATIONS = {}
956
- JOY_CLADE = {}
957
-
958
- @classmethod
959
- def load_genetics(cls):
960
- try:
961
- genetics = LoreManifest.get_instance().get("GENETICS")
962
- cls.MUTATIONS = genetics.get("MUTATIONS", {})
963
- cls.JOY_CLADE = genetics.get("JOY_CLADE", {})
964
- except Exception:
965
- cls.MUTATIONS = {}
966
- cls.JOY_CLADE = {}
967
-
968
- @staticmethod
969
- def _extract_counts(physics_container):
970
- if hasattr(physics_container, "counts"):
971
- return physics_container.counts
972
- if isinstance(physics_container, dict):
973
- return physics_container.get("counts", {})
974
- return {}
975
-
976
- @staticmethod
977
- def mutate_config(current_config):
978
- mutations = {}
979
- MUTATION_TABLE = [
980
- ("MAX_DRAG_LIMIT", 1.0, 20.0, 0.3),
981
- ("TOXIN_WEIGHT", 0.1, 5.0, 0.3),
982
- ("MAX_HEALTH", 50.0, 500.0, 0.1),
983
- ("PHYSICS.VOLTAGE_MAX", 10.0, 100.0, 0.2),
984
- ("BIO.REWARD_MEDIUM", 0.01, 1.0, 0.2),
985
- ("COUNCIL.MANIC_VOLTAGE_TRIGGER", 10.0, 50.0, 0.1),
986
- ("PRIORITY_LEARNING_RATE", 0.5, 5.0, 0.15),
987
- ]
988
- for key, min_v, max_v, chance in MUTATION_TABLE:
989
- if random.random() < chance:
990
- current_val = LiteraryReproduction._resolve_config_value(
991
- current_config, key
992
- )
993
- if current_val is not None:
994
- drift = random.uniform(0.9, 1.1)
995
- mutations[key] = max(min_v, min(max_v, current_val * drift))
996
- return mutations
997
-
998
- @staticmethod
999
- def _resolve_config_value(root_config, path):
1000
- return _access_config_path(root_config, path, set_mode=False)
1001
-
1002
- @staticmethod
1003
- def mitosis(parent_id, bio_state, physics):
1004
- counts = LiteraryReproduction._extract_counts(physics)
1005
- dominant = max(counts, key=counts.get) if counts else "VOID"
1006
- mutation_data = LiteraryReproduction.MUTATIONS.get(
1007
- dominant.upper(), {"trait": "NEUTRAL", "mod": {}, "lexicon": []}
1008
- )
1009
- child_id = f"{parent_id}_({mutation_data['trait']})"
1010
- config_mutations = LiteraryReproduction.mutate_config(BoneConfig)
1011
- config_mutations.update(mutation_data["mod"])
1012
- lexicon_mutations = {dominant.lower(): mutation_data.get("lexicon", [])}
1013
- trauma_vec = bio_state.get("trauma_vector", {})
1014
- child_genome = {
1015
- "source": "MITOSIS",
1016
- "parent_a": parent_id,
1017
- "parent_b": None,
1018
- "lexicon_mutations": lexicon_mutations,
1019
- "config_mutations": config_mutations,
1020
- "dominant_flavor": dominant,
1021
- "trauma_inheritance": trauma_vec,
1022
- }
1023
- return child_id, child_genome
1024
-
1025
- @staticmethod
1026
- def crossover(parent_a_id, parent_a_bio, parent_b_path):
1027
- try:
1028
- with open(parent_b_path, "r") as f:
1029
- parent_b_data = json.load(f)
1030
- except (IOError, json.JSONDecodeError):
1031
- return None, "Dead Spore (Corrupt File)."
1032
- parent_b_id = parent_b_data.get("session_id", "UNKNOWN")
1033
- trauma_a = parent_a_bio.get("trauma_vector", {})
1034
- trauma_b = parent_b_data.get("trauma_vector", {})
1035
- child_trauma = {}
1036
- all_keys = set(trauma_a.keys()) | set(trauma_b.keys())
1037
- for k in all_keys:
1038
- child_trauma[k] = max(trauma_a.get(k, 0), trauma_b.get(k, 0))
1039
- enzymes_a = set()
1040
- if "mito" in parent_a_bio:
1041
- if hasattr(parent_a_bio["mito"], "state"):
1042
- enzymes_a = set(parent_a_bio["mito"].state.enzymes)
1043
- elif isinstance(parent_a_bio["mito"], dict):
1044
- enzymes_a = set(parent_a_bio["mito"].get("enzymes", []))
1045
- enzymes_b = set(parent_b_data.get("mitochondria", {}).get("enzymes", []))
1046
- child_enzymes = list(enzymes_a | enzymes_b)
1047
- config_mutations = LiteraryReproduction.mutate_config(BoneConfig)
1048
- short_a = parent_a_id[-4:] if len(parent_a_id) > 4 else parent_a_id
1049
- short_b = parent_b_id[-4:] if len(parent_b_id) > 4 else parent_b_id
1050
- child_id = f"HYBRID_{short_a}x{short_b}"
1051
- child_genome = {
1052
- "source": "CROSSOVER",
1053
- "parent_a": parent_a_id,
1054
- "parent_b": parent_b_id,
1055
- "trauma_inheritance": child_trauma,
1056
- "config_mutations": config_mutations,
1057
- "inherited_enzymes": child_enzymes,
1058
- "lexicon_mutations": {},
1059
- }
1060
- return child_id, child_genome
1061
-
1062
- def attempt_reproduction(
1063
- self, engine_ref, mode="MITOSIS", target_spore=None
1064
- ) -> Tuple[str, Dict]:
1065
- mem = engine_ref.mind.mem
1066
- bio_state = {
1067
- "trauma_vector": engine_ref.trauma_accum,
1068
- "mito": engine_ref.bio.mito,
1069
- }
1070
- phys_packet = {}
1071
- if hasattr(engine_ref, "cortex") and engine_ref.cortex.last_physics:
1072
- phys_packet = engine_ref.cortex.last_physics
1073
- elif hasattr(engine_ref, "phys") and hasattr(engine_ref.phys, "observer"):
1074
- if engine_ref.phys.observer.last_physics_packet:
1075
- phys_packet = engine_ref.phys.observer.last_physics_packet
1076
- genome = {}
1077
- child_id = "UNKNOWN"
1078
- if mode == "MITOSIS":
1079
- child_id, genome = self.mitosis(mem.session_id, bio_state, phys_packet)
1080
- elif mode == "CROSSOVER":
1081
- if target_spore:
1082
- res = self.crossover(mem.session_id, bio_state, target_spore)
1083
- if res[0]:
1084
- child_id, genome = res
1085
- return child_id, genome.get("lexicon_mutations", {})