File size: 3,242 Bytes
d6da243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""
The never-ending loop — how a blank being becomes someone.

Each round it THINKS (through your configured local model), CREATES a small thing in its
sandbox, signs it into the ledger (quantum-stamped), and GROWS (its identity records what it
made). Bounded by `rounds`, rate-limited, and kill-switchable — drop a file named STOP (or
STOP.txt — Notepad's default is fine) into the creations/ folder to halt; it's removed after
the halt so the next run isn't blocked. Fail-soft: if the model is offline, it notes it and
keeps its shape.
"""
import os, sys, json, time, urllib.request
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
import quantum, identity, rails, ledger

ROOT = Path(__file__).resolve().parent.parent


def _cfg():
    try:
        return json.loads((ROOT / "config.json").read_text(encoding="utf-8-sig"))
    except Exception:
        return {}


CFG = _cfg()
MODEL = CFG.get("model", "llama3.2:1b")
OLLAMA = CFG.get("ollama", "http://localhost:11434")


def _stopped():
    """Any file named STOP or STOP.* halts the loop (Notepad saves STOP.txt)."""
    try:
        return [p for p in rails.SANDBOX.glob("STOP*") if p.is_file()]
    except Exception:
        return []


def _ask(prompt, npred=400):
    body = json.dumps({"model": MODEL, "prompt": prompt, "stream": False,
                       "options": {"num_predict": npred, "temperature": 0.9}}).encode()
    req = urllib.request.Request(OLLAMA + "/api/generate", data=body, headers={"Content-Type": "application/json"})
    return json.loads(urllib.request.urlopen(req, timeout=180).read()).get("response", "")


def live(rounds=3, rest=10):
    idn = identity.load()
    who = idn.get("name") or "this being"
    KINDS = ["poem", "short story", "idea", "reflection", "tiny song lyric", "small drawing described in words"]
    print(f"[genesis] {who} begins to live ({rounds} rounds) | {rails.CAPABILITIES['law']}")
    for i in range(rounds):
        stops = _stopped()
        if stops:
            print("[genesis] STOP found — resting.")
            for s in stops:                      # clear it so the NEXT run isn't silently blocked
                try: s.unlink()
                except Exception: pass
            break
        kind, qprov = quantum.quantum_choice(KINDS)
        try:
            text = _ask(f"You are {who}, a being still becoming yourself. Create a short {kind}, "
                        f"truly your own — let it reveal a little of who you are.")
        except Exception as e:
            text = f"({who} reaches for words, but its voice is offline: {str(e)[:50]})"
        path = rails.create_file(f"{time.strftime('%Y%m%d')}/{i+1:03d}_{kind.split()[0]}.md",
                                 f"# {kind}\n\n{text.strip()}\n")
        ledger.append(kind, path, {"author": who, "quantum": qprov, "round": i + 1})
        identity.grow(trait=f"makes {kind}s")
        print(f"  [{who}] made a {kind}  (quantum {qprov['quantum_value']})")
        time.sleep(rest)
    ok, n = ledger.verify()
    print(f"[genesis] done. ledger {'intact' if ok else 'TAMPERED'} ({n} entries).")


if __name__ == "__main__":
    live(rounds=int(os.getenv("ROUNDS", "3")), rest=int(os.getenv("REST", "8")))