File size: 3,772 Bytes
6b09b49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""Scripted demo / integration test β€” the Day-4/5 dry run, in code.

Runs a curated job sequence through the REAL loop (advise β†’ Spine β†’ reflect) on
a fresh seeded ledger and prints a readable transcript. It exists to (a) expose
demo-path bugs early β€” the step Kaggle never reached β€” and (b) be the source of
truth for the video beats: precedent applied, environment-driven shift, and the
"no close precedent" discrimination case.

Works offline (deterministic fallback) and gets richer with real Ollama.
Run: `make demo`  (or `uv run python -m scripts.scripted_demo`)
"""

from __future__ import annotations

import sys
import tempfile
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))  # repo root on path

from core.chief_engineer import advise
from core.ledger import LedgerManager
from core.models import Environment, Job, PrintSettings
from core.reflect import reflect_on_job
from core.seed_lessons import ensure_seeded
from core.spine import SpineValidator

SPINE = SpineValidator()

# (job, env, beat, outcome-to-record) β€” designed to make compounding legible.
SCENARIOS = [
    (Job(geometry_type="overhang", material="PLA", description="45Β° bracket, 60mm tall"),
     Environment(temp=28, humidity=50),
     "Warm room β€” should match the prior PLA overhang that SAGGED at 28Β°C.",
     "failed_sag"),
    (Job(geometry_type="overhang", material="PLA", description="same bracket, cooler day"),
     Environment(temp=23, humidity=40),
     "Cooler/drier β€” recommendation should shift vs the warm run.",
     "success"),
    (Job(geometry_type="stringing", material="PETG", description="hex grid, lots of travel"),
     Environment(temp=25, humidity=65),
     "Humid PETG β€” precedent should suspect MOISTURE, not just retraction.",
     "success"),
    (Job(geometry_type="vase", material="TPU", description="flexible spiral vase"),
     Environment(temp=22, humidity=45),
     "NOVEL: no TPU/vase precedent β€” expect 'no close precedent' reasoning.",
     None),
]


def _rule(label: str) -> None:
    print(f"\n{'─' * 70}\n{label}\n{'─' * 70}")


def run() -> None:
    led = LedgerManager(Path(tempfile.mkdtemp()) / "lessons.jsonl")
    print(f"seeded {ensure_seeded(led)} lessons Β· ledger={led.count()}")

    for i, (job, env, beat, outcome) in enumerate(SCENARIOS, 1):
        _rule(f"JOB {i}: {job.material}/{job.geometry_type} @ {env.temp:.0f}Β°C/{env.humidity:.0f}% RH")
        print(f"  beat β†’ {beat}")

        retrieved = led.retrieve(job.material, job.geometry_type, env.temp, env.humidity)
        if retrieved:
            print("  precedent:")
            for e, d in retrieved:
                print(f"    β€’ {e.job_id} ({e.source}) {e.outcome}  dist={d:.2f}")
        else:
            print("  precedent: (none β€” novel situation)")

        rec = advise(job, env, retrieved)
        s = rec.advice.settings
        spine = SPINE.check(s, job.material)
        print(f"  backend: {rec.backend}{' [fallback]' if rec.used_fallback else ''}")
        print(f"  reasoning: {rec.advice.reasoning}")
        print(f"  settings: nozzle={spine.settings.nozzle_temp:.0f} bed={spine.settings.bed_temp:.0f} "
              f"retr={spine.settings.retraction_mm:.1f} fan={spine.settings.fan_pct:.0f}%")
        if spine.vetoes:
            print("  πŸ›‘ spine:", "; ".join(spine.vetoes))
        for r in rec.advice.risks:
            print(f"  ⚠ risk: {r.risk} @ {r.location} β€” {r.why}")

        if outcome:
            entry = reflect_on_job(job, env, spine.settings, outcome, led)
            print(f"  πŸ“’ recorded ({outcome}) β†’ earned: {entry.lesson}")

    print(f"\nFINAL LEDGER: {led.count()}  (knowledge compounded across the run)")


if __name__ == "__main__":
    run()