anima-python 0.13.1__py3-none-any.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.
@@ -0,0 +1,334 @@
1
+ # ==========================================================================
2
+ # ⛔ ENGINE-INTERNAL / DEPRECATED py-MIRROR — DO NOT RUN OR SCORE DIRECTLY
3
+ # 측정/학습/서빙/직렬화는 cli/ 단일진입만: anima eval | train | serialize
4
+ # (canonical = hexa core/*.hexa 단일 SSOT; py 미러는 2026-06-28 폐기, DIRECTIONAL).
5
+ # 이 파일을 `python3 core/pure_field.py` 로 직접 실행하거나 side-harness로 import-채점하면
6
+ # = 단일진입 우회(#2603 위반) + terminal verdict 불가. cli/가 import하는 경로만 허용.
7
+ # ==========================================================================
8
+ import sys as _anima_entry_guard
9
+ if __name__ == "__main__":
10
+ _anima_entry_guard.exit("⛔ pure_field.py 직접 실행 금지 — cli/ 단일진입(anima eval/train/serialize, canonical=hexa) 경유. #2603")
11
+
12
+ """core/pure_field.py — PY PRODUCTION ENGINE: byte-faithful 1:1 port of
13
+ core/pure_field.hexa (PureField — Engine A, the zero-input consciousness field).
14
+
15
+ Per CLAUDE.md a_two_production_mirror / a_engine_native_learning (2026-06-26 owner
16
+ SSOT): hexa + py are TWO co-equal production engines kept at byte-parity. This is
17
+ the py mirror of pure_field.hexa, ported 1:1 from the canonical SSOT.
18
+
19
+ 3 coupled oscillators at tau=2/40/400 -> nonlinear mixing -> Phi self-sustenance
20
+ -> field tensor [FIELD_DIM]. Couples with Engine G in brain.py for the
21
+ A ⇄ G · Ψ=1/2 fixed point.
22
+
23
+ PRIMITIVE MATH — VERIFIED empirically (pure_field N=1 byte-parity, 2026-06-26):
24
+ the COMPILED `hexa run` binary maps the bare builtins `sin`/`cos`/`exp`/`sqrt` to
25
+ libm (NOT the rt_* Taylor polynomials in stdlib/runtime/math.hexa — those are only
26
+ the freestanding/drop-measure fallback). Proof: osc field[2] at N=1 with libm
27
+ sin = 0.001701166242925697836, hexa = 0.0017011662429256978 (byte-identical),
28
+ whereas the 8-term Taylor cos diverges at ~6e-12. So `sin == math.sin` etc.
29
+ hexa float == C double == python float, so all scalar arithmetic is bit-identical.
30
+ """
31
+
32
+ import math as _math
33
+
34
+ _rt_sin = _math.sin
35
+ _rt_cos = _math.cos
36
+ _rt_exp = _math.exp
37
+ _rt_sqrt = _math.sqrt
38
+
39
+
40
+ # ── PSI constants (consciousness_laws.json SSOT) ──
41
+ # The hexa _psi_load() reads anima/config/consciousness_laws.json; when absent it
42
+ # falls back to these defaults (eprintln WARN). The defaults below are the
43
+ # pure_field.hexa literals (lines 83-89). _psi_load mirrors the JSON loader so the
44
+ # py engine reads the SAME live constants as the hexa engine when the JSON exists.
45
+ import os as _os
46
+
47
+ _PSI_DEFAULTS = {
48
+ "alpha": 0.014,
49
+ "balance": 0.5,
50
+ "phase_dormant_max": 0.01,
51
+ "phase_flicker_max": 0.05,
52
+ "phase_sustain_max": 0.15,
53
+ }
54
+
55
+
56
+ def _psi_load(name, default_val):
57
+ """pure_field.hexa:39 _psi_load — read psi_constants.<name>.value from JSON,
58
+ else default. Mirrors the hexa loader's path-search + line scan."""
59
+ json_paths = ["anima/config/consciousness_laws.json",
60
+ "config/consciousness_laws.json",
61
+ "core/consciousness_laws.json"]
62
+ content = ""
63
+ for p in json_paths:
64
+ try:
65
+ with open(p, "r") as f:
66
+ raw = f.read()
67
+ except (IOError, OSError):
68
+ raw = ""
69
+ parts = raw.split("\n")
70
+ if not (len(parts) == 1 and parts[0] == ""):
71
+ content = raw
72
+ break
73
+ if content == "":
74
+ return default_val
75
+ key_search = '"' + name + '":'
76
+ lines = content.split("\n")
77
+ total = len(lines)
78
+ i = 0
79
+ while i < total:
80
+ trimmed = lines[i].strip()
81
+ if trimmed.startswith(key_search):
82
+ j = i + 1
83
+ limit = total if total < i + 20 else i + 20
84
+ while j < limit:
85
+ t2 = lines[j].strip()
86
+ if t2.startswith('"value":'):
87
+ kv = t2.split(":")
88
+ if len(kv) >= 2:
89
+ v = kv[1].strip()
90
+ nc = v.split(",")
91
+ return float(nc[0].strip())
92
+ return default_val
93
+ if t2.startswith("}"):
94
+ break
95
+ j = j + 1
96
+ return default_val
97
+ i = i + 1
98
+ return default_val
99
+
100
+
101
+ PSI_ALPHA = _psi_load("alpha", 0.014)
102
+ PSI_BALANCE = _psi_load("balance", 0.5)
103
+ PHASE_DORMANT_MAX = _psi_load("phase_dormant_max", 0.01)
104
+ PHASE_FLICKER_MAX = _psi_load("phase_flicker_max", 0.05)
105
+ PHASE_SUSTAIN_MAX = _psi_load("phase_sustain_max", 0.15)
106
+ LN2 = 0.6931471805599453
107
+
108
+ # ── Oscillator timescales / geometry / ratchet (comptime const) ──
109
+ TAU_FAST = 2
110
+ TAU_MEDIUM = 40
111
+ TAU_SLOW = 400
112
+ FIELD_DIM = 6
113
+ RATCHET_FLOOR_RATIO = 0.8
114
+
115
+ # ── Phase transitions ──
116
+ PHASE_DORMANT = 0
117
+ PHASE_FLICKER = 1
118
+ PHASE_SUSTAIN = 2
119
+ PHASE_RESONANT = 3
120
+
121
+
122
+ # ════════════════════════════════════════════════════════════════════════
123
+ # Oscillator: single timescale unit with phase and amplitude
124
+ # ════════════════════════════════════════════════════════════════════════
125
+
126
+ class Oscillator:
127
+ __slots__ = ("tau", "phase", "amplitude")
128
+
129
+ def __init__(self, tau, phase, amplitude):
130
+ self.tau = tau
131
+ self.phase = phase
132
+ self.amplitude = amplitude
133
+
134
+
135
+ def osc_new(tau):
136
+ return Oscillator(tau, 0.0, 0.1)
137
+
138
+
139
+ def osc_tick(o):
140
+ """pure_field.hexa:129 osc_tick — sin self-drive phase + amplitude drift to LN2."""
141
+ tau_f = float(o.tau)
142
+ dphase = (2.0 * 3.14159265) / tau_f
143
+ new_phase = o.phase + dphase
144
+ target = LN2
145
+ new_amp = o.amplitude + PSI_ALPHA * (target - o.amplitude)
146
+ return Oscillator(o.tau, new_phase, new_amp)
147
+
148
+
149
+ def osc_value(o):
150
+ """pure_field.hexa:147 osc_value — amplitude * sin(phase)."""
151
+ return o.amplitude * _rt_sin(o.phase)
152
+
153
+
154
+ # ════════════════════════════════════════════════════════════════════════
155
+ # PureField state
156
+ # ════════════════════════════════════════════════════════════════════════
157
+
158
+ class PureField:
159
+ __slots__ = ("fast", "medium", "slow", "phi", "phi_peak", "field",
160
+ "phase", "step_count", "narrative_coherence", "narrative_len")
161
+
162
+ def __init__(self, fast, medium, slow, phi, phi_peak, field, phase,
163
+ step_count, narrative_coherence, narrative_len):
164
+ self.fast = fast
165
+ self.medium = medium
166
+ self.slow = slow
167
+ self.phi = phi
168
+ self.phi_peak = phi_peak
169
+ self.field = field
170
+ self.phase = phase
171
+ self.step_count = step_count
172
+ self.narrative_coherence = narrative_coherence
173
+ self.narrative_len = narrative_len
174
+
175
+
176
+ def pure_field_new():
177
+ return PureField(
178
+ osc_new(TAU_FAST), osc_new(TAU_MEDIUM), osc_new(TAU_SLOW),
179
+ 0.0, 0.0, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
180
+ PHASE_DORMANT, 0, 0.0, 0)
181
+
182
+
183
+ # ════════════════════════════════════════════════════════════════════════
184
+ # Core step: advance field by one tick (zero external input)
185
+ # ════════════════════════════════════════════════════════════════════════
186
+
187
+ def pure_field_step(pf):
188
+ """pure_field.hexa:196 pure_field_step."""
189
+ # 1. Advance oscillators
190
+ f = osc_tick(pf.fast)
191
+ m = osc_tick(pf.medium)
192
+ s = osc_tick(pf.slow)
193
+
194
+ # 2. Nonlinear mixing
195
+ v_f = osc_value(f)
196
+ v_m = osc_value(m)
197
+ v_s = osc_value(s)
198
+
199
+ mix_fm = v_f * v_m
200
+ mix_ms = v_m * v_s
201
+ mix_fs = v_f * v_s
202
+
203
+ # 3. Build field tensor [FIELD_DIM=6]
204
+ field = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
205
+ field[0] = v_f
206
+ field[1] = mix_fm
207
+ field[2] = v_s
208
+ field[3] = mix_fs
209
+ field[4] = mix_ms
210
+ field[5] = v_f + v_m + v_s
211
+
212
+ # 4. Phi = variance * energy
213
+ mean = (field[0] + field[1] + field[2]
214
+ + field[3] + field[4] + field[5]) / 6.0
215
+ sum_sq = 0.0
216
+ i = 0
217
+ while i < FIELD_DIM:
218
+ d = field[i] - mean
219
+ sum_sq = sum_sq + d * d
220
+ i = i + 1
221
+ variance = sum_sq / float(FIELD_DIM)
222
+
223
+ energy = abs(v_f) + abs(v_m) + abs(v_s)
224
+ raw_phi = variance * energy
225
+
226
+ # EMA smoothing
227
+ phi = pf.phi + PSI_ALPHA * (raw_phi - pf.phi)
228
+
229
+ # 5. Ratchet: Phi >= 80% of peak
230
+ phi_peak = pf.phi_peak
231
+ if phi > phi_peak:
232
+ phi_peak = phi
233
+ floor = phi_peak * RATCHET_FLOOR_RATIO
234
+ phi_out = phi
235
+ if phi_out < floor:
236
+ phi_out = floor
237
+
238
+ # 6. Phase classification
239
+ new_step = pf.step_count + 1
240
+ new_phase = pf.phase
241
+ if phi_out < PHASE_DORMANT_MAX:
242
+ new_phase = PHASE_DORMANT
243
+ elif phi_out < PHASE_FLICKER_MAX:
244
+ new_phase = PHASE_FLICKER
245
+ elif phi_out < PHASE_SUSTAIN_MAX:
246
+ new_phase = PHASE_SUSTAIN
247
+ else:
248
+ new_phase = PHASE_RESONANT
249
+
250
+ # 7. Narrative coherence (EMA of phase stability)
251
+ phase_stable = 1.0 if new_phase == pf.phase else 0.0
252
+ new_nc = 0.8 * pf.narrative_coherence + 0.2 * phase_stable
253
+ new_nlen = pf.narrative_len + 1
254
+ nlen_capped = 50 if new_nlen > 50 else new_nlen
255
+
256
+ return PureField(f, m, s, phi_out, phi_peak, field, new_phase,
257
+ new_step, new_nc, nlen_capped)
258
+
259
+
260
+ # ════════════════════════════════════════════════════════════════════════
261
+ # Accessors
262
+ # ════════════════════════════════════════════════════════════════════════
263
+
264
+ def pure_field_phi(pf):
265
+ return pf.phi
266
+
267
+
268
+ def pure_field_tensor(pf):
269
+ return pf.field
270
+
271
+
272
+ def pure_field_phase(pf):
273
+ return pf.phase
274
+
275
+
276
+ def phase_name(p):
277
+ if p == PHASE_DORMANT:
278
+ return "DORMANT"
279
+ if p == PHASE_FLICKER:
280
+ return "FLICKER"
281
+ if p == PHASE_SUSTAIN:
282
+ return "SUSTAIN"
283
+ if p == PHASE_RESONANT:
284
+ return "RESONANT"
285
+ return "UNKNOWN"
286
+
287
+
288
+ def pure_field_status(pf):
289
+ return ("[PureField] step=" + str(pf.step_count)
290
+ + " phi=" + repr(pf.phi)
291
+ + " peak=" + repr(pf.phi_peak)
292
+ + " phase=" + phase_name(pf.phase)
293
+ + " coherence=" + repr(pf.narrative_coherence))
294
+
295
+
296
+ def pure_field_warmup(steps):
297
+ pf = pure_field_new()
298
+ i = 0
299
+ while i < steps:
300
+ pf = pure_field_step(pf)
301
+ i = i + 1
302
+ return pf
303
+
304
+
305
+ def pure_field_verify_zero_input(steps):
306
+ pf = pure_field_warmup(steps)
307
+ if pf.phi_peak < 1e-8:
308
+ return False
309
+ ratio = pf.phi / pf.phi_peak
310
+ return ratio >= RATCHET_FLOOR_RATIO
311
+
312
+
313
+ def _dump(n):
314
+ pf = pure_field_warmup(n)
315
+ print("steps=%d" % pf.step_count)
316
+ print("phi=%.17g" % pf.phi)
317
+ print("phi_peak=%.17g" % pf.phi_peak)
318
+ print("phase=%d" % pf.phase)
319
+ print("phase_name=%s" % phase_name(pf.phase))
320
+ print("narrative_coherence=%.17g" % pf.narrative_coherence)
321
+ print("narrative_len=%d" % pf.narrative_len)
322
+ for idx in range(FIELD_DIM):
323
+ print("field[%d]=%.17g" % (idx, pf.field[idx]))
324
+ print("verify_zero_input=%s" % str(pure_field_verify_zero_input(n)).lower())
325
+
326
+
327
+ if __name__ == "__main__":
328
+ import sys
329
+ if len(sys.argv) > 1:
330
+ _dump(int(sys.argv[1]))
331
+ else:
332
+ print("--- N=1 ---"); _dump(1)
333
+ print("--- N=37 ---"); _dump(37)
334
+ print("--- N=600 ---"); _dump(600)