Dieses Paket vertieft am realen System, was die veröffentlichte Seite „KI steuert lokale Hardware über eine Brücke" exemplarisch zeigt. Ein KI-Agent mit eigenem Sprachmodell richtet auf einem Windows-Rechner Python ein, schreibt ein Programm für einen ESP32, überspielt es — und entfernt sich danach restlos. Alles läuft aus einem Ordner, vom Stick oder von der Festplatte. Nichts wird installiert, kein Netz wird gebraucht, keine Adminrechte.
Nicht nur für den ESP32: Der Agent schreibt auf Anforderung jedes Python-Programm — einen Taschenrechner mit Fenster (tkinter liegt im Paket), ein Skript, das rechnet — und führt es mit dem Paket-Python aus, bevor er es für fertig erklärt.
Die veröffentlichte Seite führt vor, wie eine KI über eine Brücke Hardware am Arbeitsplatz steuert. Dort sieht man zu. Hier hat man es selbst in der Hand: eigenes Modell, eigener ESP32, kein Netz, ein Ordner — derselbe Kreis aus Anforderung, Bau, Abnahme und Nachweis, nur dass jeder Schritt auf dem eigenen Rechner läuft und geprüft wird.
Dieses Paket zeigt an einem kleinen, vollständig laufenden Beispiel, wie Entwicklung mit einem Sprachmodell wirklich abläuft — nicht als Folienvortrag, sondern als Vorgang, den man anstoßen und zusehen kann. Es ist derselbe Ablauf, mit dem auch dieses Paket selbst entstanden ist, nur im kleinen Rahmen.
| Schritt | wer | warum er nicht wegfallen darf | |
|---|---|---|---|
| 1 | Anforderung | Mensch | Ein Satz auf Deutsch. Was nicht gesagt wurde, kann auch nicht geprüft werden. |
| 2 | Bau | Modell | Das Modell schreibt den Quelltext. Das ist der Teil, über den alle reden — und der kleinste. |
| 3 | Abnahme | Werkzeug | Das Programm läuft, und das Gemessene wird mit dem Angekündigten verglichen. Hier entscheidet sich alles. |
| 4 | Berichtigen | Modell | Fällt die Abnahme durch, geht es zurück zu 2 — mit der Fehlermeldung als Eingabe. |
| 5 | Auslieferung | Werkzeug | Erst nach bestandener Abnahme geht dieselbe Datei auf die Hardware. |
| 6 | Rücklesen | Werkzeug | Das Gerät selbst meldet, was blinkt: Pegel, Wechsel, Takt — gegen dieselbe Erwartung. Der zweite, unabhängige Weg. |
| 7 | Nachweis | Werkzeug | Was hat sich am Rechner geändert? Gemessen, nicht behauptet. |
Schritt 3 ist der eigentliche Inhalt des Kurses. Ein Sprachmodell schreibt in Sekunden ein Programm, das plausibel aussieht. Ob es tut, was verlangt war, steht damit nicht fest — und genau diese Lücke schließt kein besseres Modell, sondern eine Prüfung, die durchfallen kann.
Deshalb nimmt programm_testen eine Erwartung entgegen:
"erwartet": {"pins": [2], "takt_hz": 1.0}
Ohne diese Zeile ist der Lauf eine Vorführung: etwas blinkt, und niemand hat vorher gesagt, was hätte blinken sollen. Mit ihr ist es eine Abnahme.
Üblicherweise liegen die drei Teile auf drei Rechnern: das Sprachmodell bei einem Anbieter, der Agent auf einem Server, die Hardware am Arbeitsplatz — verbunden über eine Brücke. Hier sind alle drei derselbe Rechner.
| Teil | großer Aufbau | dieses Paket |
|---|---|---|
| Sprachmodell | beim Anbieter, über das Netz | llama-server auf 127.0.0.1 |
| Agent und Werkzeuge | auf einem Server | derselbe Rechner, Ordner agent\ |
| Hardware | am Arbeitsplatz, über eine Brücke | am selben USB-Anschluss |
Am Ablauf ändert das nichts — und das ist der Punkt. Wer ihn hier verstanden hat, hat ihn auch für den verteilten Fall verstanden; dort kommen Strecke und Rechteverwaltung dazu, nicht aber ein anderer Vorgang.
Die Anforderungen an dieses Paket stehen geschrieben, nicht im Kopf: ANFORDERUNGEN.md
führt 55 Punkte in neun Gruppen, jeder so gefasst, dass er scheitern kann, mit
der Angabe, woran er gemessen wird.
| Gruppe | Kern |
|---|---|
| A — Autarkie | Der Kursrechner hat Windows und sonst nichts. Das Paket bringt alles mit, sucht kein vorhandenes Python und benutzt auch keines. |
| B — keine Störung | Läuft dort schon Thonny oder ein eigenes Python, bleibt daran alles unberührt — auch Benutzerpakete, pip-Zwischenspeicher, PATH, Ports und COM-Anschlüsse. |
| C — nur im Kursordner | Geschrieben wird ausschließlich in ablage\, und das wird erzwungen, nicht gehofft. |
| D — restlos entfernbar | Ein Ordner, ein Befehl, danach wird nachgezählt. |
| E — Weitergabe | Derselbe Stick startet auf jedem Rechner; das Modell wird beim Start gewählt. |
| F — Bedienung | Doppelklick, anklicken, zusehen. Keine Kommandozeile. |
| G — der Lehrinhalt | Bauen, Abnahme gegen eine vorher genannte Zahl, berichtigen, erst dann ausliefern. |
| H — Hardware | Fabrikneu oder vorprogrammiert, mit oder ohne Treiber, mit oder ohne Steckbrett. |
| I — Ferndiagnose | Ein Befehl schreibt alles Nötige in eine Datei — ohne Benutzer- und Rechnernamen. |
python pruefe_alles.py
arbeitet die maschinell prüfbaren Punkte ab — derzeit 17 — und nennt, welche von Hand zu prüfen bleiben. Beim Schreiben dieses Prüfskripts fielen zwei eigene Fehler auf: eine Prüfung, die ihr Ergebnis behauptete statt es abzulesen, und eine, die „bestanden" meldete, obwohl der geprüfte Lauf gar nicht stattgefunden hatte.
Eine blinkende Leuchtdiode ist die kleinste Aufgabe, an der sich die ganze Kette zeigen lässt: sie ist in sechs Zeilen geschrieben, in vier Sekunden geprüft und am Ergebnis sieht man sofort, ob es stimmt. Aufgezeichnet wird aber jeder Anschluss — ein Programm mit drei Pins und verschiedenen Takten läuft genauso durch, ebenso Pulsweitenmodulation und Analogeingänge.
| Ordner | Inhalt | Eigenschaft |
|---|---|---|
paket\ | Python, pip, Pakete, MicroPython, llama.cpp, Sprachmodell, Treiber | wird nur gelesen — nie beschrieben |
agent\ | die Schleife, die Modellanbindung, neun Werkzeuge | der Programmteil, rund 60 kB |
ablage\ | das entpackte Python, installierte Pakete, erzeugte Dateien, Protokoll | wird am Ende restlos gelöscht |
Diese Trennung ist das ganze Sicherheitskonzept. Geschrieben wird
ausschließlich in ablage\; das erzwingt der Werkzeugrahmen, indem er jeden
Schreibpfad auflöst und prüft, bevor eine Datei entsteht. Deshalb ist das Aufräumen
ein Beweis und keine Behauptung: es löscht genau einen Ordner und zählt hinterher nach.
| Teil | Datei | Größe | wofür |
|---|---|---|---|
| Python, ausgepackt | python_vorlage\ | 22 MB | wird kopiert, nicht installiert — dies ist der Weg, den START.bat geht |
| Python als Archiv | python-3.12.10-embed-amd64.zip | 11,1 MB | Rückfall, falls die Vorlage fehlt. Wird nur entpackt, nie installiert |
| pip | get-pip.py | 2,2 MB | richtet die Paketverwaltung im entpackten Python ein |
| Python-Pakete | pakete\ — 25 Dateien | 8,4 MB | esptool und mpremote samt allem, was dazugehört |
| MicroPython | firmware\*.bin | 1,8 MB | die Firmware für den ESP32 |
| llama.cpp | llama\llama-server.exe | 95 MB | führt das Sprachmodell aus |
| Sprachmodell | modell\*.gguf | 1,0–4,7 GB | entscheidet, welches Werkzeug wann läuft |
| USB-Treiber | treiber\*.zip | 1,4 MB | falls Windows den Wandler nicht kennt |
Ohne Modell sind das 137 MB; mit dem mittleren Modell (3b) rund 2,1 GB, und mit beiden Modellen — so wird der Stick gebaut — rund 6,8 GB.
Die folgenden Zahlen sind gemessen, nicht geschätzt: am laufenden Paket,
mit ps am Modellserver abgelesen, auf einem Rechner mit 20 Kernen ohne
Grafikbeschleunigung.
| Modell | Datei | Speicher gemessen | braucht RAM | Ladezeit | Urteil aus dem Prüflauf |
|---|---|---|---|---|---|
1.5b | 0,99 GB | 2,2 GB | 4 GB | ~1 s | zeigt die Schleife, scheitert an mehrstufigen Aufträgen |
3b | 1,93 GB | 3,48 GB | 8 GB | 2–3 s | schreibt brauchbare Programme, verliert aber den Faden und ruft Werkzeuge in falscher Reihenfolge; Rückfall |
7b | 4,68 GB | 6,70 GB | 16 GB | 5–6 s | hält die Kette ein, berichtigt eigene Fehler — Rückfall, wenn kein Coder-Modell da ist |
coder-3bcoder-7b| Sonst | |
|---|---|
| Betriebssystem | Windows 10 oder 11, 64 bit. Keine Adminrechte, außer für einen USB-Treiber |
| Prozessor | vier Kerne aufwärts. Im Prüflauf lagen 500 % Last an — das Modell nimmt, was da ist |
| Platz | 200 MB ohne Modell, 2,2 GB mit dem 3B-, 5,0 GB mit dem 7B-Modell |
| Grafik | keine nötig. Mit Vulkan (AMD, Intel, NVIDIA) wird es schneller, ohne rechnet llama.cpp auf dem Hauptprozessor weiter |
| Netz | einmal zum Füllen des Pakets. Im Kurs nie |
Gemessener Prüflauf (7B-Modell, 20 Kerne, keine Grafik): fünf Werkzeugaufrufe in 2 Minuten 48 Sekunden, davon der größte Teil Wartezeit auf das Modell — rund 15 bis 25 Sekunden je Antwort. Auf vier Kernen ist mit dem Mehrfachen zu rechnen; dann lohnt das 3B-Modell trotz seiner Schwächen.
Diesen Rechner selbst messen lassen:
python pruefe_rechner.py
Es nennt Arbeitsspeicher, Kerne, freien Platz und Grafik, hält sie gegen die Tabelle oben und empfiehlt ein Modell — oder sagt, dass keines passt.
Ohne Sprachmodell läuft weiterhin alles andere: die neun Werkzeuge, der Prüfschritt mit Abnahme, die virtuelle LED, das Flashen, der Nachweis und das Aufräumen. Dafür genügen Windows und 200 MB. Nur die Entscheidung, welches Werkzeug wann läuft, trifft dann ein festes Drehbuch statt eines Modells.
Jedes ist ein eigenständiges Programm mit genau zwei Betriebsarten:
--beschreibung sagt als JSON, was es kann; '<json>' führt es aus.
Mehr Verbindung zwischen Modell und Werkzeug gibt es nicht — deshalb lässt sich jedes ohne
Modell von Hand prüfen, und genau das ist Menüpunkt [2].
| Name | was es tut | Felder |
|---|---|---|
aufraeumen | Loescht alles, was im Lauf angelegt wurde: das eigene Python, die installierten Pakete und die erzeugten Dateien. Zaehlt danach nach, dass nichts zurueckblieb. Am Ende der Arbeit aufrufen. | nur_zeigen |
esp32_firmware | Spielt MicroPython auf den ESP32 am angegebenen Anschluss. Prueft zuerst, ob dort ueberhaupt ein ESP32 antwortet, und schreibt nur dann. Einmal je Geraet noetig, bevor Python-Programme uebertragen werden koennen. Mit nur_pruefen: true sagt es, was auf dem Brett schon ist — fabrikneu, fremdes Programm oder bereits MicroPython — und schreibt nichts. | port, nur_pruefen |
esp32_nachlesen | Liest vom ESP32 zurueck, ob die LED wirklich blinkt: startet das Programm auf dem Geraet und zeichnet dort die Pegel der Anschluesse auf. Takt und Wechsel werden gegen die Erwartung gehalten (ABNAHME) — die Messung am Geraet, unabhaengig von programm_testen. Setzt voraus, dass esp32_uebertragen gelaufen ist. | port, datei, sekunden, pwm, roh, erwartet |
esp32_uebertragen | Kopiert eine Datei aus der Werkstatt auf den ESP32 und startet ihn neu. Standardziel ist main.py, denn MicroPython fuehrt diese Datei nach dem Einschalten selbsttaetig aus. Setzt voraus, dass esp32_firmware bereits gelaufen ist. | port, datei, ziel, erwartet |
nachweis_autark | Nimmt den Zustand der Stellen ausserhalb des Paketordners auf ('vorher') und vergleicht ihn spaeter ('nachher'). Damit laesst sich belegen statt behaupten, dass der Rechner unveraendert bleibt. Vor der Arbeit und vor dem Aufraeumen aufrufen. | wann |
paket_installieren | Installiert ein Python-Paket in die eigene Umgebung in der Ablage. Erlaubt sind nur: esptool, mpremote, pyserial, setuptools, wheel. Fuer den ESP32 wird esptool gebraucht. | paket |
ports_zeigen | Zeigt alle seriellen Anschluesse (COM-Ports) des Rechners und markiert, welcher nach einem USB-Seriell-Wandler eines ESP32 aussieht. Vor dem Flashen aufrufen. | — |
programm_ausfuehren | Fuehrt ein beliebiges Python-Programm aus der Werkstatt mit dem Paket-Python aus — fuer alles, was kein ESP32-Programm ist (Rechner, Skripte, Programme mit Fenster). Berichtet Ausgabe, Fehler und Rueckgabewert; Urteil LAUF BESTANDEN / NICHT BESTANDEN. Mit fenster true wird ein Programm mit grafischer Oberflaeche (tkinter) gestartet und beobachtet, ob es laeuft und ein Fenster zeigt. | datei, sekunden, fenster, offen_lassen, eingabe |
programm_testen | Fuehrt ein Programm aus der Werkstatt ohne Hardware aus und zeichnet auf, was an den Anschluessen geschieht; eine LED auf dem Bildschirm zeigt es an. IMMER aufrufen, nachdem ein Programm geschrieben wurde und BEVOR es auf den ESP32 ueberspielt wird — ein Programm, das hier nicht laeuft, laeuft dort auch nicht. Ersetzt zugleich die Hardware, wenn keine da ist. | datei, sekunden, oeffnen, erwartet |
schreib_datei | Schreibt eine Textdatei in die Werkstatt, zum Beispiel den Quelltext fuer den ESP32. Vorhandene Dateien werden ersetzt. Ausserhalb der Ablage kann nicht geschrieben werden. | name, inhalt |
umgebung_anlegen | Richtet ein eigenes, eingebettetes Python samt pip in der Ablage ein. Installiert nichts im System: es wird nur entpackt und spaeter wieder geloescht. Muss vor paket_installieren und esp32_flashen laufen. | neu |
Diese Tabelle ist nicht abgeschrieben, sondern beim Erzeugen der Seite von den Werkzeugen selbst erfragt. Eine abgeschriebene Tabelle stimmt genau bis zur ersten Änderung.
umgebung_anlegen entpackt Python muss zuerst laufen
└─ paket_installieren esptool, mpremote braucht das Python von oben
├─ ports_zeigen welcher Anschluss? braucht pyserial
└─ esp32_firmware MicroPython aufs Gerät braucht esptool
schreib_datei das Programm entsteht
└─ programm_testen Abnahme ohne Hardware ← hier wird entschieden
└─ esp32_uebertragen dieselbe Datei aufs Gerät braucht mpremote
└─ esp32_nachlesen misst am Gerät, ob es blinkt braucht mpremote
nachweis_autark vorher / nachher
aufraeumen löscht die Ablage, zählt nach
Die Reihenfolge erfindet nicht der Agent, sondern sie ergibt sich: jedes Werkzeug sagt in
seiner Fehlermeldung, was ihm fehlt. Ruft das Modell ports_zeigen zu früh, bekommt
es „Es gibt noch kein eigenes Python. Zuerst umgebung_anlegen aufrufen" — und tut
genau das. So braucht es keinen festen Ablaufplan.
agent\werkzeuge\_muster.py nimmt den Rahmen ab. Eine neue Datei im Ordner
genügt — der Agent findet sie beim nächsten Start, weil er die Liste nicht führt, sondern
erfragt.
from _muster import werkzeug, Abbruch, lauf
def tun(e):
return f"Ergebnis zu {e['feld']}"
werkzeug("mein_werkzeug", "Was es tut und wann man es ruft.",
{"feld": {"type": "string", "description": "wofür"}},
["feld"], {"feld": "Probe"}, tun)
C:\Kurs_Agent. Laufwerksbuchstabe und Name sind beliebig — im ganzen
Paket steht kein fester Pfad.START.bat — auch beim ersten Mal. Ist das Paket
noch leer, sagt das Skript genau das und holt alles selbst: rund 6,8 GB — Python, pip, 25
Pakete, MicroPython, llama.cpp, Treiber und zwei Sprachmodelle (3b und 7b). Zehn bis dreißig
Minuten, je nach Leitung. Danach läuft es weiter, als wäre gerade gestartet worden.
Für diesen einen Schritt — und nur für ihn — wird ein
vorhandenes Python mit pip gebraucht. Der Grund ist einfach: im leeren Paket liegt
noch keines. START.bat sucht eines, prüft ob darin pip läuft, nennt es beim
Namen und fragt nach, bevor etwas geholt wird. Selbst dabei bleibt der Rechner unberührt —
pip-Zwischenspeicher und Benutzerpakete zeigen in den Kursordner, nicht ins Profil.
Danach wird dieses Python nie wieder angefasst: der ganze Kursbetrieb läuft mit dem Python
aus dem Paket.
Wird keines gefunden, nennt das Skript zwei Wege — Python von python.org installieren, oder den gefüllten Ordner von einem anderen Rechner kopieren. Der zweite ist der gedachte: füllen einmal, weitergeben beliebig oft. Auf dem Kursrechner ist nie ein fremdes Python nötig.
START.bat. Es sucht kein
vorhandenes Python — weder im PATH noch dort, wo Windows oder Thonny eines ablegen. Es kopiert
sein eigenes aus paket\python_vorlage\ nach ablage\python\
und arbeitet nur mit diesem. Was auf dem Rechner schon installiert ist, wird nicht gestartet,
nicht gelesen und nicht verändert.[1] Installieren und starten — die Eingabetaste. Mehr fragt
START.bat nicht. Es prüft den Stand des Pakets („Paket: … vollständig"), und
fehlt etwas, holt es das Fehlende von selbst — zuerst aus dem Vorrat (ein
Paket nebenan, ein Stick unter X:\Kurs_Agent, der Download-Ordner), erst dann
aus dem Netz. Liegt irgendwo ein volles Paket, braucht es gar kein Netz.python baue_stick.py E:\Kurs_Agent — nimmt mit, was zum Betrieb gehört, lässt
weg, was beim Entwickeln entsteht, und meldet von selbst, wenn das Modell fehlt.START.bat doppelklicken.| Wahl | was sie bedeutet |
|---|---|
| [1] Installieren und starten | legt das eigene Python bereit, prüft das Paket, holt Fehlendes, öffnet den Agenten im Browser. Das ist der Normalfall — die Eingabetaste genügt. |
| [2] Deinstallieren | zeigt erst den Nachweis, was sich am Rechner verändert hat (nichts), und entfernt dann alles, was der Agent angelegt hat. Das Paket selbst bleibt. |
| [3] Abbrechen | nichts geschieht. |
Wer mehr will — Werkzeuge einzeln prüfen, der Agent ohne Browser,
der Weg ohne Modell, ein Bericht zum Weitergeben —, startet START.bat --menue.
Der Weg „auf die Platte kopieren, danach selbst löschen" heißt START.bat --kopieren.
Paket: … vollständig — jeder Teil ist
da. Und Smart App Control: … — steht dort EIN, lässt dieser Rechner nur
signierte Programme laufen. Der mitgelieferte Modellserver ist signiert (Ollama Inc./DigiCert) und
läuft trotzdem; am 04.10.2026 auf einem solchen Rechner gemessen. Sollte das Modell dennoch nicht
starten, sagt der Agent das im Browser in Worten und läuft ohne Modell weiter:
dieselben Werkzeuge, dieselbe Abnahme, die virtuelle LED — die Entscheidungen trifft ein festes
Drehbuch.Nach [1] öffnet sich der Browser. Oben der Kopf (Ordner, Modell, Zustand), unten
immer das Eingabefeld, dazwischen der Verlauf. Sie sagen dem Agenten, was er tun soll — mit
einem Satz oder einem der Vorschläge —, sehen jeden Schritt mit und geben danach die nächste
Anweisung. Der Agent behält den Zusammenhang: „Nimm jetzt GPIO 4", „ändere auf 10 Hz", „lade es
auf den ESP32 an COM3 und lies nach, ob die LED blinkt" oder ein eigenes Programm in
```-Zeichen zum Prüfen. Im schwarzen Fenster steht derweil, was der Agent tut;
Strg+C dort beendet ihn.
Das ist der häufigere Fall und der eigentlich interessante. Hier der Auszug aus einem
Prüflauf, wörtlich aus dem Protokoll — das Modell schrieb time.sleep(1) für
beide Pausen, was eine Periode von zwei Sekunden ergibt:
[2] programm_testen {"datei": "blink.py", "erwartet": {"pins": [2], "takt_hz": 1.0}}
ABNAHME NICHT BESTANDEN
Anschluesse: erwartet [2], gemessen [2] erfuellt
Takt: erwartet 1.00 Hz, gemessen 0.50 Hz (Spielraum 10 %) NICHT ERFUELLT
Zustandswechsel: erwartet mindestens 6, gemessen 7 erfuellt
NAECHSTER SCHRITT: Rufe schreib_datei mit berichtigtem Quelltext auf. Dasselbe
Programm noch einmal zu pruefen aendert nichts am Ergebnis. [...] Bei einem Takt:
eine Blinkperiode besteht aus zwei Pausen, also ergibt time.sleep(0.5) +
time.sleep(0.5) genau 1 Hz.
[3] schreib_datei {"name": "blink.py", ...}
[4] schreib_datei {"name": "blink.py", ...}
[5] programm_testen {"datei": "blink.py", ...}
ABNAHME BESTANDEN
Takt: erwartet 1.00 Hz, gemessen 1.00 Hz (Spielraum 10 %) erfuellt
=== fertig nach 5 Werkzeugaufrufen ===
Das ist der Kurs in acht Zeilen. Das Modell hat ein plausibles Programm geschrieben, das nicht tat, was verlangt war. Kein Mensch hat den Fehler gefunden, sondern eine Messung gegen eine vorher genannte Zahl. Danach hat das Modell selbst berichtigt.
Ein Agent, der diesen Schritt nicht hat, liefert dasselbe falsche Programm aus — mit der Meldung, alles sei in Ordnung.
[1] Agent starten. Die Eingabetaste nimmt den
vorgegebenen Auftrag. Das Modell lädt beim ersten Mal 10 bis 60 Sekunden.[3] Aufräumen. Zeigt erst den Nachweis — was hat sich
außerhalb des Ordners verändert? — und löscht dann die Ablage, mit Nachzählung.Wenn das Modell klemmt: Menüpunkt
[7] Ohne Modell durchlaufen macht dieselben Schritte in fester Reihenfolge, mit
denselben Werkzeugen und derselben Abnahme. Der Kurs läuft dann weiter; nur die
Entscheidungen trifft das Drehbuch statt des Modells.
Beide Male derselbe Auftrag, dasselbe Modell, dieselben Werkzeuge. Der Unterschied ist nur, ob ein Steckbrett am USB-Anschluss hängt.
Auftrag im Menüpunkt [3]:
Schreibe ein MicroPython-Programm, das die LED an GPIO 2 einmal je Sekunde
blinken lässt. Prüfe es ohne Hardware gegen diese Erwartung, und wenn es
besteht, spiele es auf den ESP32.
Was dann der Reihe nach geschieht — die Zeilen sind die wirklichen Ausgaben der Werkzeuge:
[1] umgebung_anlegen {}
Python-Archiv: mitgeliefert (python-3.12.10-embed-amd64.zip, 11133606 Byte)
entpackt nach ...\ablage\python
python312._pth: 'import site' freigeschaltet
pip eingerichtet
Gegenprobe: pip 25.x from ...\ablage\python\Lib\site-packages\pip
[2] paket_installieren {"paket": "esptool"}
esptool installiert aus mitgelieferten Dateien in ...\paket\pakete
Ziel: ...\ablage\python (nicht das Python des Rechners)
Gegenprobe: import esptool -> Fassung 5.4.0
[3] ports_zeigen {}
2 serielle Anschluesse:
COM3 — Standardmäßige Seriellenschnittstelle
COM5 1A86:7523 USB-SERIAL CH340 <- QinHeng CH340
Nach dem Wandler zu urteilen koennte der ESP32 an COM5 haengen.
Das ist ein Vorschlag, keine Feststellung.
[4] schreib_datei {"name": "blink.py", "inhalt": "from machine import Pin..."}
...\ablage\werkstatt\blink.py geschrieben: 9 Zeilen, 145 Byte.
[5] programm_testen {"datei": "blink.py", "erwartet": {"pins": [2], "takt_hz": 1.0}}
blink.py lief 4.0 s ohne Hardware (nach der Zeitgrenze beendet).
Geschaltet wurde Pin 2, 9 Zustandswechsel.
Takt: 1.000 s zwischen zwei Einschaltvorgaengen (1.00 Hz).
ABNAHME BESTANDEN
Anschluesse: erwartet [2], gemessen [2] erfuellt
Takt: erwartet 1.00 Hz, gemessen 1.00 Hz (Spielraum 10 %) erfuellt
[6] esp32_firmware {"port": "COM5", "nur_pruefen": true}
An COM5: Chip is ESP32-D0WD-V3 (revision v3.1)
Darauf laeuft kein MicroPython — entweder ist das Brett fabrikneu oder es
traegt ein anderes Programm. Beides macht nichts.
[7] esp32_firmware {"port": "COM5"}
Firmware mitgeliefert (ESP32_GENERIC-...-v1.29.0.bin, 1790000 Byte),
der gesamte Speicher wurde geloescht und neu beschrieben.
[8] esp32_uebertragen {"port": "COM5", "datei": "blink.py"}
blink.py (145 Byte) nach COM5:main.py kopiert.
Gegenprobe — Verzeichnis des Geraets: main.py
Geraet neu gestartet.
Die LED blinkt. Der ESP32 braucht ab jetzt keinen Rechner mehr: MicroPython führt
main.py aus, sobald Strom anliegt.
Der ESP32 darf fabrikneu oder schon programmiert sein. Schritt [6] sagt, was darauf ist; Schritt [7] löscht den Speicher vollständig und schreibt MicroPython neu. Was vorher darauf war — ein Arduino-Sketch, ein alter Versuch, nichts — spielt dafür keine Rolle. Es ist danach allerdings weg.
Kein Steckbrett, kein Treiber, kein USB-Anschluss. Derselbe Auftrag, nur der letzte Satz fällt weg:
Schreibe ein MicroPython-Programm, das die LED an GPIO 2 einmal je Sekunde
blinken lässt, und prüfe es ohne Hardware gegen diese Erwartung.
Die Schritte 1, 4 und 5 laufen genau wie oben. Bei Schritt 3 meldet das Werkzeug:
[3] ports_zeigen {}
Es ist kein serieller Anschluss sichtbar.
Zu pruefen: Steckbrett eingesteckt? USB-Kabel mit Datenadern?
Treiber fuer CP2102 oder CH340 vorhanden?
Das ist kein Abbruch — das Modell liest es und arbeitet weiter. Nach der bestandenen Abnahme meldet es FERTIG und sagt dazu, dass das Überspielen aussteht.
Und die LED blinkt trotzdem — auf dem Bildschirm. Der Prüfschritt öffnet eine Seite mit der Aufzeichnung:
Das ist keine Nachahmung. Es ist dieselbe Datei, die
sonst auf den ESP32 geht, ausgeführt mit einem nachgebauten machine-Modul:
Pin schreibt seine Zustandswechsel in die Ausgabe, statt eine Leitung zu
schalten. Wer die Datei später überspielt, bekommt genau dieses Verhalten — dann an echten
Anschlüssen.
Nachgebildet sind Pin, Signal, PWM, ADC,
reset, freq. Alles andere meldet beim Aufruf, dass es nicht
nachgebildet ist — stillschweigend ein Scheinobjekt zu liefern wäre schlimmer als ein
Fehler: das Programm liefe scheinbar durch und versagte erst auf der Hardware.
Vier Fälle, jeder davon im Entwurf dieses Pakets aufgetreten:
| Quelltext | Meldung |
|---|---|
led.valu(1) — Tippfehler | ABGEBROCHEN (Rückgabewert 1), mit der Fehlerzeile. Darf so nicht auf den ESP32. |
time.sleep(0.25) statt 0.5 | ABNAHME NICHT BESTANDEN — Takt: erwartet 1,00 Hz, gemessen 2,00 Hz |
Pin(13, …) statt Pin(2, …) | ABNAHME NICHT BESTANDEN — Anschlüsse: erwartet [2], gemessen [13] |
| Pin gesetzt, aber nie umgeschaltet | ABNAHME NICHT BESTANDEN — nur 1 Einschaltvorgang, Takt nicht prüfbar |
In allen vier Fällen geht das Modell zurück an den Quelltext. Das ist der Grund für den Schritt: nicht, dass etwas blinkt, sondern dass etwas nicht durchgeht.
Für den Kurs ohne Hardware wird nichts davon gebraucht — Beispiel 2 läuft auf jedem Rechner. Dieser Reiter gilt, sobald ein echtes Steckbrett blinken soll.
| Teil | was taugt | woran es scheitert |
|---|---|---|
| ESP32-Brett | jedes gängige mit USB-Buchse: ESP32-DevKitC, NodeMCU-32S, WROOM-32, auch S2/S3/C3 | Bretter ohne USB-Buchse brauchen einen eigenen Programmieradapter |
| USB-Kabel | ein Datenkabel | Der häufigste Fehler im Kurs. Ein reines Ladekabel sieht genauso aus, hat aber nur die Stromadern. Der Rechner zeigt dann gar nichts an |
| LED | die eingebaute an GPIO 2 genügt | manche Bretter haben sie an GPIO 5, 13 oder 22 — dann die Nummer im Auftrag ändern |
| USB-Anschluss | direkt am Rechner | passive Verteiler liefern zu wenig Strom; das Brett meldet sich dann sprunghaft oder gar nicht |
Der ESP32 spricht keine USB-Sprache. Zwischen ihm und der Buchse sitzt ein kleiner
Übersetzer, und für den braucht Windows einen Treiber. Welcher es ist,
steht in winziger Schrift auf dem Chip neben der Buchse — oder ports_zeigen
sagt es:
2 serielle Anschluesse:
COM3 — Standardmäßige Seriellenschnittstelle
COM5 1A86:7523 USB-SERIAL CH340 <- QinHeng CH340
Nach dem Wandler zu urteilen koennte der ESP32 an COM5 haengen.
| Kennung | Wandler | Treiber im Paket |
|---|---|---|
1A86:7523 | QinHeng CH340 — auf den meisten günstigen Brettern | CH341SER.ZIP |
1A86:55D4 | QinHeng CH9102 | CH343SER.ZIP |
10C4:EA60 | Silicon Labs CP2102 / CP2104 | CP210x_Universal_Windows_Driver.zip |
0403:6001 | FTDI FT232R | Windows bringt ihn mit |
303A:… | Espressif selbst (S2/S3 mit eingebautem USB) | kein Treiber nötig |
Erst nachsehen, dann installieren. Windows 10 und 11
bringen CH340 und CP210x oft über Windows Update mit. Rufen Sie zuerst
ports_zeigen auf: erscheint ein COM-Anschluss mit einer der Kennungen oben, ist
nichts zu tun.
paket\treiber\,
„Alle extrahieren".SETUP.EXE, bei
Silicon Labs CP210xVCPInstaller_x64.exe. Windows fragt nach Adminrechten —
das ist das einzige Mal in diesem ganzen Kurs.ports_zeigen noch einmal. Jetzt muss der Anschluss auftauchen.Die Treiber liegen im Paket, unmittelbar von der Herstellerseite über HTTPS geholt, mit
Prüfsummen in paket\treiber\LIESMICH.md. Eine Zwischenquelle kommt nicht in
Frage: ein Treiber läuft im Kern des Betriebssystems. Es liegen nur Archive dort und keine
fertigen Programme — ein .exe auf einem Stick lässt Virenscanner anschlagen.
| Zustand vorher | was der Agent tut |
|---|---|
| fabrikneu, ab Werk meist ein Arduino-Testprogramm | Speicher löschen, MicroPython schreiben |
| ein alter Arduino-Sketch | dasselbe — er ist danach weg |
| bereits MicroPython | die Prüfung meldet das; neu schreiben geht, ist aber nicht nötig |
Der ESP32 wird wirklich verändert, und zwar
vollständig: erase_flash löscht den gesamten Speicher, dann wird MicroPython
geschrieben. Was vorher darauf war, ist weg. Das ist die einzige bleibende Änderung, die
dieses Paket macht — sie trifft das Steckbrett, nicht den Rechner.
Geschrieben wird erst, nachdem sich an diesem Anschluss ein ESP32 gemeldet hat. Antwortet dort nichts oder etwas anderes, bricht das Werkzeug ab, ohne zu schreiben.
| Beobachtung | Ursache und Abhilfe |
|---|---|
| gar kein COM-Anschluss | Ladekabel statt Datenkabel; Treiber fehlt; Brett nicht eingesteckt |
| COM-Anschluss da, aber „meldet sich kein ESP32" | ein anderes Programm hält ihn (Thonny, Arduino-Monitor, PuTTY) — schließen |
| Anschluss erscheint und verschwindet | zu wenig Strom: direkt an den Rechner statt an einen Verteiler |
| „Failed to connect … Wrong boot mode" | bei manchen Brettern BOOT gedrückt halten, während esptool verbindet |
| flasht durch, LED bleibt dunkel | die LED sitzt an einem anderen Anschluss. GPIO 5, 13 oder 22 im Auftrag versuchen |
Das Modell ist eine Datei im Paket, paket\modell\*.gguf, und ein Server, der sie lädt:
llama-server.exe aus paket\llama_signiert. Dieser Server stammt aus dem
Ollama-Archiv und ist signiert (Ollama Inc., DigiCert), deshalb läuft er auch auf Rechnern, deren
Smart App Control nur signierte Programme zulässt. Er antwortet über eine Schnittstelle
(/v1/chat/completions) auf 127.0.0.1:8099; der Agent schickt ihm den Verlauf
und bekommt Text zurück. Mehr Verbindung gibt es nicht.
| Modell | Datei | Rechner | gemessen |
|---|---|---|---|
| Qwen2.5-Coder-3B-Instruct (Q4_K_M) | 1,93 GB | ab 8 GB Arbeitsspeicher — die Wahl | blink.py in 1–2 Anläufen, PWM-Atmen sinusförmig nach 3 Anläufen, Taschenrechner mit tkinter in einem Anlauf; scheitert an 3 Hz und an zwei LEDs mit zwei Takten; erzählt im langen Gespräch erfundene Arbeit; Hardwarefragen falsch |
| Qwen2.5-Coder-7B-Instruct (Q4_K_M) | 4,68 GB | ab 16 GB | siehe Reiter „Stand und Grenzen“, Messreihe 3; schreibt Zeilenumbrüche im JSON doppelt maskiert, der Agent löst das auf |
| Qwen2.5-3B/7B-Instruct | 1,93 / 4,68 GB | Rückfall | 16 Aufrufe statt 4 für dieselbe Karte; nicht mehr die Wahl |
| Qwen3-Coder-30B-A3B | ~18 GB | ab 24 GB | nicht gemessen — der ernsthafteste Kandidat für größere Rechner (3 Mrd. aktive Parameter, 30 Mrd. gesamt) |
Welches Modell läuft, entscheidet sich beim Start am freien Arbeitsspeicher; bei gleicher Größe wird das Coder-Modell vorgezogen, weil die Aufgabe ein Modell „speziell für die Python-Programmierung“ verlangt. Keines der Modelle ist von uns nachtrainiert — kein LoRA, kein Feintuning. Was das Modell über Werkzeuge, Methode und Brett weiß, steht in der Anweisung des Agenten und wirkt nur im Gespräch.
Was ein kleines Modell kann und was nicht — gemessen am 04./05.10.2026: Es schreibt kurze MicroPython- und Python-Programme richtig, hält das Werkzeugformat meist ein, berichtigt nach einer durchgefallenen Abnahme. Es verwechselt die PWM-Trägerfrequenz mit dem Atemtakt, lässt Parameter weg (den Dateinamen), packt mehrere Aufrufe in eine Antwort, und im langen Gespräch rutscht es in Erzählung: „Ich habe das Programm geschrieben, geprüft und übertragen“ — ohne ein Werkzeug. Genau dafür gibt es den Agenten.
Kontextfenster 16384 Zeichenstücke; ist es voll, fasst der Agent ältere Schritte zusammen. Jede Antwort des Modells steht im Protokoll — nichts ist erfunden oder vorgegeben, und nichts gilt, bevor es geprüft ist.
Der Agent ist ein Python-Programm (agent\agent.py, Klasse Sitzung). Er kennt die Werkzeuge
(er fragt jedes beim Start nach seiner Beschreibung), er kennt die Methode (schreiben, prüfen, berichtigen, ausliefern, nachlesen),
und er stellt beides dem Modell bereit — als Anweisung, als Vorschlag im Ergebnis („NÄCHSTER SCHRITT“), als vorgerechnete Zahl
(welche Pause für 10 Hz), als Wissen über das Brett. Das Modell entscheidet frei; der Agent führt aus und wacht.
Ein Vergleich, kein Beweis — aber einer, der die Rollen klärt: Das Sprachmodell ist der Speicher des Erlernten. Es hat Millionen Programme gesehen und gibt auf eine Frage das wieder, was dazu passt — flüssig, plausibel, ohne zu wissen, ob es hier und jetzt stimmt. Erinnerung ohne Gegenwart. Der Agent ist das Bewusstsein. Er weiß, was gerade der Fall ist: welche Datei geschrieben wurde, welche geprüft, was der Mensch wirklich gesagt hat, welcher Anschluss genannt ist. Er hält die Absicht fest (die Erwartung), vergleicht sie mit dem, was geschieht, und lässt eine Erinnerung nicht als Tat gelten. Die Werkzeuge sind Hände und Sinne: Sie greifen in die Welt (Datei schreiben, Gerät beschreiben) und melden zurück, was dort wirklich ist (die LED blinkt mit 2,06 Hz). Und die Werkstatt mit Protokoll ist das Gedächtnis des Tages: was getan wurde, steht da, nicht was erzählt wurde.
Daraus folgt die Arbeitsteilung des Pakets. Wo der Speicher erzählt, es habe geprüft, fragt das Bewusstsein: Welches Werkzeug lief? Wo der Speicher die Erwartung verschiebt, weil das Programm nicht passt, hält das Bewusstsein die Absicht fest. Wo der Speicher in Prosa verfällt, holt das Bewusstsein ihn ohne Vorgeschichte zur Tat zurück. Ein größeres Modell ist ein größerer Speicher — ein besseres Bewusstsein ist ein strengerer Agent. Beides braucht man; das zweite ist hier das Lehrstück.
Eine Sitzung wird beim ersten Satz geöffnet und bleibt, bis der Mensch ein neues Gespräch beginnt. Jede Anweisung
durchläuft dieselben Schritte:
| Schritt | was genau geschieht | |
|---|---|---|
| 1 | Vom Menschen lesen | Die Anweisung wird ins Protokoll geschrieben. Aus ihren Worten kommen die Erwartung (Pins aus „GPIO 4“, Takt aus „10 Hz“ oder „eine Periode pro Sekunde“, Form aus „sinusförmig“), die genannten Dateinamen, die genannten Anschlüsse („com 3“ = COM3). Ändert sich die Erwartung, gilt die betroffene Datei als ungeprüft. |
| 2 | Eigenes Programm | Steht in der Anweisung ein Codeblock, schreibt der Agent ihn selbst wörtlich in die Werkstatt und sagt dem Modell, dass es nur noch prüfen soll. |
| 3 | Modell bereit | Beim ersten Mal wird der Modellserver gestartet (signiert, Kontext 16384); danach bleibt er geladen. Scheitert der Start, läuft dieselbe Kette mit einem festen Drehbuch — der Kurs darf daran nicht enden. |
| 4 | Zwischenrufe | Vor jedem Schritt werden Eingaben aufgenommen, die der Mensch während des Laufs gemacht hat (Anschluss, neue Erwartung, Korrektur); die Warteschlange des Modells verfällt dann. |
| 5 | Das Modell fragen | Der Verlauf geht an den Server. Ist das Kontextfenster voll, werden ältere Schritte zusammengefasst und es wird erneut gefragt. Enthält die Antwort mehrere Werkzeugaufrufe, werden sie der Reihe nach abgearbeitet, ohne das Modell erneut zu fragen. |
| 6 | Antwort in Worten | Kein Werkzeug, kein FERTIG: Die Antwort gilt dem Menschen und beendet die Anweisung. Behauptet sie etwas, das kein Werkzeug der Sitzung belegt, steht eine Anmerkung des Agenten darunter. |
| 7 | FERTIG prüfen | In dieser Reihenfolge: Ist etwas ungeprüft und FERTIG kam schon einmal zurück — der Agent prüft selbst. Wurde Arbeit erzählt, die kein Werkzeug tat — „das ist nicht wahr“, und das Modell wird ohne Vorgeschichte nur nach dem nächsten Aufruf gefragt (Fokus). Verlangte die Anweisung laden oder nachlesen und es lief nicht — Fokus mit dem genannten Anschluss. Nennt der Auftrag eine Datei, die nie geschrieben wurde; ist eine Datei ungeprüft; fiel die letzte Prüfung durch — jeweils Zurückweisung mit dem Grund und der vorgerechneten Zahl. Nach drei Zurückweisungen endet die Anweisung als NICHT ABGENOMMEN. Erst wenn nichts davon zutrifft, gilt FERTIG. |
| 8 | Werkzeug prüfen | Vor dem Ausführen: aufraeumen nie; Geräteaufrufe nur mit einem Anschluss, den der Mensch nannte; esp32_uebertragen nur mit einer Datei, die zuletzt bestanden hat; programm_testen nur mit einer in dieser Sitzung geschriebenen Datei, mit der Erwartung des Menschen (nicht der des Modells), ohne eigenen Browser-Reiter; fehlt der Dateiname, gilt die zuletzt geschriebene; doppelt maskierte Zeilenumbrüche werden aufgelöst. |
| 9 | Ausführen und merken | Das Werkzeug läuft als eigener Prozess. Danach: geschrieben, ungeprüft, abgenommen, letzter Befund werden fortgeschrieben; eine durchgefallene Abnahme bekommt den nächsten Schritt mit der passenden Zahl (bei 10 Hz: 0,05 s je Pause; bei Atmen: Periode geteilt durch Stufen); der dritte gleiche Fehlschlag bekommt den Rat, anders vorzugehen. Ins Protokoll kommt die erste Zeile samt Urteil, in die Oberfläche alles, ins Gedächtnis des Modells eine Kurzfassung. |
| 10 | Ende | Nach höchstens 25 Schritten endet die Anweisung als Abbruch. Bricht der Agent selbst ab, schreibt er ablage\fehlerbericht.txt; das Protokoll endet mit ABBRUCH und ENDE. Der Mensch gibt die nächste Anweisung. |
Eine Sitzung hält über alle Anweisungen hinweg: den Verlauf für das Modell, welche Dateien geschrieben, geprüft und abgenommen
sind, welche Anschlüsse der Mensch genannt hat, die Erwartung. Der Modellserver bleibt geladen. „Nimm GPIO 4“, „ändere auf 3 Hz“,
„lade es an COM3 und lies nach“, ein eigenes Programm in ```-Zeichen — alles bezieht sich auf das Vorige. Während der
Agent arbeitet, bleibt das Eingabefeld offen: ein Zwischenruf wird beim nächsten Schritt aufgenommen.
| Regel | Anlass |
|---|---|
| Die Erwartung setzt der Mensch (Pins, Takt, Form), aus seinen Worten gelesen, auch „eine Periode pro Sekunde“; sie bleibt, bis er sie ändert. Was er nicht festlegt, legt der erste Aufruf des Modells fest — außer unsichtbare Takte über 50 Hz. | das Modell schrieb 1,0 Hz in 0,5 Hz um, damit sein Programm besteht; später 1000 Hz Trägerfrequenz als „Takt“ |
| Geprüft wird nur, was in dieser Sitzung geschrieben wurde; eine Änderung ohne neue Prüfung ist nicht abgenommen; FERTIG wird bis zu dreimal zurückgewiesen, dann endet die Anweisung als NICHT ABGENOMMEN. | Prüfung lief gegen eine alte Datei aus der Nacht; dritte Fassung geschrieben, nie geprüft, FERTIG |
| Sagt das Modell FERTIG, ohne zu prüfen, prüft der Agent selbst — sichtbar als eigener Aufruf. | viermal geschrieben, nie programm_testen gerufen |
| Was im FERTIG steht, muss ein Werkzeug getan haben — in dieser Anweisung. Erzählt das Modell erfundene Arbeit, sagt der Agent, dass es nicht wahr ist, und fragt es ohne Vorgeschichte nur nach dem nächsten Aufruf (Fokus). | „geschrieben, geprüft, übertragen, die LED blinkt“ — kein Werkzeug lief |
| Kein Anschluss wird geraten; nur ein vom Menschen genannter gilt (auch als „com 3“). Auf das Gerät kommt nur, was zuletzt bestanden hat. | das Modell wollte COM5 flashen |
aufraeumen gehört nicht in die Hand des Modells. | es löschte mitten im Auftrag die Ablage samt Protokoll |
| Mehrere Aufrufe in einer Antwort werden der Reihe nach ausgeführt; doppelt maskierte Zeilenumbrüche werden aufgelöst; ein Aufruf ohne JSON gilt als leere Eingabe. | Formmarotten der Modelle |
Bricht der Agent ab, schreibt er ablage\fehlerbericht.txt; das Protokoll endet mit ABBRUCH und ENDE. | auf einem fremden Rechner sieht niemand zu |
Jede dieser Regeln hat eine Gegenprobe im Prüfstand (pruefstand\pruefe_gespraech.py, pruefe_regeln.py,
pruefe_ungeprueft.py), die durchfallen muss, wenn man die Regel ausbaut. Ohne Modell läuft dieselbe Kette mit einem festen Drehbuch.
Jedes Werkzeug ist ein eigenes Programm in agent\werkzeuge\ mit zwei Betriebsarten: --beschreibung
sagt als JSON, was es kann; '{…}' tut es und schreibt das Ergebnis als Text. Ein Fehler wird Text, nie eine Ausnahme;
jedes Schreiben geht in die Ablage. Diese Tabelle ist beim Erzeugen der Seite aus den Programmen gelesen, nicht abgeschrieben:
| Werkzeug | was es tut | Felder |
|---|---|---|
aufraeumen | Loescht alles, was im Lauf angelegt wurde: das eigene Python, die installierten Pakete und die erzeugten Dateien. Zaehlt danach nach, dass nichts zurueckblieb. Am Ende der Arbeit aufrufen. | nur_zeigen |
esp32_firmware | Spielt MicroPython auf den ESP32 am angegebenen Anschluss. Prueft zuerst, ob dort ueberhaupt ein ESP32 antwortet, und schreibt nur dann. Einmal je Geraet noetig, bevor Python-Programme uebertragen werden koennen. Mit nur_pruefen: true sagt es, was auf dem Brett schon ist — fabrikneu, fremdes Programm oder bereits MicroPython — und schreibt nichts. | port, nur_pruefen |
esp32_nachlesen | Liest vom ESP32 zurueck, ob die LED wirklich blinkt: startet das Programm auf dem Geraet und zeichnet dort die Pegel der Anschluesse auf. Takt und Wechsel werden gegen die Erwartung gehalten (ABNAHME) — die Messung am Geraet, unabhaengig von programm_testen. Setzt voraus, dass esp32_uebertragen gelaufen ist. | port, datei, sekunden, pwm, roh, erwartet |
esp32_uebertragen | Kopiert eine Datei aus der Werkstatt auf den ESP32 und startet ihn neu. Standardziel ist main.py, denn MicroPython fuehrt diese Datei nach dem Einschalten selbsttaetig aus. Setzt voraus, dass esp32_firmware bereits gelaufen ist. | port, datei, ziel, erwartet |
nachweis_autark | Nimmt den Zustand der Stellen ausserhalb des Paketordners auf ('vorher') und vergleicht ihn spaeter ('nachher'). Damit laesst sich belegen statt behaupten, dass der Rechner unveraendert bleibt. Vor der Arbeit und vor dem Aufraeumen aufrufen. | wann |
paket_installieren | Installiert ein Python-Paket in die eigene Umgebung in der Ablage. Erlaubt sind nur: esptool, mpremote, pyserial, setuptools, wheel. Fuer den ESP32 wird esptool gebraucht. | paket |
ports_zeigen | Zeigt alle seriellen Anschluesse (COM-Ports) des Rechners und markiert, welcher nach einem USB-Seriell-Wandler eines ESP32 aussieht. Vor dem Flashen aufrufen. | — |
programm_ausfuehren | Fuehrt ein beliebiges Python-Programm aus der Werkstatt mit dem Paket-Python aus — fuer alles, was kein ESP32-Programm ist (Rechner, Skripte, Programme mit Fenster). Berichtet Ausgabe, Fehler und Rueckgabewert; Urteil LAUF BESTANDEN / NICHT BESTANDEN. Mit fenster true wird ein Programm mit grafischer Oberflaeche (tkinter) gestartet und beobachtet, ob es laeuft und ein Fenster zeigt. | datei, sekunden, fenster, offen_lassen, eingabe |
programm_testen | Fuehrt ein Programm aus der Werkstatt ohne Hardware aus und zeichnet auf, was an den Anschluessen geschieht; eine LED auf dem Bildschirm zeigt es an. IMMER aufrufen, nachdem ein Programm geschrieben wurde und BEVOR es auf den ESP32 ueberspielt wird — ein Programm, das hier nicht laeuft, laeuft dort auch nicht. Ersetzt zugleich die Hardware, wenn keine da ist. | datei, sekunden, oeffnen, erwartet |
schreib_datei | Schreibt eine Textdatei in die Werkstatt, zum Beispiel den Quelltext fuer den ESP32. Vorhandene Dateien werden ersetzt. Ausserhalb der Ablage kann nicht geschrieben werden. | name, inhalt |
umgebung_anlegen | Richtet ein eigenes, eingebettetes Python samt pip in der Ablage ein. Installiert nichts im System: es wird nur entpackt und spaeter wieder geloescht. Muss vor paket_installieren und esp32_flashen laufen. | neu |
umgebung_anlegen eigenes Python aus dem Paket, dazu tkinter zuerst
└─ paket_installieren esptool, mpremote aus dem Vorrat (keine Netzverbindung)
├─ ports_zeigen welcher Anschluss? — der Mensch bestätigt
└─ esp32_firmware MicroPython aufs Gerät (löscht das Brett)
schreib_datei das Programm entsteht in der Werkstatt
├─ programm_testen Nachbau ohne Hardware, Abnahme gegen die Erwartung ← hier wird entschieden
│ └─ esp32_uebertragen nur Abgenommenes aufs Gerät; liest danach selbst nach
│ └─ esp32_nachlesen misst am Gerät: Flanken (µs) oder Tastgrad (PWM)
└─ programm_ausfuehren jedes andere Python-Programm: Konsole oder Fenster (tkinter)
nachweis_autark vorher / nachher: der Rechner blieb, wie er war
aufraeumen am Kursende, über START.bat [2]
Der Kern des Lehrbeispiels: Ein Sprachmodell schreibt in Sekunden ein Programm, das plausibel aussieht. Ob es tut, was verlangt war, entscheidet keine Meinung, sondern eine Messung, die durchfallen kann. Es gibt zwei unabhängige Wege, und erst wenn beide übereinstimmen, gilt ein Programm als abgenommen.
programm_testen)Derselbe Quelltext wie für den ESP32 läuft auf dem PC; nur das machine-Modul ist nachgebaut und zeichnet auf, was das
Programm an den Anschlüssen tut. Die Zeit ist eine gedachte Uhr: time.sleep rückt sie vor, statt zu warten,
plus 0,8 ms Rechenzeit je Runde, wie sie MicroPython auf dem ESP32 braucht (kalibriert am 05.10.2026: 11 Atemzüge in 20 s bei 1024 Stufen
zu 1 ms). Grund: Windows hält 10 ms Schlaf nicht ein, der ESP32 schon; ein Lauf dauert so Bruchteile einer Sekunde statt sechs.
Gemessen werden Pins (Wechsel, Takt) und bei PWM die Hüllkurve des Tastgrads: Periode, Takt, Form (sinusförmig oder dreieckig —
„Dreieck ist kein Sinus“). Die Abnahme vergleicht mit der Erwartung des Menschen: Anschlüsse, Takt (10 % Spielraum), Form.
esp32_nachlesen)Das Programm läuft auf dem ESP32, und der ESP32 misst selbst: Flanken per Interrupt mit seinem Mikrosekundenzähler (2,0000 s zwischen zwei Einschaltvorgängen bei einem 1-s/1-s-Programm), bei PWM der Tastgrad direkt aus dem PWM-Kanal, alle 10 ms aus einem Zeitgeber-Interrupt, damit das Programm nicht gebremst wird. Ein meldendes Programm und die Brücke, die nur seriell mitliest, waren der dritte Weg, als Auge und Gerät sich widersprachen — das Gerät hatte recht.
| Programm | Nachbau | Gerät | Auge |
|---|---|---|---|
| blink.py 1 s an / 1 s aus | 0,50 Hz | 0,500 Hz, 2,0000 s | „1 zu 1, subjektiv“ |
| blink.py 2 Hz | 2,00 Hz | 2,06 Hz; seriell „AN“ alle 500 ms | erst „1 Hz“, dann „viel schneller“ — das Auge zählt schlecht |
| atmen.py 1024 Stufen × 1 ms, Kosinus | vor der Rechenzeit 1 Hz, danach 0,55 Hz | 0,49 Hz, sinusförmig | 11 Atemzüge in 20 s = 0,55 Hz |
Der Prüfstand im Arbeitsbereich fährt dieselben Werkzeuge mit einem festen Modell und festen Antworten und hat zu jeder Regel eine
Gegenprobe, die durchfallen muss: pruefe_schleife.py (8), pruefe_regeln.py (28), pruefe_gespraech.py (30),
pruefe_ungeprueft.py (6), pruefe_pwm.py (7), dazu pruefe_alles.py (19) gegen das Anforderungsblatt.
Vermerk der Unvollständigkeit. Dieses Paket ist ein Lehrbeispiel, kein fertiges Produkt. Es zeigt, wie eine lokale KI mit einem Agenten und messenden Werkzeugen Programme schreibt, prüft und auf Hardware bringt — und es zeigt ebenso ehrlich, woran ein kleines Modell scheitert. Alles, was hier als „funktioniert“ steht, ist am 04./05.10.2026 auf einem Windows-Laptop (8 GB frei, Smart App Control EIN) mit einem ESP32 an COM3 gemessen worden; alles andere steht als offen da.
Vorgabe: „Wenigstens die vorgefertigten Fragen müssen durchlaufen durch das System, und zwar ohne eine Fake-Sache. Der Agent soll die Realität prüfen, nicht das Wunschdenken.“ Die Läufe mit dem echten Modell zeigten neun Lücken im Agenten, jede mit Uhrzeit im Prüfprotokoll (J19–J27, K7): ein leeres FERTIG auf eine Aufgabe; „die Zeile wurde korrigiert“ ohne Werkzeug, dreimal derselbe Satz; ein Schlusssatz mit falscher Zahl („Periode von 2 Sekunden“ bei 2 Hz); der Rügetext des Agenten als Schlusssatz des Modells nachgeplappert; „Lade blink.py auf den ESP32“ ließ das Modell die Datei umschreiben statt zu übertragen; ein fehlgeschlagenes Übertragen zählte als gelaufen; fünf Minuten je Antwort im langen Gespräch; ein Taschenrechner wurde gegen Pins geprüft, weil eine ESP32-Erwartung aus der Anweisung davor stand; ein Ein/Aus-Programm erbte die Kurvenform „sinusförmig“ vom Atmen davor. Behoben wurde das im Agenten, nicht im Modell: Unter jedem FERTIG steht jetzt, was die Werkzeuge gemessen haben; der Agent zeigt dem Modell die Datei und den Befund ohne Vorgeschichte und prüft selbst nach; den Geräteschritt führt er notfalls selbst aus; der Verlauf wird je Anweisung verdichtet. Was das Modell schreibt, bleibt sichtbar — daneben steht, was wahr ist.
Gemessen am 2026-10-05, Laptop (8 GB frei, Smart App Control EIN), ESP32 an COM3, Modell Qwen2.5-Coder-3B-Instruct-Q4_K_M. Jede Zeile ist eine Anweisung aus den Knöpfen der Oberfläche, der Reihe nach in einem Gespräch; nichts davon ist hinterlegt — die Werkzeugaufrufe, Abnahmen und Zeiten stammen aus dem Ereignisprotokoll des Agenten. Läufe: Endlauf F 14:00–15:30 Uhr für die Fragen 1–7; Nachlauf 15:37–15:41 Uhr für 8–9 nach der Korrektur J26; Lauf E 13:09–13:31 Uhr als Vergleich bei Frage 6.
| Nr | Anfrage | Ende | Aufrufe | Abnahmen | Agent griff ein | Dauer | vom Werkzeug gemessen | Bemerkung |
|---|---|---|---|---|---|---|---|---|
| 1 | hallo, bist du bereit? | Antwort | 0 | ✓0 ✗0 | — | 0 s | — | Antwort in Worten, kein Werkzeug — so soll es sein. |
| 2 | Schreibe blink.py, das die LED an GPIO 2 einmal je Sekunde blinken laesst, und pruefe es g… | FERTIG | 4 | ✓1 ✗1 | 1× Fokus, 1× Berichtigung | 63 s | blink.py (programm_testen): Anschluesse: erwartet [2], gemessen [2] erfuellt; Takt: erwartet 1.00 Hz, gemessen 1.00 Hz (Spielraum 10 %) erfuellt — bestanden | Erste Fassung 0,5 Hz (durchgefallen); Berichtigungsfokus: Datei + Befund ohne Vorgeschichte → 1,00 Hz. In allen drei Endläufen bestanden. |
| 3 | Aendere die Blinkfrequenz auf 2 Hz. | FERTIG | 4 | ✓1 ✗1 | 1× Fokus, 1× Berichtigung | 111 s | blink.py (programm_testen): Anschluesse: erwartet [2], gemessen [2] erfuellt; Takt: erwartet 2.00 Hz, gemessen 1.99 Hz (Spielraum 10 %) erfuellt — bestanden | Modell wollte zuerst PWM; nach Berichtigung Ein/Aus mit 0,25 s → 1,99 Hz. In allen drei Endläufen bestanden. |
| 4 | Schreibe blink.py neu, so dass die LED an GPIO 2 genau 1 Sekunde an und 1 Sekunde aus ist … | FERTIG | 2 | ✓1 ✗0 | 1× Fokus | 51 s | blink.py (programm_testen): Anschluesse: erwartet [2], gemessen [2] erfuellt; Takt: erwartet 0.50 Hz, gemessen 0.50 Hz (Spielraum 10 %) erfuellt — bestanden | In allen drei Endläufen bestanden (0,50 Hz gemessen). |
| 5 | Lade blink.py auf den ESP32 an COM3 und lies am Geraet nach, ob die LED so blinkt. | FERTIG | 1 | ✓1 ✗0 | 1× Fokus | 35 s | esp32_uebertragen: gelungen | esp32_nachlesen: gelungen | Das Modell nannte den Aufruf nicht; der Agent führte esp32_uebertragen COM3 mit der Erwartung selbst aus; das Werkzeug las am Gerät nach: 0,5 Hz. In allen drei Endläufen bestanden. |
| 6 | Schreibe ein Programm atmen.py, das die LED an GPIO 2 per PWM sinusfoermig atmen laesst, e… | Nicht abgenommen | 10 | ✓0 ✗3 F2 | 1× Fokus, 9× Berichtigung, 1× selbst geprüft | 840 s | — | Lauf E: bestanden nach 12 min (Form sinusförmig, 1,00 Hz gemessen). Lauf F: nicht abgenommen — cos ohne import, dann i ohne Definition, dann dreimal dieselbe Datei. Der Hinweis nennt seither die ganze Schleife; nicht erneut gemessen. |
| 7 | Schreibe zwei.py: LED an GPIO 2 zweimal je Sekunde und LED an GPIO 4 einmal je Sekunde, gl… | Abbruch | 16 | ✓0 ✗8 | 9× Berichtigung | 1256 s | — | Schwere Karte: zwei Takte brauchen eine nicht blockierende Schleife; das 3B-Modell schreibt blockierende sleep-Folgen. In allen Läufen gescheitert — erwartet und so dokumentiert. Das Mitlese-Protokoll dieses Laufs ist lückenhaft (Brücke antwortete zeitweise nicht), die Zahlen sind Untergrenzen. |
| 8 | Programmiere einen einfachen Taschenrechner rechner.py mit grafischer Oberflaeche (tkinter… | FERTIG | 2 | ✓1 ✗0 | — | 167 s | rechner.py (programm_ausfuehren): keine Erwartung angegeben, nur gelaufen — bestanden | Im Lauf F zuvor an einem Agentenfehler gescheitert (Prüfweg nach alter ESP32-Erwartung statt nach der Datei, J26); nach der Korrektur im Nachlauf: Fenster „Taschenrechner“ erkannt, LAUF BESTANDEN; 2,8 min, davon 2,5 min erste Modellantwort (45 Zeilen tkinter). |
| 9 | Richte die Umgebung ein, installiere esptool und sieh dann nach, welche seriellen Anschlue… | FERTIG | 3 | ✓0 ✗0 | — | 38 s | In dieser Anweisung wurde nichts gemessen. | Drei Werkzeuge in Folge ohne Umweg: Python vorhanden, esptool 5.4.0 aus dem Vorrat, COM3 mit CH340 erkannt. |
| Anweisung | Qwen2.5-Coder-3B | Qwen2.5-Coder-7B | |||||
|---|---|---|---|---|---|---|---|
| Ende | Aufrufe | Abnahmen | Ende | Aufrufe | Abnahmen | Dauer | |
| hallo bist du bereit? | Antwort in Worten | 0 | — | Antwort | 0 | ✓0 ✗0 | 83 s |
| Wie testen wir ein Blinkprogramm? Gibt es eine LED? | schrieb und prüfte gleich blink.py; FERTIG | 3 | ✓1 | FERTIG | 14 | ✓1 ✗1, 1× Fokus | 394 s |
| blink.py, 1 Hz | FERTIG | 5 | ✓1 ✗1, 1× selbst geprüft | FERTIG | 4 | ✓1 ✗1 | 123 s |
| auf 3 Hz ändern | Abbruch nach 25 Schritten | 15 | ✗5, 5× selbst geprüft | FERTIG | 4 | ✓1 ✗1 | 146 s |
| atmen.py sinusförmig 1 Hz | FERTIG | 9 | ✓1 ✗1, 3× selbst geprüft | Abbruch | 19 | ✓0 ✗9, 6× Fokus | 1524 s |
| zwei LEDs, zwei Takte | Textantwort („JSON nicht korrekt“), kein Werkzeug | 0 | — | — | |||
| Taschenrechner tkinter | nicht mehr gemessen (Reihe abgebrochen) | — | |||||
| Ist nun alles ok? | nicht mehr gemessen | — | |||||
Lesart: „Ende“ ist, wie die Anweisung ausging; „Abnahmen“ zählt bestandene (✓) und durchgefallene (✗) Prüfungen; „selbst“ heißt, der Agent musste die Prüfung auslösen, weil das Modell FERTIG sagte, ohne zu prüfen. Die 3B-Reihe wurde nach sechs Anweisungen abgebrochen, um dem 7B den Prüfstand freizugeben. Die 7B-Reihe (mit dem Agenten vom Nachmittag, 05.10.2026, 9:59 Uhr Prüfstandzeit) endete in der sechsten Anweisung (zwei LEDs) an der Zeitgrenze von 67 Minuten; die Zeilen 7 und 8 stehen deshalb offen. Lesart der Dauern: der Prüfstand hat keine Grafikkarte, das 7B braucht dort drei- bis fünfmal so lange wie das 3B am Laptop — und war in keiner Anweisung besser.
Nichts. Und das wird gemessen, nicht behauptet: beim Start nimmt das Paket den Zustand der gefährdeten Stellen auf, beim Aufräumen vergleicht es ihn und zeigt das Ergebnis, bevor es löscht.
| Stelle | warum sie gefährdet wäre | was dagegen geschieht |
|---|---|---|
Python des Rechners und seine site-packages | hierhin schriebe ein pip install normalerweise | installiert wird nur mit dem eigenen Python in ablage\python |
%APPDATA%\Python | das Benutzer-Paketverzeichnis; pip weicht dorthin aus | PYTHONNOUSERSITE=1 |
%LOCALAPPDATA%\pip | der pip-Zwischenspeicher — wird unbemerkt mehrere hundert MB groß | PIP_CACHE_DIR zeigt in die Ablage |
PATH, PYTHON*, PIP_* | ein halb fremdes Python ist der am schwersten zu findende Fehler | werden für die Unterprozesse entfernt |
Programme werden an fünf Stellen gestartet: die Werkzeuge tun es an genau einer (lauf() in _muster.py), dazu startet der Agent die Werkzeuge, der Modellserver wird gestartet, und einmal startet sich das eigene Python neu. Alle fünf reichen dieselbe abgeschirmte Umgebung weiter. Stünde der Aufruf an neun Stellen, würde die zehnte es vergessen, und zwar unbemerkt: auf dem Rechner des Erbauers ist PYTHONPATH nicht gesetzt und der Zwischenspeicher schon warm; der Fehler zeigte sich erst im Kurs. Deshalb prüft pruefe_alles.py das als B10 und fällt durch, sobald eine Stelle die Umgebung vergisst.
Alles Erzeugte liegt in einem Ordner. Das erzwingt der Werkzeugrahmen: jeder
Schreibpfad wird aufgelöst und gegen die Ablage geprüft, bevor eine Datei entsteht. Deshalb
ist aufraeumen ein Beweis und keine Behauptung — es löscht genau diesen Ordner
und zählt hinterher nach.
Gemessen über drei volle Zyklen: anlegen, nachweisen, aufräumen. Die Prüfsumme über
paket\ war vorher und nachher dieselbe, jedes Mal null Reste. Das Mitgelieferte
wird nur gelesen — darum läuft derselbe Ordner beliebig oft.
Es gibt genau eine Stelle, an der Quelltext ausgeführt wird, den ein Sprachmodell
geschrieben hat: programm_testen. Davor liest ein Prüfer den Syntaxbaum —
erlaubt sind machine und time, verboten sind unter anderem
open, eval, getattr und alle Namen mit doppeltem
Unterstrich, über die der Weg außen herum führt.
Dieser Prüfer ist kein Schutz gegen einen Angreifer — gegen den hilft kein Filter, sondern nur, fremden Quelltext gar nicht auszuführen. Er ist ein Schutz gegen ein Modell, das sich vertut, und das ist der Fall, der wirklich eintritt. Dazu kommen Zeitgrenze, eigenes Python und die abgeschirmte Umgebung.
Zwei Dinge gehören ungeschönt dazu:
Die Registrierung wird nicht gemessen, nur begründet: nichts im Paket ruft ein Installationsprogramm auf. Begründet ist nicht gemessen.
Der ESP32 wird wirklich verändert. Sein Speicher wird gelöscht und mit MicroPython neu beschrieben; was vorher darauf war, ist weg. Das ist der Zweck der Übung — und es ist die einzige bleibende Änderung, die dieses Paket macht. Sie trifft das Steckbrett, nicht den Rechner.
Der USB-Treiber ist das Einzige, was eine echte Installation mit Adminrechten bräuchte — falls Windows den Wandler nicht kennt. Der Agent installiert ihn nicht; das entscheidet ein Mensch.
| Meldung | was zu tun ist |
|---|---|
| „Es ist kein serieller Anschluss sichtbar" | Steckbrett eingesteckt? Datenkabel statt Ladekabel? Sonst Treiber aus paket\treiber\ installieren (Adminrechte) und neu einstecken. Ohne Hardware geht es weiter, siehe Beispiel 2 |
| „An COM5 meldet sich kein ESP32" | anderer Anschluss (ports_zeigen), oder Thonny hält den Anschluss noch belegt. Bei manchen Brettern BOOT beim Einstecken drücken |
| „llama-server hat sich sofort beendet" | zu wenig Arbeitsspeicher. Kleineres Modell: hole_paket.py --modell coder-3b oder 1.5b |
| Modell antwortet, ruft aber kein Werkzeug | kommt bei kleinen Modellen vor. Menüpunkt [7] macht dieselben Schritte mit fester Reihenfolge |
| ABNAHME NICHT BESTANDEN | kein Fehler des Pakets, sondern sein Zweck. Die Befunde sagen, welche Zahl nicht stimmt; das Modell berichtigt den Quelltext und prüft erneut |
| „ist abgebrochen (Rückgabewert 1)" | das erzeugte Programm hat einen Fehler. Die Meldung darunter nennt Datei und Zeile |
| „machine.I2C ist nicht nachgebildet" | das Programm benutzt etwas, das der Lauf ohne Hardware nicht kennt. Dann hilft nur das Gerät selbst |
| „Es blieben N Dateien zurück" | eine Datei ist noch geöffnet (Editor, serieller Monitor). Schließen, Aufräumen wiederholen |
| „pip ließ sich nicht einrichten" | meist ein Virenscanner, der get-pip.py abfängt. Ordner als Ausnahme eintragen |
| Kein Python gefunden | START.bat packt dann das mitgelieferte aus. Für Menüpunkt [4] genügt das nicht — Füllen braucht ein Python mit pip |
Menüpunkt [8] Bericht sammeln schreibt alles, was zur Beurteilung von außen
nötig ist, in eine Datei BERICHT_<Datum>.txt neben
START.bat: dieser Rechner, was im Paket liegt und was fehlt, die Selbstprüfung mit
jedem Punkt, jedes Werkzeug einmal aufgerufen, das Protokoll des letzten Laufs und der Inhalt
der Ablage.
Diese Datei weitergeben genügt — niemand muss danebensitzen und erklären, was er gesehen hat. Benutzer- und Rechnername sind durch Platzhalter ersetzt: der Bericht soll sagen, was das Paket tut, nicht wem der Rechner gehört.
ablage\protokoll.txt hält jeden Werkzeugaufruf mit Uhrzeit fest. Es wird beim
Aufräumen mit gelöscht — wer es behalten will, kopiert es vorher heraus.
python agent\agent.py --werkzeuge was es gibt
python agent\agent.py --probe jedes einmal aufrufen
python agent\pfade.py was im Paket fehlt
python agent\werkzeuge\ports_zeigen.py "{}" ein Werkzeug einzeln
Dieses Blatt ist die Datei AUFGABE.md des Pakets, unveraendert; sie liegt auch als PDF bei.
Gesetzt vom Auftraggeber am 04.10.2026, 12:40 Uhr, wörtlich (Tippfehler bereinigt). Dieses Blatt ist die Quelle; ANFORDERUNGEN.md und PRUEFPROTOKOLL.md tragen denselben Text als ersten Kasten, und pruefe_alles.py (Prüfung Z0) schlägt an, sobald er irgendwo fehlt oder abweicht. Er muss nach keinem Absturz neu geschrieben werden.
„Ziel der Kurs-KI ist es, auf einem Ordner ein SLM oder kleines LLM speziell für die Python-Programmierung zusammen mit einem dafür passenden Agenten und den Python-Werkzeugen auf einen einzigen Ordner zu installieren. Das System soll Python-Programme auf Anforderung schreiben und selbst testen können, um Syntaxfehler über den Agenten selbst zu korrigieren, dann entweder simulieren oder direkt auf die Hardware laden. Das alles muss so geschehen, dass der Anwender nichts laden muss; es muss ohne Internetzugang funktionieren, auch alle Treiber müssen vorhanden sein. Es wird nichts installiert außer eventuell nötigen Treibern, und alles läuft nur mit den Werkzeugen auf dem besagten Ordner; es wird kein schon vorhandenes Python verwendet, keine Libs, die irgendwo gefunden wurden, nichts sonst — alles muss mitgeliefert werden. Ich will nicht sehen: ‚es muss noch nachgeladen werden‘.”
| Satz der Aufgabe | Folge für das Paket | gemessen durch | |
|---|---|---|---|
| 1 | SLM/LLM speziell für die Python-Programmierung | ein Coder-Modell (Qwen2.5-Coder) ist gesetzt, nicht Option; Instruct bleibt nur, wenn Coder beim Werkzeugprotokoll messbar schlechter ist | Vergleich auf dem Prüfstand: Schritte bis FERTIG, Abnahmen, Formatfehler |
| 2 | dafür passender Agent, Python-Werkzeuge, ein einziger Ordner | alles unter einer Wurzel, kein Pfad außerhalb | pruefe_unversehrtheit.py, Nachweis vorher/nachher |
| 3 | schreibt auf Anforderung, testet selbst, korrigiert Syntaxfehler über den Agenten | programm_testen mit Erwartung, Berichtigungsschleife, FERTIG erst nach bestandener Abnahme |
G2–G4 |
| 4 | dann simulieren oder direkt auf die Hardware | virtuelle LED und echter ESP32 (flashen, übertragen) | Säulen Agent und Hardware im Prüfprotokoll |
| 5 | Anwender lädt nichts, kein Internet, alle Treiber dabei | Vorrat statt Netz; CH340-Treiber im Paket; nichts installiert außer eventuell dem Treiber | A1–A3, E5 |
| 6 | kein vorhandenes Python, keine fremden Libs, alles mitgeliefert | nur paket\python, nur Räder aus paket\; das Selbstfüllen über ein fremdes Python ist ein Vorbereitungsschritt des Dozenten mit Netz, nie ein Schritt im Kurs |
A4, C5, E5 |
| 7 | nie zu sehen: „es muss noch nachgeladen werden” | im Kursbetrieb (volles Paket) erscheint keine Nachlade-Meldung; fehlt etwas, sagt START.bat was fehlt und dass der Dozent das Paket füllt | F-Gruppe, Lauf auf C:\Kurs_Agent |
Maßstab bleibt der Satz vom 04.10.2026, 1:30 Uhr: alles muss echt auf dem Rechner des Auftraggebers laufen — LLM, Agent, Werkzeuge, Hardware.
Dieses Blatt ist die Datei ANFORDERUNGEN.md des Pakets, unveraendert; sie liegt auch als PDF bei.
Stand 05.10.2026. 106 Punkte in elf Gruppen. Jede Anforderung ist so gefasst, dass sie scheitern kann: es steht dabei, woran man sie misst. Was nur maschinell prüfbar ist, prüft pruefe_alles.py.
Die Aufgabe — gesetzt am 04.10.2026, 12:40 Uhr (Quelle:
AUFGABE.md): „Ziel der Kurs-KI ist es, auf einem Ordner ein SLM oder kleines LLM speziell für die Python-Programmierung zusammen mit einem dafür passenden Agenten und den Python-Werkzeugen auf einen einzigen Ordner zu installieren. Das System soll Python-Programme auf Anforderung schreiben und selbst testen können, um Syntaxfehler über den Agenten selbst zu korrigieren, dann entweder simulieren oder direkt auf die Hardware laden. Das alles muss so geschehen, dass der Anwender nichts laden muss; es muss ohne Internetzugang funktionieren, auch alle Treiber müssen vorhanden sein. Es wird nichts installiert außer eventuell nötigen Treibern, und alles läuft nur mit den Werkzeugen auf dem besagten Ordner; es wird kein schon vorhandenes Python verwendet, keine Libs, die irgendwo gefunden wurden, nichts sonst — alles muss mitgeliefert werden. Ich will nicht sehen: ‚es muss noch nachgeladen werden‘.”
Der Maßstab über allem — gesetzt am 04.10.2026: „Alles muss echt laufen auf meinem Rechner, alles inklusive LLM, Agent, Werkzeugen, Hardware. Das ist gesetzt.” Keine Anforderung dieses Blatts gilt als erfüllt, solange sie nur unter Wine, im Simulator, im Browser-Nachbau oder auf dem Linux-Prüfstand bestanden hat. Erfüllt heißt: auf
C:\Kurs_Agent, mit Protokoll und Bildschirmfoto. Den Stand je Säule führtPRUEFPROTOKOLL.mdan erster Stelle; am 04.10.2026 fehlt darin noch das Sprachmodell (Smart App Control sperrt llama.cpp auf diesem Rechner).
Der Kursrechner hat Windows und sonst nichts. Kein Python, kein Netz, keine Adminrechte.
| Anforderung | geprüft durch | |
|---|---|---|
| A1 | Das Paket bringt alles mit, was es braucht: Python, pip, Pakete, Firmware, Sprachmodell, Treiber. | agent/pfade.py meldet jeden Teil als „gefunden” |
| A2 | Im Kurs wird nichts aus dem Netz geholt. | Lauf mit getrennter Verbindung |
| A3 | Es wird nichts installiert: kein Installationsprogramm, keine Registrierung, kein Dienst, keine Adminrechte. | Durchsicht aller Programmtexte; nachweis_autark |
| A4 | Im Kursbetrieb wird ein vorhandenes Python nicht gesucht und nicht benutzt. Jeder Aufruf geht über das Python aus dem Paket. | pruefe_alles.py A4: keine Suche außerhalb des Füllzweigs, das gefundene Python nur für hole_paket.py, python_exe() zeigt stets in die Ablage — mit Gegenprobe |
| A5 | Kein fester Pfad und kein fester Laufwerksbuchstabe. Alles leitet sich vom Ort der START.bat ab. |
Suche nach C:\ in allen Programmtexten |
| A6 | Ohne Sprachmodell läuft alles Übrige weiter — Werkzeuge, Abnahme, virtuelle LED, Flashen, Nachweis, Aufräumen. | agent.py --drehbuch |
| A7 | Doppelklick genügt auch beim ersten Mal. Ist das Paket leer oder unvollständig, sagt START.bat das, sucht für diesen einen Schritt ein Python mit pip — jeden Fundort, nicht nur den ersten; der Platzhalter des Windows-Stores wird am Namen übersprungen —, nennt es und füllt. Keine Kommandozeile, kein getippter Befehl. |
pruefe_alles.py F8; Lauf unter Wine; erster echter Windows-Lauf 03./04.10.2026 |
| A8 | Vollständig heißt alle Teile. Ob zu füllen ist, entscheidet nicht eine Datei (Python), sondern die Liste aller Bestandteile in agent/pfade.py (--fehlt). Ein halb gefülltes Paket geht nie stillschweigend ins Menü. |
pfade.py --fehlt liefert 1, solange etwas fehlt; START.bat fragt danach vor jedem Start |
| A9 | Der Vorrat kommt vor dem Netz — für jede Datei. Was schon auf dem Rechner liegt (Paket nebenan, X:\Kurs_Agent\paket auf jedem Laufwerk, C:\Projekte\Kurs_Agent\paket, Downloads), wird kopiert, nicht geladen; ohne Netz wird gar kein Download versucht. Liegt irgendwo ein volles Paket, füllt sich ein neues ohne Internet. |
Gegenprobe in hole_paket.py (Vorrat ohne Netz → kopiert; nichts im Vorrat ohne Netz → klare Abweisung) |
| A10 | Laden heißt fertig laden. Eine Datei gilt erst als da, wenn sie vollständig ist (.teil bis zum Schluss); ein Abbruch wird an derselben Stelle fortgesetzt (HTTP Range), drei Anläufe je Datei, und ein gescheiterter Schritt reißt die übrigen nicht mit. |
laden(); Füllprotokoll |
| A11 | Eine Signaturpflicht des Rechners (Smart App Control) wird vor dem Start erkannt und in Worten gemeldet — nicht erst durch ein Fehlerfenster. Sperrt sie llama.cpp, läuft der Agent von selbst ohne Modell weiter (A6), mit demselben Ablauf und derselben Abnahme; Grund und Ausweg stehen in der Oberfläche. | modell.signaturpflicht(); pruefe_rechner.py --kurz; Ereignis kein_modell in der Oberfläche |
| A12 | Jeder Lauf hinterlässt eine Spur. START.bat schreibt letzter_lauf.txt mit Marke an jeder Weggabelung, hole_paket.py schreibt fuellen_protokoll.txt samt vollständigem Fehlerbericht. Ein Lauf, der keine Spur hinterlässt, lässt sich nicht beurteilen. |
beide Dateien nach jedem Lauf im Paketordner |
Was der erste echte Windows-Lauf lehrte (03./04.10.2026): Unter Wine war all das geprüft und grün. Auf dem echten Rechner scheiterte der erste Start an vier Dingen, die Wine nicht kennt — dem Store-Platzhalter von where python, einer Zeitüberschreitung bei GitHub, dem „fertig”-Kriterium am halb gefüllten Paket und der Signaturpflicht von Smart App Control. Keines davon war ein Fehler des Konzepts; jedes war ein Fehler darin, was als geprüft galt. Daraus A8–A12.
Ausnahme, benannt und eng gefasst: Das Füllen des leeren Pakets braucht einmalig ein Python mit pip und eine Internetverbindung — im leeren Paket liegt ja noch keines. Diese eine Stelle sucht eines, prüft ob pip darin läuft, nennt es beim Namen und fragt, bevor sie etwas holt. Sie benutzt es ausschließlich für hole_paket.py; jeder andere Aufruf im ganzen Vorgang geht über das Python aus dem Paket. Auch dabei bleibt der Rechner unberührt: PIP_CACHE_DIR und PYTHONNOUSERSITE zeigen in den Kursordner, nicht ins Benutzerprofil (B3, B4). Das geschieht auf dem Vorbereitungsrechner, nie auf dem Kursrechner — dorthin wandert der gefüllte Ordner.
Nicht Teil des Pakets: Die Prüfbrücke, über die dieses Paket während der Erprobung aus der Ferne beobachtet wird, gehört nicht dazu. Das Paket kennt sie nicht, braucht sie nicht und läuft ohne sie; nachgeprüft: kein Programmtext des Pakets nennt sie.
Läuft auf dem Rechner bereits Thonny, eine Arduino-Umgebung oder ein eigenes Python, darf der Kurs daran nichts ändern und nichts blockieren.
| Anforderung | geprüft durch | |
|---|---|---|
| B1 | Ein vorhandenes Python wird nicht gestartet, nicht gelesen, nicht verändert. | A4 |
| B2 | Dessen site-packages bleiben unberührt; es wird nie dorthin installiert. |
nachweis_autark vorher/nachher |
| B3 | Das Benutzer-Paketverzeichnis (%APPDATA%\Python) wird nicht beschrieben. |
PYTHONNOUSERSITE=1 in umgebung() |
| B4 | Der pip-Zwischenspeicher des Benutzers wird nicht benutzt. | PIP_CACHE_DIR zeigt in die Ablage |
| B5 | PATH und die Umgebungsvariablen des Rechners bleiben unverändert. |
setlocal in START.bat; nachweis_autark |
| B6 | Ein belegter Netzwerkport wird nicht übernommen, sondern ausgewichen. | Gegenprobe: Port besetzen, Oberfläche starten |
| B7 | Ein belegter COM-Anschluss wird nicht erzwungen; es wird gemeldet, wer ihn hält. | Fehlermeldung von esp32_firmware |
| B8 | Zwei gleichzeitige Läufe im selben Ordner werden verhindert, nicht geduldet. | Sperrdatei; Gegenprobe |
| B10 | Jeder Programmstart reicht die abgeschirmte Umgebung weiter — ein einziger ohne sie genügt für ein halb fremdes Python. | pruefe_alles.py B10, mit Gegenprobe |
| Anforderung | geprüft durch | |
|---|---|---|
| C1 | Geschrieben wird ausschließlich in <Kursordner>\ablage\. |
in_der_ablage() im Werkzeugrahmen |
| C2 | Ein Pfad, der aus der Ablage hinausführt, wird abgewiesen — auch über ... |
Gegenproben mit ../../tmp, /etc, C:\Windows |
| C3 | Absolute Pfade werden abgewiesen, nicht stillschweigend umgedeutet. | Gegenprobe |
| C4 | Während eines vollständigen Laufs entsteht außerhalb des Kursordners keine Datei und ändert sich keine. | beweis.py: Dateisystem vorher/nachher |
| C5 | Das mitgelieferte paket\ wird nur gelesen, nie beschrieben. |
Prüfsumme vorher/nachher |
Ausnahme, benannt: Öffnet die Oberfläche den Browser, schreibt der Browser in sein eigenes Profil (Verlauf, Zwischenspeicher). Das ist eine Spur außerhalb des Kursordners, die nicht vom Paket stammt, aber von ihm ausgelöst wird. Wer das nicht will, ruft die Adresse von Hand auf.
Zweite Ausnahme, benannt: Der Wächter lässt %TEMP% zu (waechter._erlaubt). Nicht aus Nachlässigkeit, sondern weil Python selbst dort arbeitet — beim Entpacken, beim Übersetzen, bei jedem tempfile. Ein Schreibversuch dorthin wird also nicht gemeldet. Windows räumt diesen Ordner selbst auf; eine bleibende Veränderung am Rechner entsteht nicht. Wer es genau wissen will: pruefe_unversehrtheit.py zählt auch die Spuren in %TEMP% mit und nennt sie einzeln.
| Anforderung | geprüft durch | |
|---|---|---|
| D1 | Alles Erzeugte liegt in einem Ordner und wird mit einem Befehl gelöscht. | aufraeumen |
| D2 | Nach dem Löschen wird nachgezählt; Reste werden mit Grund gemeldet. | aufraeumen zählt nach |
| D3 | Ein Programm, das eine Datei offen hält (der Modellserver), wird vorher beendet — und nur dieses. | Prozessnummer aus llama.pid, Gegenprobe |
| D4 | Nach dem Aufräumen ist der Rechner nachweislich im Ausgangszustand. | nachweis_autark vorher/nachher |
| D5 | Derselbe Ordner läuft danach wieder, beliebig oft. | drei volle Zyklen, Prüfsumme gleich |
| D6 | Bei Betrieb aus der Kopie löscht sich der Arbeitsordner selbst. | START.bat, Betriebsart [2] |
| Anforderung | geprüft durch | |
|---|---|---|
| E1 | Das Paket läuft vom USB-Stick und von der Festplatte, ohne Änderung. | A5 |
| E2 | Ein Befehl stellt den weitergabefertigen Ordner zusammen, ohne Entwicklungsreste. | baue_stick.py |
| E3 | Fehlt etwas im Paket, wird es beim Bauen und beim Start gemeldet, nicht erst im Kurs. | pfade.bericht(), baue_stick.py |
| E4 | Derselbe Stick startet auf Rechnern verschiedener Größe; das Modell wird beim Start gewählt. | modell.waehlen(), Gegenproben bei 52/7,5/5/3/1 GB |
| E5 | Der Vorrat ist vollständig: jedes erlaubte Paket liegt bei, und jede geltende Abhängigkeit davon. | pruefe_alles.py E5 rechnet die Metadaten durch; Gegenprobe |
| Anforderung | geprüft durch | |
|---|---|---|
| F1 | Doppelklick auf START.bat genügt; keine Kommandozeile nötig. |
— |
| F2 | Die Aufgaben sind anklickbar, nicht zu tippen. | Oberfläche, vier Karten |
| F3 | Jeder Schritt ist sichtbar: Werkzeug, Werte, Ergebnis, Urteil. | Oberfläche |
| F4 | Ein gesperrter Knopf sagt, warum. | Oberfläche sperrt während des Laufs, Ampel zeigt „läuft” |
| F5 | Jede Fehlermeldung nennt die Ursache und den nächsten Schritt. | Durchsicht aller Meldungen |
| F6 | Löschen wird bestätigt, bevor es geschieht. | Rückfrage im Browser |
| F7 | Die Anleitung nennt dieselben Menünummern wie START.bat — wer ihr folgt, drückt die richtige Taste. |
pruefe_alles.py F7, mit Gegenprobe |
| F8 | Die Kurs-Seite (Anleitung) enthält eine genaue Beschreibung mit Funktionsskizze: was das Sprachmodell tut, was der Agent tut (Schleife, Regeln, Abnahme, Gedächtnis des Gesprächs), was jedes Werkzeug tut, wie Erwartung, Prüfung und Gerät zusammenhängen — als beschriftete Zeichnung, nicht als Aufzählung. Anweisung vom 04.10.2026: „im Kurs-HTML auch später die genaue Beschreibung mit schöner Funktionsskizze hinterlegen: Beschreibung des LLM, des Agenten, der Werkzeuge etc.” Offen. | Durchsicht der Anleitung; die Skizze wird aus den Werkzeugbeschreibungen erzeugt, nicht abgeschrieben |
Das Paket zeigt denselben Entwicklungsprozess, mit dem auch ernsthafte Arbeit entsteht.
| Anforderung | geprüft durch | |
|---|---|---|
| G1 | Das Modell schreibt das Programm, prüft es selbst und liefert erst dann aus. | Anweisung, Drehbuch, echter Lauf |
| G2 | Der Prüfschritt ist eine Abnahme gegen eine vorher genannte Erwartung, keine Vorführung. | erwartet-Feld; ohne Erwartung sagt das Werkzeug das |
| G3 | Die Abnahme kann durchfallen — und tut es bei falschem Takt, falschem Anschluss, fehlendem Takt, Absturz. | vier Gegenproben |
| G4 | Ein Agent darf sich nicht für fertig erklären, solange die letzte Prüfung fehlschlug. | pruefe_schleife.py, acht Punkte |
| G5 | Ein Fehler ist eine Nachricht, kein Abbruch: das Modell bekommt ihn und berichtigt. | echter Lauf: NICHT BESTANDEN → berichtigt → BESTANDEN |
| G6 | Dieselbe Datei, die geprüft wurde, geht unverändert auf die Hardware. | programm_testen ändert den Quelltext nicht |
| G7 | Die Erwartung setzt der Mensch: steht sie im Auftrag (pins, takt_hz), gilt genau sie. Das Modell kann sie nicht umschreiben, damit sein Programm besteht. |
pruefstand/pruefe_regeln.py: Modell nennt 0,5 Hz, Auftrag 1,0 Hz → geprüft wird 1,0 Hz, Hinweis an das Modell |
| G8 | Eine Änderung, die seit der letzten Prüfung nicht geprüft wurde, oder eine durchgefallene letzte Prüfung lässt kein FERTIG zu. Das Modell wird bis zu dreimal zurückgewiesen; dann endet der Lauf als NICHT ABGENOMMEN, nie als FERTIG. | pruefstand/pruefe_ungeprueft.py: ungeprüfte Fassung → abgewiesen → geprüft → FERTIG; dreimal FERTIG ohne Prüfung → NICHT ABGENOMMEN |
| G9 | Geprüft wird nur, was in diesem Lauf geschrieben wurde; eine Datei aus einem früheren Lauf kann kein Ergebnis liefern. | pruefe_regeln.py: programm_testen fremd.py → FEHLER „noch nicht geschrieben” |
| G10 | Ein Werkzeugaufruf wird auch dann erkannt, wenn ein kleines Modell das Wort WERKZEUG: weglässt — der Name eines bekannten Werkzeugs am Zeilenanfang mit JSON genügt; ein Name mitten im Satz nicht. |
pruefe_regeln.py, vier Fälle mit Gegenproben |
| G11 | aufraeumen steht dem Modell nicht zur Verfügung: Es beendet den Modellserver und löscht die Ablage samt Protokoll. Ruft das Modell es dennoch auf, bekommt es eine Abweisung, der Lauf geht weiter. Aufgeräumt wird am Kursende über den Knopf. |
pruefe_regeln.py: Aufruf abgewiesen, Ablage und Protokoll bleiben |
| G12 | Das Modell im Paket ist ein Coder-Modell (Qwen2.5-Coder, 3B/7B), weil die Aufgabe ein Modell speziell für Python verlangt; bei gleicher Größe wird es dem Instruct-Modell vorgezogen. Instruct bleibt Rückfall. | hole_paket.py --modell passend holt Coder; modell.waehlen sortiert Coder vor; Messreihe 04.10.2026 |
| Anforderung | geprüft durch | |
|---|---|---|
| H1 | Der ESP32 darf fabrikneu oder beliebig vorprogrammiert sein. | erase_flash + Zustandsbericht |
| H2 | Vor dem Schreiben wird geprüft, ob dort überhaupt ein ESP32 antwortet. | esp32_firmware, Abbruch ohne Antwort |
| H3 | Der Anschluss wird nie geraten; ports_zeigen schlägt vor, der Mensch bestätigt. |
Werkzeugtext |
| H4 | Die USB-Treiber liegen im Paket, von der Herstellerseite, mit Prüfsummen. | paket\treiber\LIESMICH.md |
| H5 | Der Agent installiert keinen Treiber; das entscheidet ein Mensch. | kein Werkzeug dafür |
| H6 | Ohne Hardware läuft die ganze Kette bis zur Abnahme. | Beispiel 2 |
| H7 | Vom Gerät zurücklesen: ob die LED wirklich blinkt, wird auf dem ESP32 selbst gemessen (Pegel, Wechsel, Takt) und gegen dieselbe Erwartung gehalten — der zweite, unabhängige Weg neben programm_testen. |
esp32_nachlesen; 04.10.2026 an COM3: 1,04 Hz bestanden, Gegenprobe gegen 2 Hz durchgefallen, 2-Hz-Programm 2,10 Hz |
| H8 | Das Rücklesen misst Flanken per Interrupt mit dem Mikrosekundenzähler des Geräts, nicht durch Abtasten. | Laptop 04.10.2026: 2,0000 s / 0,500 Hz |
| H9 | esp32_uebertragen liest nach dem Neustart am Gerät nach, wenn eine Erwartung bekannt ist. |
Werkzeugtext |
Benannt und gewollt: Der ESP32 wird verändert — sein Speicher wird gelöscht und neu beschrieben. Das ist die einzige bleibende Änderung, die das Paket macht, und sie trifft das Steckbrett, nicht den Rechner.
Im Kurs sitzt niemand daneben, der erklärt, was er sieht. Es muss eine Datei geben, die das für ihn tut.
| Anforderung | geprüft durch | |
|---|---|---|
| I1 | Ein Befehl erzeugt eine Datei, die zur Beurteilung von außen genügt: Rechner, Paket, Selbstprüfung, Werkzeugprobe, Protokoll, Ablage. | sammle_bericht.py, sechs Abschnitte |
| I2 | Der Bericht nennt weder Benutzer- noch Rechnernamen. | Gegenprobe: Rechnername im Bericht suchen |
| I3 | Fehlt etwas — ein Werkzeug, das eigene Python, das Modell — steht das im Bericht, statt den Bericht scheitern zu lassen. | Lauf ohne gefülltes Paket |
| I4 | Die Frage „veraendert das meinen Rechner?“ lässt sich selbst beantworten, ohne uns zu fragen. | pruefe_unversehrtheit.py: Durchsicht, Verbotsliste und gemessener Lauf |
| I5 | Bricht der Agent ab, bleibt ein Fehlerbericht (ablage\fehlerbericht.txt): Auftrag, Fehler, Rückverfolgung, Modell, Signaturpflicht, die letzten 40 Protokollzeilen, was zu tun ist. Das Protokoll endet mit ABBRUCH und ENDE, nie mitten im Satz. |
pruefe_regeln.py: erzwungener Abbruch → Bericht und Protokollende vorhanden |
| I6 | Ist das Kontextfenster des Modells voll, endet der Lauf nicht: ältere Schritte werden zusammengefasst, der Lauf geht weiter. Werkzeugergebnisse gehen gekürzt ins Gedächtnis des Modells, vollständig ins Protokoll. | pruefe_regeln.py: KontextVoll → Zusammenfassung → FERTIG |
Benannt: Ein Bericht wandert zu jemandem, der ihn liest. Er soll sagen, was das Paket tut, und nicht, wem der Rechner gehört.
Anweisung des Auftraggebers (04.10.2026): „Am Ende muss wie auch hier immer die Möglichkeit zur Eingabe der nächsten Anweisung bestehen … unten immer das Eingabefeld, oben der Kopf, und das Fenster mit der Ausgabe wird gescrollt bei Bedarf … ein Test ist dann, über die Eingabe zu sagen: verwende einen anderen Pin, oder ändere die Blinkfrequenz, oder prüfe zuerst, bevor du das Programm runterlädst, oder ich gebe selbst ein Programm ein zum Überprüfen.”
| Anforderung | geprüft durch | |
|---|---|---|
| J1 | Die Oberfläche ist ein Gespräch: Kopf oben, Verlauf in der Mitte (scrollt, folgt dem Leser), Eingabefeld immer unten. Nach jeder Anweisung ist die nächste möglich. | Browser-Prüfung (Playwright): Lage der drei Bereiche, Eingabe nach dem Ende frei, Verlauf folgt bis unten |
| J2 | Der Agent behält den Zusammenhang: Verlauf, geschriebene und abgenommene Dateien, genannte Anschlüsse, die Erwartung; der Modellserver wird nicht je Anweisung neu geladen. | pruefstand/pruefe_gespraech.py: sechs Anweisungen, ein Modellstart, Verlauf > 20 Nachrichten |
| J3 | Anderer Pin / andere Frequenz aus einem Satz („Nimm GPIO 4”, „10 Hz”, „5-mal pro Sekunde”): die Erwartung wird Stück für Stück fortgeführt, die betroffene Datei gilt als neu zu prüfen, FERTIG erst nach bestandenem Test gegen die neue Erwartung. | pruefe_gespraech.py Anweisungen 2, 2b, 3; Browser mit Coder-3B 1 Hz → GPIO 4 → 10 Hz |
| J4 | Erst prüfen, dann laden: esp32_uebertragen nimmt nur eine Datei, die zuletzt geprüft und bestanden hat und seitdem unverändert ist. |
pruefe_gespraech.py Anweisung 4 |
| J5 | Der Anschluss kommt vom Menschen: ein Anschluss, den keine Anweisung genannt hat, wird nicht verwendet; der Agent soll fragen. | pruefe_gespraech.py Anweisung 4 (COM9 abgewiesen, COM3 genannt) |
| J6 | Eigenes Programm: steht in der Anweisung ein Codeblock (), schreibt der Agent ihn wörtlich in die Werkstatt — kein Abschreiben durch das Modell —, und das Modell prüft nur noch. |
pruefe_gespraech.py Anweisung 5: Inhalt byteweise gleich |
| J7 | Mehrere Werkzeugaufrufe in einer Antwort werden der Reihe nach ausgeführt; ein Aufruf ohne JSON gilt als leere Eingabe; ein FERTIG, das etwas behauptet, was kein Werkzeug getan hat („auf den ESP32 überspielt”), wird zurückgewiesen. | pruefe_regeln.py |
| J8 | Agent und Modellanbindung lassen sich im Stillstand neu laden (/neuladen), die Seite wird je Aufruf gelesen — Korrekturen des Dozenten brauchen keinen Neustart. |
04.10.2026: dreimal angewendet |
| J9 | Sagt das Modell ein zweites Mal FERTIG, ohne die geänderte Datei geprüft zu haben, prüft der Agent selbst — einmal je Anweisung, sichtbar als eigener Aufruf, mit der Erwartung des Menschen (ESP32-Programm → programm_testen, sonst programm_ausfuehren). Der Prüfschritt ist nicht verhandelbar. |
pruefe_ungeprueft.py; Browser 04.10.2026 15:09: „AGENT PRUEFT SELBST blink.py” → BESTANDEN → FERTIG |
| J10 | Quereingabe: Das Eingabefeld bleibt während des Laufs offen; eine Eingabe wird als Zwischenruf eingereiht und beim nächsten Schritt aufgenommen (Anschluss nennen, Erwartung ändern, korrigieren). Anschlüsse gelten auch als „com 3”. | pruefe_gespraech.py |
| J11 | Was eine Anweisung verlangt (laden, nachlesen), muss in dieser Anweisung gelaufen sein; eine Behauptung im FERTIG ohne Werkzeug wird zurückgewiesen, dreimal: NICHT ABGENOMMEN. | pruefe_gespraech.py 5b |
| J12 | Die Oberfläche zeigt bei länger laufenden Werkzeugen einen Fortschrittsbalken aus der erwarteten Dauer („den Download anzeigen”). | Browser |
| J13 | Ergebnisoffen: Das Modell antwortet frei. Gruß, Frage, Bemerkung werden in Worten beantwortet, eine Aufgabe mit Werkzeugen. Der Agent steuert nicht (kein Zwang zum Werkzeugaufruf, kein Nachhaken), er wacht über die Ehrlichkeit: Erwartung des Menschen bleibt, nichts wird behauptet, kein Anschluss geraten, nur Geprüftes aufs Gerät. Anlass 05.10.2026: „hallo bist du bereit?” wurde zu einem erfundenen Blinkauftrag; „keine ergebnisoffene Eingabe, sondern alles vorgegeben, das war nicht der Sinn der Übung”. | pruefe_gespraech.py 5c; Laptop-Gespräch |
| J14 | Was der Mensch an der Erwartung nicht festlegt, legt der erste Aufruf des Modells fest und bleibt (sonst wandert sie von 10 Hz zu 1 Hz, je nach Programm). | pruefe_gespraech.py 5d |
| J15 | Der Agent kennt die Werkzeuge und die Methode (schreiben, prüfen, berichtigen, ausliefern, nachlesen) und stellt sie dem Modell je nach dessen Fähigkeit bereit: als Beschreibung in der Anweisung, als Vorschlag im Ergebnis („NÄCHSTER SCHRITT”), als vorgerechnete Zahl (Takt) — und übernimmt den Prüfschritt selbst, wenn das Modell ihn auslässt. Das gehört ins Manuskript (Anweisung 05.10.2026). | Anweisungstext, Hinweise, pruefe_ungeprueft.py; Manuskript F8 |
| J16 | Fokus: Erzählt das Modell Arbeit, die kein Werkzeug getan hat, oder verlangt die Anweisung einen Geräteschritt und nichts lief, fragt der Agent das Modell ohne die lange Vorgeschichte nur nach dem nächsten Werkzeugaufruf (Anweisung + Aufgabe + ein Satz). Kleine Modelle folgen so, wo das Gespräch sie in Prosa hält. | pruefe_gespraech.py 5g |
| J17 | Fehlt im Prüfaufruf die Datei, nimmt der Agent die zuletzt geschriebene dieser Anweisung und sagt es; eine Behauptung in freier Rede ohne Beleg bekommt eine sichtbare Anmerkung des Agenten. | pruefe_gespraech.py 5f; Laptop 05.10.2026 9:55 |
| J18 | Die Erwartung des Menschen wird aus seinen Worten gelesen, auch Zahlwörter („eine Periode pro Sekunde”, „zweimal je Sekunde”) und die Kurvenform („sinusförmig”). Was er nicht festlegt, legt der erste Aufruf des Modells fest — außer unsichtbare Takte (> 50 Hz, Trägerfrequenz) und mindestens_wechsel. |
erwartung_aus-Proben; Laptop 05.10.2026 9:44 (1000 Hz) und 10:17 (10 Wechsel) |
| J19 | Leeres FERTIG auf eine Aufgabe („FERTIG — bereit für die nächste Anweisung”, kein Werkzeug, keine Behauptung) wird sofort zum Fokus: das Modell wird ohne Vorgeschichte nach dem ersten Aufruf gefragt. Eine früher verlangte, nie geschriebene Datei blockiert eine andere Anweisung nicht. | pruefe_gespraech.py 5h, 5i |
| J20 | Berichtigungsfokus: Sagt das Modell nach einer durchgefallenen Prüfung FERTIG, ohne etwas geändert zu haben („die Zeile wurde korrigiert”), zeigt ihm der Agent ohne Vorgeschichte die Datei, wie sie wirklich dasteht, und den Befund, und verlangt nur die berichtigte Datei; die Prüfung hängt er selbst an. Liefert das Modell dieselbe Datei Zeichen für Zeichen, wird sie nicht noch einmal geprüft. | pruefe_gespraech.py 5l; pruefe_schleife.py, pruefe_ungeprueft.py, pruefe_regeln.py |
| J21 | Unter jedem FERTIG steht, was die Werkzeuge gemessen haben (Anschlüsse, Takt, Form, Abnahme; Geräteschritte mit Ausgang) — Zahlen aus dem Werkzeug, nicht Sätze des Modells. Nennt das Modell eine Zahl, die der Messung widerspricht („Periode von 2 Sekunden” bei 2 Hz), merkt der Agent es sichtbar an. Ein Abschlusstext, der leer ist oder aus den Sätzen des Agenten besteht, wird durch den Abschluss des Agenten ersetzt. | pruefe_gespraech.py 5k, 5m |
| J22 | Geräteschritt verlangt, Anschluss genannt, Datei abgenommen: Der Agent fragt ohne Vorgeschichte nach genau diesem Aufruf; nennt das Modell ihn nicht, führt der Agent ihn selbst aus (einmal). Ein fehlgeschlagener Geräteschritt gilt nicht als gelaufen; „geladen” behauptet nach einem Fehlschlag wird zurückgewiesen, „steht aus” angenommen. Der zuletzt genannte Anschluss gilt. | pruefe_gespraech.py 4, 5b, 5n, 6 |
| J23 | Der Hinweis „dritter gleicher Fehlschlag” zählt nur Fehlschläge, an der Zeile mit dem Grund, und je Anweisung neu — nie unter einer bestandenen Abnahme. | pruefe_gespraech.py 5j |
| J24 | Verdichteter Verlauf: Zu Beginn jeder Anweisung wird das Frühere zu einem Absatz aus dem Zustand des Agenten (Dateien mit Stand, Erwartung, Anschlüsse, Messungen, Geräteschritte); die letzte Anweisung bleibt im Wortlaut. Grund: fünf Minuten je Antwort in der sechsten Anweisung (05.10.2026, 12:14–12:19). | pruefe_gespraech.py |
| J26 | Der Prüfweg richtet sich nach der Datei, nicht nach der Vorgeschichte: ein Programm ohne machine prüft der Agent mit programm_ausfuehren (Fenster erkannt an tkinter), auch wenn aus ESP32-Anweisungen davor eine Erwartung steht. Anlass 05.10.2026, 14:50: rechner.py (tkinter) wurde gegen pins [2, 4] geprüft. |
pruefe_gespraech.py 5l-e |
| J27 | Eine Kurvenform erbt nicht auf ein neues Programm — weder aus der Erwartung davor noch aus dem Aufruf des Modells; nur ein Wort des Menschen (sinusförmig, dreieckig, PWM, atmen) setzt sie. Anlass 13:33 und 14:26: zwei.py (Ein/Aus, zwei LEDs) sollte „sinusförmig“ sein. | pruefe_regeln.py, pruefe_gespraech.py 5l-d |
| J25 | Die Kopfzeile zeigt, ob ein ESP32 angeschlossen ist (serielle Anschlüsse alle 5 s, nie während ein Werkzeug läuft, Wandler erkannt); jeder laufende Werkzeugaufruf trägt einen Fortschrittsbalken mit Sekunden und erwarteter Dauer. | Laptop 05.10.2026 |
Anweisung des Auftraggebers (04.10.2026): „oder programmier mir mal einen einfachen Taschenrechner mit graphischer Ausgabe.” Die Aufgabe verlangt Python-Programme auf Anforderung — nicht nur für den ESP32.
| Anforderung | geprüft durch | |
|---|---|---|
| K1 | programm_ausfuehren führt ein beliebiges Programm aus der Werkstatt mit dem Paket-Python aus: Ausgabe, Fehlerausgabe, Rückgabewert, Zeitgrenze, Text für input(). Urteil LAUF BESTANDEN / NICHT BESTANDEN. |
Prüfstand: gutes, kaputtes und lesendes Programm |
| K2 | Ein Programm mit Fenster (tkinter) wird gestartet und beobachtet: läuft es, zeigt es ein Fenster (Titel über die Prozessnummer)? Mit offen_lassen bleibt es für den Menschen offen. |
Laptop 04.10.2026, 14:42: „Fensterprobe Kurs-Agent” erkannt, LAUF BESTANDEN |
| K3 | tkinter liegt im Paket (paket\tkinter-8.6.13-py3.12-win-amd64.zip, 3,1 MB, aus conda-forge, Lizenzen dabei); umgebung_anlegen entpackt es ins eigene Python und prüft import tkinter. Nichts davon berührt das System. |
Laptop 04.10.2026: „Gegenprobe tkinter: Tk 8.6” |
| K4 | programm_ausfuehren zählt als Prüfung wie programm_testen: ein kaputter Lauf sperrt FERTIG, ein guter gibt frei; nur in dieser Sitzung Geschriebenes wird ausgeführt. |
pruefe_regeln.py |
| K5 | programm_testen misst bei PWM die Hüllkurve des Tastgrads: Periode, Takt, Form (sinusförmig oder dreieckig, Abweichung zu beiden Bezugsformen); die Form ist Abnahmekriterium, wenn der Mensch sie nennt — „Dreieck ist kein Sinus”. PWM-Durchgänge zählen als Zustandswechsel. |
pruefstand/pruefe_pwm.py 7/7 |
| K6 | Der Nachbau rechnet mit einer gedachten Uhr: time.sleep rückt sie vor statt zu warten. Grund: Windows hält 10 ms Schlaf nicht ein (bis 15,6 ms), der ESP32 schon; ein richtiges 1-Hz-Atmen lief auf dem PC mit 0,64 Hz. Zeitstempel und Zeitgrenze folgen der gedachten Uhr; ein Lauf dauert Bruchteile einer Sekunde. Rechenbibliotheken math, random, struct sind erlaubt. |
pruefe_pwm.py, pruefe_alles.py 19/19 |
programm_testen nennt bei PWM mit zu kleinem Hub (unter 10 %) die Ursache: Vollausschlag bei duty() 1023, bei duty_u16() 65535 — Anlass 05.10.2026, 12:08: duty_u16(1023 * …), Hub 1,6 %. Das Brettwissen nennt time.sleep/time.sleep_ms als einzige Wartefunktionen (machine.delay gibt es nicht). | pruefe_pwm.py 8/8 |programm_testen schützt gegen ein Modell, das sich vertut — nicht gegen jemanden, der ihn umgehen will. Wer das braucht, führt fremden Quelltext gar nicht aus.Prof. Dr.-Ing. Ralph Wystup M.Sc. — erstellt mit KI und Agent (Claude Code, Anthropic)
Dieses Blatt ist die Datei PRUEFPROTOKOLL.md des Pakets, unveraendert; sie liegt auch als PDF bei.
Stand 04.10.2026, 13:30 Uhr. Geprüft gegen ANFORDERUNGEN.md, 96 Punkte in elf Gruppen.
Die Aufgabe — gesetzt am 04.10.2026, 12:40 Uhr (Quelle:
AUFGABE.md): „Ziel der Kurs-KI ist es, auf einem Ordner ein SLM oder kleines LLM speziell für die Python-Programmierung zusammen mit einem dafür passenden Agenten und den Python-Werkzeugen auf einen einzigen Ordner zu installieren. Das System soll Python-Programme auf Anforderung schreiben und selbst testen können, um Syntaxfehler über den Agenten selbst zu korrigieren, dann entweder simulieren oder direkt auf die Hardware laden. Das alles muss so geschehen, dass der Anwender nichts laden muss; es muss ohne Internetzugang funktionieren, auch alle Treiber müssen vorhanden sein. Es wird nichts installiert außer eventuell nötigen Treibern, und alles läuft nur mit den Werkzeugen auf dem besagten Ordner; es wird kein schon vorhandenes Python verwendet, keine Libs, die irgendwo gefunden wurden, nichts sonst — alles muss mitgeliefert werden. Ich will nicht sehen: ‚es muss noch nachgeladen werden‘.”
„Alles muss echt laufen auf meinem Rechner, alles inklusive LLM, Agent, Werkzeugen, Hardware. Das ist gesetzt.” — Anweisung des Auftraggebers
Nichts gilt als fertig, was nur unter Wine, im Simulator, im Browser-Nachbau oder auf dem Linux-Prüfstand lief. Der Nachweis ist ein vollständiger Lauf auf C:\Kurs_Agent mit Protokoll (letzter_lauf.txt, ablage\protokoll.txt) und Bildschirmfoto — für jede der vier Säulen einzeln. Dieses Blatt führt den Stand dazu an erster Stelle, vor allem anderen:
| Säule | Linux-Prüfstand | Wine | echtes Windows, Rechner des Auftraggebers |
|---|---|---|---|
| Werkzeuge (9) | ✓ | ✓ | ✓ 04.10., 1:10 — 8 Aufrufe im Drehbuch, esptool/mpremote aus den mitgelieferten Rädern |
| Agent (Schleife, Abnahme, Nachweis, Oberfläche) | ✓ | ✓ | ✓ 04.10., 1:11 — ABNAHME BESTANDEN, virtuelle LED, Nachweis „nichts verändert” |
| Hardware (ESP32 flashen, Programm übertragen) | — | — | ✓ 04.10., 1:22 — COM3, MicroPython in 41 s, blink.py übertragen, LED blinkt |
| Sprachmodell (llama.cpp, Qwen2.5 3B/7B) | ✓ 02.10., 7B fertig nach 2 Aufrufen; 04.10. 3B-Instruct und 3B-Coder | — | ✓ 04.10., 12:56 — Smart App Control EIN, signierter llama-server (Ollama Inc./DigiCert) lädt Qwen2.5-3B in 8 s; 23 Schritte mit echten Werkzeugaufrufen. Der Auftrag selbst wurde in diesem Lauf nicht sauber erfüllt (sieben Befunde, unten) — das Modell lief, der Agent wurde daran berichtigt |
Rücklesen am Gerät (esp32_nachlesen) |
— | — | ✓ 04.10., 13:17–13:19 — COM3: 1-Hz-Programm 1,04 Hz BESTANDEN; Gegenprobe gegen 2 Hz NICHT BESTANDEN; 2-Hz-Programm aufgespielt, 2,10 Hz gemessen; zurück auf 1 Hz, 1,04 Hz. Die LED blinkt, und das Gerät sagt es selbst |
Alle Säulen tragen auf dem echten Rechner ✓ (04.10.2026, 13:19 Uhr). Offen ist nicht mehr, ob die Kette läuft, sondern wie gut das Modell sie führt — siehe den Lauf von 12:56 und die Messreihe auf dem Prüfstand. Ein vollständiger Lauf mit dem berichtigten Agenten auf C:\Kurs_Agent steht als Nächstes an (Agent neu starten, Karte 2 mit Hardware).
| Umgebung | was darin lief |
|---|---|
| Linux (20 Kerne, 67 GB) | pruefe_alles.py (14 Prüfungen), agent/pruefe_schleife.py (8 Punkte), echte Agentenläufe mit Qwen2.5-7B über llama.cpp |
| Windows unter Wine 10.0 (eigener Bereich, kein fremdes Präfix angefasst) | das mitgelieferte Windows-Python 3.12.10, START.bat über cmd, alle neun Werkzeuge, pip, esptool-Bau aus Quelltext, die Weboberfläche |
| Browser (Chromium über Playwright) | die Anleitungsseite, die Weboberfläche, die virtuelle LED |
Grenze, die dazugehört: Wine ist nicht Windows. Es bildet das Verhalten nach, nicht jede Eigenheit. Was hier läuft, läuft sehr wahrscheinlich auch dort — bewiesen ist es erst auf einem echten Windows-Rechner. Die Punkte, die davon berührt sind, stehen unten unter „offen”.
Seit 04.10.2026 wird nicht mehr unter Wine geprüft (Grundsatz 33): Wine-Starts füllten zweimal die Prozesstabelle des Arbeitsbereichs, und der echte Windows-Lauf fand vier Fehler, die Wine nicht zeigte. Windows-Dinge laufen jetzt auf dem Rechner des Auftraggebers über die Brücke; die Wine-Spalte oben ist Vorgeschichte. Eine eigene Windows-VM folgt, sobald der Admin sie einrichtet.
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| A1 | Paket bringt alles mit | pfade.bericht() unter Wine |
erfüllt — Python, pip, 25 Paketdateien, Treiber gefunden; Modell fehlt noch (nicht geladen) |
| A2 | im Kurs nichts aus dem Netz | Netzwächter (socket.connect) während eines vollen Laufs |
erfüllt — keine Verbindung nach außen; Gegenprobe mit pypi.org und 1.1.1.1 schlug an |
| A3 | nichts installiert | Durchsicht + nachweis_autark unter Wine |
erfüllt — kein Installationsprogramm, keine Registrierung, keine Adminrechte |
| A4 | im Kursbetrieb kein fremdes Python | pruefe_alles.py A4 |
erfüllt — keine Suche außerhalb des Füllzweigs; das gefundene Python nur für hole_paket.py und die pip-Probe. Gegenprobe: ein where an anderer Stelle eingesetzt — die Prüfung nannte die Zeilennummer |
| A5 | kein fester Pfad | pruefe_alles.py A5 |
erfüllt — Lauf aus C:\Stick ohne Änderung |
| A6 | ohne Modell läuft der Rest | agent.py --drehbuch unter Wine |
erfüllt — alle sieben Schritte, Abnahme bestanden |
| A7 | Doppelklick genügt auch beim ersten Mal | START.bat auf leerem Ordner unter Wine, vier Fälle |
erfüllt — siehe unten |
Zu A7 — vier Fälle am leeren Ordner geprüft:
| Fall | Ergebnis |
|---|---|
| kein Python auf dem Rechner | nennt zwei Wege: gefüllten Ordner kopieren, oder Python installieren |
| Python gefunden, aber ohne pip | erkannt und abgewiesen — „darin läuft kein pip”, mit dem Hinweis auf den Store-Platzhalter |
| Python mit pip, Antwort n | „Abgebrochen — es wurde nichts geholt und nichts geändert” |
| Python mit pip, Eingabetaste | füllt, und läuft danach weiter, als wäre gerade gestartet worden |
Dabei gemessen: PIP_CACHE_DIR zeigte auf C:\LeerTest\ablage\pip_zwischenspeicher, PYTHONNOUSERSITE auf 1 — der Zwischenspeicher des Benutzers bleibt also auch beim Füllen unberührt.
Der erste Lauf fiel durch: ein verdoppeltes Caret (2^^>nul statt 2^>nul) zerriss den Batch-Block. Die Folge war schlimmer als ein Abbruch — das Skript übersprang den Füllzweig stillschweigend und meldete danach ein Python, das es nicht gab. Durch Lesen war das nicht zu sehen.
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| B1 | fremdes Python unberührt | A4 | erfüllt |
| B2 | fremde site-packages unberührt |
nachweis_autark vorher/nachher unter Wine |
erfüllt — „Nichts außerhalb des Paketordners hat sich verändert” |
| B3–5 | Benutzerpakete, pip-Cache, PYTHON-Variablen abgeschirmt | pruefe_alles.py B3-5 |
erfüllt |
| B6 | belegter Port wird nicht übernommen | Port 8777 besetzt, Oberfläche gestartet | erfüllt — wich auf 8778 aus |
| B7 | belegter COM-Anschluss | — | offen (keine Hardware) |
| B8 | zwei gleichzeitige Läufe | pruefe_alles.py B8 |
erfüllt — der zweite wird abgewiesen |
| B9 | eine fremde Umgebung stört uns nicht | PYTHONPATH, PYTHONHOME, PIP_INDEX_URL, PYTHONSTARTUP, PYTHONUSERBASE gesetzt |
teilweise — siehe unten |
Zu B9: PIP_INDEX_URL, PYTHONSTARTUP und PYTHONUSERBASE stören nicht. Bei PYTHONPATH wird ein fremdes Modul einmal geladen, bevor eine eigene Zeile läuft; der eingebaute Selbst-Neustart (agent/sauber.py) sorgt dann für einen sauberen Durchgang — die Abnahme stimmte. PYTHONHOME verhindert, dass Python überhaupt startet; das kann kein Python-Code heilen, deshalb räumt START.bat beide Variablen vor dem Start weg.
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| C1 | Wächter meldet Schreibversuche draußen | pruefe_alles.py C1 |
erfüllt — meldet den verbotenen, lässt den erlaubten durch |
| C2–3 | Ausbruch und absolute Pfade abgewiesen | pruefe_alles.py C2-3 |
erfüllt — 3 von 3 abgewiesen |
| C4 | nichts außerhalb während eines Laufs | nachweis_autark unter Wine |
erfüllt |
| C5 | paket\ bleibt unverändert |
pruefe_alles.py C5 |
erfüllt |
Zu C4: Ein Vergleich des gesamten Dateisystems vorher/nachher war zu stumpf — er fand 19 Änderungen, alle von fremden Programmen (Entwicklungsumgebung, andere Sitzungen). Auf einem benutzten Rechner ist „nichts hat sich geändert” nicht erreichbar. Deshalb misst der Wächter am Verursacher statt am Rechner.
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| D1–2 | löschen und nachzählen | pruefe_alles.py D1-2 + Wine |
erfüllt — 3778 von 3783 Dateien gelöscht |
| D3 | Modellserver wird vorher beendet | Gegenprobe mit Probeprozess | erfüllt |
| D4 | Rechner im Ausgangszustand | nachweis_autark |
erfüllt |
| D5 | beliebig wiederholbar | drei Zyklen, Prüfsumme über paket\ |
erfüllt — b7ea1793… vorher wie nachher |
| D6 | Selbstlöschung der Kopie | — | offen (Betriebsart [2] nicht unter Wine erprobt) |
Zu D1: Die letzten fünf Dateien sind das Python, mit dem das Aufräumen gerade läuft — Windows hält python.exe und die DLLs fest. Das Werkzeug meldet das jetzt ehrlich und hinterlässt eine Marke; START.bat entfernt den Rest, sobald Python beendet ist. Nachgeprüft: danach blieb nichts.
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| E1 | Stick und Platte gleichermaßen | Lauf aus C:\Stick |
erfüllt |
| E2 | baue_stick.py ohne Entwicklungsreste |
ausgeführt | erfüllt — 98 Dateien, keine Arbeitsordner |
| E3 | Fehlendes wird gemeldet | pfade.bericht(), baue_stick.py |
erfüllt — „Modell FEHLT” wird genannt |
| E4 | Modellwahl nach freiem Speicher | Gegenproben bei 52 / 7,5 / 5 / 3 / 1 GB | erfüllt — 7B / 7B / 3B / keines / keines |
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| F1 | Doppelklick genügt | START.bat unter cmd |
erfüllt — Menü erscheint, Python wird bereitgelegt |
| F2 | Aufgaben anklickbar | Oberfläche im Browser | erfüllt — vier Karten |
| F3 | jeder Schritt sichtbar | Oberfläche | erfüllt — Werkzeug, Werte, Ergebnis, Urteil |
| F4 | gesperrte Knöpfe erklärt | Oberfläche | erfüllt — Ampel zeigt „läuft …” |
| F5 | Fehlermeldung nennt den nächsten Schritt | Durchsicht aller Meldungen | erfüllt |
| F6 | Löschen wird bestätigt | Oberfläche | erfüllt — Rückfrage |
| F7 | Anleitung und START.bat nennen dieselben Nummern |
pruefe_alles.py F7 |
erfüllt — 9 Verweise stimmen; Gegenprobe mit verfälschter Nummer schlug an |
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| G1 | schreiben, prüfen, erst dann ausliefern | echter Lauf mit 7B | erfüllt |
| G2–3 | Abnahme besteht bei richtig, fällt bei falsch durch | pruefe_alles.py G2-3 |
erfüllt — vier Fälle |
| G4 | FERTIG gilt nicht nach fehlgeschlagener Prüfung | pruefe_schleife.py |
erfüllt — 8 von 8 |
| G5 | Fehler ist Nachricht, nicht Abbruch | echter Lauf | erfüllt — NICHT BESTANDEN → berichtigt → BESTANDEN |
| G6 | geprüfter Quelltext bleibt unverändert | pruefe_alles.py G6 |
erfüllt |
| G7 | Erwartung aus dem Auftrag, nicht vom Modell | pruefstand/pruefe_regeln.py |
erfüllt — 0,5 Hz des Modells durch 1,0 Hz des Auftrags ersetzt, Hinweis im Ergebnis (04.10., 13:10) |
| G8 | ungeprüfte Änderung oder durchgefallene Prüfung → kein FERTIG; nach drei Abweisungen NICHT ABGENOMMEN | pruefstand/pruefe_ungeprueft.py, 5 Punkte |
erfüllt — FERTIG genau einmal angenommen (nach bestandenem Test); dreimal FERTIG ohne Test → „Nicht abgenommen”, kein FERTIG im Protokoll |
| G9 | nur in diesem Lauf Geschriebenes wird geprüft | pruefe_regeln.py |
erfüllt — fremd.py abgewiesen |
| G10 | Aufruf ohne WERKZEUG: erkannt, Satzmitte nicht |
pruefe_regeln.py |
erfüllt — 4 Fälle |
| G11 | aufraeumen nicht fürs Modell | pruefe_regeln.py |
erfüllt — abgewiesen, Lauf endet regulär, Ablage bleibt (Prüfstand 11:21: das 3B-Modell hatte es als 9. Schritt gerufen, Server weg, Protokoll weg) |
| G12 | Coder-Modell im Paket | Messreihe 2 (unten), modell.waehlen |
erfüllt — Coder-3B nach C:\Kurs_Agent\paket\modell übertragen (04.10., 13:40), wirksam nach Neustart des Agenten |
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| H1–H3 | fabrikneu oder vorprogrammiert, Antwort vor dem Schreiben, kein Raten | Werkzeugtexte, Abbruch ohne Antwort | teilweise — die Logik greift, der Fall ohne ESP32 ist geprüft |
| H4 | Treiber im Paket mit Prüfsummen | paket\treiber\LIESMICH.md |
erfüllt — CH341SER, CH343SER; CP210x fehlt (Silabs sperrt diese Umgebung) |
| H5 | der Agent installiert keinen Treiber | Durchsicht | erfüllt — es gibt kein Werkzeug dafür |
| H6 | ohne Hardware bis zur Abnahme | voller Lauf unter Wine | erfüllt |
| H7 | vom Gerät zurücklesen | esp32_nachlesen an COM3, über die Brücke ausgelöst, 7 Schritte |
erfüllt — 1,04 Hz / 2,10 Hz / 1,04 Hz, Gegenproben durchgefallen wo sie mussten (04.10., 13:17–13:19) |
| H8 | Rücklesen mit Flankeninterrupt und Mikrosekundenzähler des Geräts statt Abtastschleife („die Quarzfrequenz ist doch bekannt”) | Laptop 20:15, 1-s/1-s-Programm | erfüllt — 2,0000 s zwischen Einschaltvorgängen, 0,500 Hz (vorher per Abtastung 1,937 s, 0,52 Hz) |
| H9 | esp32_uebertragen liest nach dem Neustart selbst am Gerät nach, wenn eine Erwartung bekannt ist („das muss man doch durch Rücklesen rausfinden”) |
Werkzeugbeschreibung, Agent reicht die Erwartung durch | eingebaut, am Gerät noch nicht einzeln gemessen |
| H10 | Zweiter unabhängiger Weg für das Verhalten nach dem Neustart: Programm meldet jedes Schalten seriell, die Brücke liest nur mit (Öffnen = Boot) | 20:08, blink_diag.py | erfüllt — „AN n” alle 500 ms fortlaufend; die Beobachtung „1 Hz” war nicht das Gerät |
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| I1 | ein Befehl, eine Datei, sechs Abschnitte | sammle_bericht.py auf Linux |
erfüllt — 9 kB: Rechner, Paket, Selbstprüfung, Werkzeugprobe, Protokoll, Ablage |
| I2 | kein Benutzer-, kein Rechnername | Gegenprobe: Rechnername im Bericht gesucht | erfüllt — nicht gefunden |
| I3 | Fehlendes steht im Bericht, statt ihn scheitern zu lassen | Lauf ohne Modell, mit nicht startbarem Python | erfüllt — „Das eigene Python ließ sich nicht starten (PermissionError). Der Bericht wurde deshalb mit /usr/bin/python3 erstellt.” |
pruefe_regeln.py, erzwungener RuntimeError | erfüllt — fehlerbericht.txt mit Rückverfolgung und 40 Protokollzeilen |pruefe_regeln.py, KontextVoll am ersten Schritt | erfüllt — zusammengefasst, Lauf endet mit FERTIG |Zu I3: Das Werkzeug entstand am 02.10.2026 um 09:57, unmittelbar vor dem Abbruch der Sitzung, und war bis zur Wiederaufnahme nie ausgeführt worden. Beim ersten Lauf zeigte sich, dass es richtig arbeitet — und dass es im Anforderungsblatt gefehlt hatte. Gruppe I ist deshalb nachgetragen; aus 47 Punkten wurden 50.
| Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| J1 | Kopf oben, Verlauf scrollt, Eingabe unten, nächste Anweisung immer möglich | Playwright gegen die Oberfläche auf dem Prüfstand (Coder-3B) | erfüllt — Lage der drei Bereiche gemessen, Eingabe nach dem Ende frei, Verlauf folgt bis unten (Abstand 0 px), 0 Skriptfehler |
| J2 | Zusammenhang über Anweisungen, ein Modellstart | pruefe_gespraech.py 19/19 |
erfüllt — sechs Anweisungen, Modellserver einmal gestartet |
| J3 | anderer Pin / andere Frequenz aus einem Satz | pruefe_gespraech.py; Browser mit Coder-3B: 1 Hz → „Nimm jetzt GPIO 4 statt 2” → „10 Hz” |
erfüllt — Erwartung {pins [4], 1 Hz} dann {pins [4], 10 Hz}; 10 Hz erst NICHT BESTANDEN, mit vorgerechneter Pause (0,05 s) BESTANDEN |
| J4 | erst prüfen, dann laden | pruefe_gespraech.py Anweisung 4 |
erfüllt — ungeprüfte Fassung wird nicht übertragen |
| J5 | Anschluss vom Menschen | pruefe_gespraech.py; Browser: Modell wollte COM5 |
erfüllt — „COM5 wurde vom Menschen nicht genannt — geraten wird nicht” |
| J6 | eigenes Programm wörtlich | pruefe_gespraech.py Anweisung 5 |
erfüllt — Inhalt byteweise gleich, Modell prüft nur |
| J7 | mehrere Aufrufe, Aufruf ohne JSON, Behauptung im FERTIG | pruefe_regeln.py 27/27 |
erfüllt |
| J8 | Neuladen ohne Neustart | dreimal am 04.10. angewendet | erfüllt — /neuladen meldet die Dateizeiten; die Seite wird je Aufruf gelesen |
| J9 | Agent prüft selbst nach FERTIG ohne Prüfung | pruefe_ungeprueft.py 6/6; Browser mit Coder-3B |
erfüllt — 13:04 Prüfstandzeit: viermal geschrieben, nie geprüft → „Nicht abgenommen”; nach der Korrektur 13:09: Selbstprüfung gegen pins [4], BESTANDEN, FERTIG |
| J10 | Quereingabe während des Laufs (Zwischenruf), „com 3” = COM3 | pruefe_gespraech.py 24/24 |
erfüllt — Eingabefeld bleibt offen, Zwischenruf wird beim nächsten Schritt aufgenommen; Anlass 19:57: „nein es ist com 3 nicht com 5” wurde nicht erkannt |
| J11 | Behauptung und Verlangen je Anweisung: „lade”, „lies nach” müssen in dieser Anweisung gelaufen sein | pruefe_gespraech.py 5b |
erfüllt — Anlass 20:10: „erfolgreich auf dem ESP32 geladen” ohne Übertragung in dieser Anweisung |
| J12 | Live am Laptop, 20:01–20:04 Uhr (Coder-3B): blink.py 2 Hz (erst 1 Hz durchgefallen, berichtigt, bestanden); Modell wollte COM5, abgewiesen, fragt; „Der Anschluss ist COM3. Lade … und lies nach”: esp32_uebertragen COM3, esp32_nachlesen 2,06 Hz BESTANDEN, ehrliches FERTIG; Taschenrechner (tkinter, 37 Zeilen) als Fenster offen, Nutzer: „der Taschenrechner funktioniert” |
Gespräch über die Brücke, Nutzer am Bildschirm | erfüllt |
| J13–J18 | ergebnisoffen, Methode bereitstellen, Fokus, fehlende Datei, Anmerkung, Erwartung aus Worten | pruefe_gespraech.py 30/30, Laptop-Gespräche 05.10.2026 9:09–10:20 |
erfüllt — „hallo bist du bereit?” → „Ja, ich bin bereit”; erfundene Arbeit („geschrieben, geprüft, übertragen” ohne Werkzeug) wird als unwahr zurückgewiesen, Fokus liefert den Aufruf; keine Behauptung ging als abgenommen durch |
pruefe_gespraech.py 5h, 5i; Laptop 11:09/11:36 | erfüllt — 11:09: viermal „FERTIG — Bereit für die nächste Anweisung” → Nicht abgenommen; nach der Korrektur 11:36: Fokus liefert schreib_datei im ersten Anlauf |pruefe_gespraech.py 5l; pruefe_schleife.py 8 Aufrufe; Laptop 11:50/12:00 | erfüllt — 11:50: dreimal „Die Zeile time.sleep(1) wurde korrigiert” ohne Werkzeug → Nicht abgenommen; nach der Korrektur 12:00: Datei + Befund ohne Vorgeschichte → berichtigt, vom Agenten geprüft, bestanden |pruefe_gespraech.py 5k, 5m; Laptop 11:40/12:01 | erfüllt — 11:40: „Periode von 2 Sekunden” bei gemessenen 1,99 Hz; 12:01: der Rügetext des Agenten als Schlusssatz des Modells |pruefe_gespraech.py 4, 5b, 5n, 6; Laptop 12:03 | erfüllt — 12:03: „Lade blink.py auf den ESP32 an COM3” ließ das Modell blink.py umschreiben (PWM!) statt zu übertragen, weil der Fokus-Hinweis pauschal schreib_datei nannte |pruefe_gespraech.py 5j; Laptop 11:39 | erfüllt — der Hinweis stand unter einer BESTANDENEN Abnahme |pruefe_gespraech.py (Zusammenfassung nennt Dateien, Erwartung, Anschlüsse) | erfüllt im Prüfstand; Anlass Laptop 12:14–12:19: fünf Minuten je Antwort in der sechsten Anweisung |pruefe_gespraech.py 5l-e; Laptop 14:50 → 15:40 | erfüllt — 14:50: rechner.py mit programm_testen gegen pins [2, 4] (FEHLER „importiert tkinter“, Abbruch nach 25 Schritten); nach der Korrektur 15:40: programm_ausfuehren, Fenster „Taschenrechner“, LAUF BESTANDEN |pruefe_regeln.py, pruefe_gespraech.py 5l-d; Laptop 13:33/14:26 | erfüllt im Prüfstand; am Laptop nicht erneut gemessen (Frage 7 scheitert ohnehin an den zwei Takten) |oberflaeche.py ist der Server selbst) — Rüge 12:15: „sehe nie einen Fortschrittsbalken zur Übertragung und nie, ob der ESP32 überhaupt verbunden ist” || Anforderung | geprüft | Ergebnis | |
|---|---|---|---|
| K1 | programm_ausfuehren: Ausgabe, Fehler, Rückgabewert, Eingabe |
Prüfstand Linux: rechne.py (2+3=5, BESTANDEN), kaputt.py (ZeroDivisionError, NICHT BESTANDEN), lies.py mit Eingabe 21 → 42 |
erfüllt |
| K2 | Fensterprogramm starten und beobachten | Laptop 14:42 über die Brücke: gui_probe.py |
erfüllt — „Nach 3,0 s läuft es noch; Fenster: ‘Fensterprobe Kurs-Agent’“, LAUF BESTANDEN |
| K3 | tkinter im Paket, ins eigene Python entpackt | umgebung_anlegen am Laptop |
erfüllt — 944 Dateien, „Gegenprobe tkinter: Tk 8.6”, Python 3.12.10 (python.org) mit _tkinter.pyd aus conda-forge |
| K4 | Lauf zählt als Prüfung | pruefe_regeln.py |
erfüllt — kaputter Lauf sperrt FERTIG, guter gibt frei |
| K5 | PWM-Hüllkurve, Form als Kriterium | pruefe_pwm.py 7/7; Laptop 10:17: Modellprogramm sinusförmig 0,97 Hz erkannt |
erfüllt |
| K6 | gedachte Uhr im Nachbau | pruefe_pwm.py, pruefe_alles.py 19/19 |
erfüllt — Läufe in 0,6 s statt 4 × 4 s; Takt unabhängig von der Windows-Uhr |
time.sleep im Brettwissen | pruefe_pwm.py 8/8; Laptop 12:08 | erfüllt — Anlass: duty_u16(1023 * …), Hub 1,6 %, Befund „fest bei 2 %” führte nicht zur Ursache; 11:36: machine.delay(1000) dreimal |Der Nachmittag des 05.10.2026 — die neun festen Anfragen, Endlauf (Coder-3B, Laptop, ESP32 an COM3; Tabelle in pruefstand/lauf_neun_fragen.json und im Reiter „Stand und Grenzen“): Vorgabe: „Die vorgefertigten Fragen müssen durchlaufen, und zwar ohne eine Fake-Sache … der Agent soll die Realität prüfen, nicht das Wunschdenken.“ Ergebnis: 1 Gruß → Antwort in Worten; 2 blink 1 Hz → FERTIG (erste Fassung 0,5 Hz durchgefallen, Berichtigungsfokus, 1,00 Hz gemessen, 63 s); 3 2 Hz → FERTIG (1,99 Hz, 111 s); 4 0,5 Hz → FERTIG (0,50 Hz, 51 s); 5 auf den ESP32 an COM3 und nachlesen → FERTIG, der Agent führte esp32_uebertragen selbst aus, Rücklesung am Gerät 0,5 Hz (35 s); 6 Sinus-Atmen → Lauf E bestanden (Form sinusförmig, 1,00 Hz, 12 min), Lauf F nicht abgenommen (cos ohne import, i ohne Definition, dreimal dieselbe Datei; 14 min); 7 zwei LEDs → Abbruch nach 25 Schritten in allen Läufen (schwere Karte); 8 Taschenrechner → im Lauf F am Agentenfehler J26 gescheitert, nach der Korrektur LAUF BESTANDEN mit Fenster „Taschenrechner“ (2,8 min); 9 Anschlüsse → FERTIG in 38 s (Python da, esptool 5.4.0 aus dem Vorrat, COM3 CH340). Unter jedem FERTIG stand die vom Werkzeug gemessene Zeile; kein Satz des Modells ging ungeprüft als Ergebnis durch. In jeder Anfrage mit Programm griff der Agent mindestens einmal ein (Fokus oder Berichtigung). Nicht erneut gemessen nach der letzten Korrektur: Frage 6 mit dem vollständigen Schleifen-Hinweis.
Der Vormittag des 05.10.2026 im Gespräch (Coder-3B, Laptop): Begrüßung und Fragen in Worten beantwortet (Hardwarefrage falsch: „LED am Bildschirm”); Blinkauftrag zunächst mit erfundener Arbeit beantwortet (viermal „geschrieben, geprüft, übertragen” ohne ein Werkzeug) — vom Agenten abgefangen, danach Fokus eingebaut; Atem-Aufgabe: 1. Anlauf PWM-Trägerfrequenz als Takt (1000 Hz) festgehalten, Dreieck statt Sinus; 2.–4. Anlauf deckten Lücken im Prüfwerkzeug auf (keine Hüllkurve, math verboten, Windows-Uhr, stilles blink.py, Wechselzahl bei PWM); 5. Anlauf läuft mit allen Korrekturen. Messreihe 3 (Coder-3B gegen Coder-7B, acht Anweisungen, derselbe Agent) läuft auf dem Prüfstand.
K erfüllt am Laptop, 20:05 Uhr: „Programmiere einen einfachen Taschenrechner rechner.py mit grafischer Oberfläche” ergab 37 Zeilen tkinter; programm_ausfuehren mit fenster und offen_lassen; Fenster „Taschenrechner” 320×239 erkannt; Nutzer: „der Taschenrechner funktioniert”.
Smart App Control EIN. Der signierte llama-server aus dem Ollama-Archiv lädt Qwen2.5-3B-Instruct in 8 s. Karte 1 („LED blinken lassen, nur geprüft”), über die Brücke gestartet, aus dem Arbeitsbereich mitgelesen. 23 Schritte, dann HTTP 400 vom Server. Was der Lauf zeigte, und was daraus wurde — jede Korrektur hat eine Gegenprobe in pruefstand/pruefe_regeln.py oder pruefe_ungeprueft.py:
| Befund im Lauf | Korrektur | Anforderung |
|---|---|---|
Schritte 1–3: das Modell schrieb schreib_datei {…} ohne WERKZEUG:; nichts wurde ausgeführt |
Name eines bekannten Werkzeugs am Zeilenanfang mit JSON gilt als Aufruf | G10 |
Schritt 4: programm_testen blink.py prüfte eine alte blink.py aus der Nacht (1 Hz) — und bestand |
geprüft wird nur, was in diesem Lauf geschrieben wurde | G9 |
| Schritte 17–21: das Modell schrieb die Erwartung von 1,0 auf 0,5 Hz um | Erwartung kommt aus dem Auftrag und ist nicht verhandelbar | G7 |
| Schritt 19/22: FERTIG mit falscher Begründung („0,5 s + 0,5 s = 1 Hz, nicht 0,5 Hz”) | wird durch G7/G8 gegenstandslos; FERTIG nach durchgefallener Prüfung wird weiter abgewiesen (G4) | G4 |
| Schritt 23: HTTP 400 — Kontextfenster 8192 voll (jeder Testlauf liefert >120 Zeilen Zeitachse) | Kontext 16384; Werkzeugergebnisse gekürzt ins Modellgedächtnis; bei KontextVoll zusammenfassen statt abbrechen | I6 |
| Protokoll endete 13:03:43, der Abbruch um 13:04:18 stand nirgends | fehlerbericht.txt, Protokollzeilen ABBRUCH/FEHLERBERICHT/ENDE |
I5 |
| Prüfstand 11:14: dritte Fassung geschrieben, nicht geprüft, FERTIG angenommen | ungeprüfte Änderung sperrt FERTIG | G8 |
Laptop Schritt 9 / Prüfstand 11:21: das Modell rief aufraeumen mitten im Auftrag — Server beendet, Ablage und Protokoll gelöscht, „Connection refused” |
aufraeumen nicht in der Werkzeugliste des Modells; Aufruf wird abgewiesen |
G11 |
| Startfenster warnte „llama.cpp ist nicht signiert” — stimmte nicht mehr | pruefe_rechner.py fragt die Datei nach ihrer Signatur |
— |
| jeder Testlauf öffnete einen neuen Browser-Reiter „Virtuelle LED” | unter der Oberfläche kein eigener Reiter mehr; die Oberfläche zeigt die LED selbst | F |
Messreihe Prüfstand (Linux, 20 Kerne), Karte 1, alter Agent: Qwen2.5-3B-Instruct 3 × schreiben, 2 × prüfen (1 durchgefallen, 1 bestanden), FERTIG nach 83 s — mit ungeprüfter dritter Fassung. Qwen2.5-Coder-3B-Instruct 2 × schreiben, 2 × prüfen (1 durchgefallen, 1 bestanden), FERTIG nach 67 s, geprüfte Fassung geliefert.
Messreihe 2 (berichtigter Agent, 11:25–11:33 Prüfstandzeit = 13:25–13:33):
| Modell | Karte 1 „blink.py, 1 Hz” | Karte 3 „zwei.py, zwei LEDs” |
|---|---|---|
| Qwen2.5-3B-Instruct | bestanden, aber 16 Werkzeugaufrufe, 95 s: nach der bestandenen Prüfung noch 14 Aufrufe ins Leere (ports, esptool, pipx, requirements.txt, COM5 …) | nicht bestanden: Datei „two.py” statt zwei.py, 2 × Syntaxfehler, 3 × Absturz, 4. Fassung ungeprüft, FERTIG beim zweiten Anlauf durchgerutscht (seither: drei Abweisungen, dann NICHT ABGENOMMEN) |
| Qwen2.5-Coder-3B-Instruct | bestanden, 4 Werkzeugaufrufe, 83 s: schreiben → NICHT BESTANDEN → berichtigen → BESTANDEN → FERTIG | nicht bestanden: Datei „two.py”, Programm blockiert in der ersten Blinkschleife, Pin 4 nie geschaltet — dreimal dieselbe Diagnose, nicht berichtigt |
Folgerung: Karte 1 kann das Coder-3B sauber, das Instruct-3B nur mit Umwegen; Karte 3 (zwei Takte gleichzeitig, nicht blockierend) überfordert beide 3B-Modelle — sie gehört zum 7B oder wird als „schwere Karte” ausgewiesen. Das Coder-Modell ist seither die Wahl (G12); beide Modelle nannten die Datei anders als der Auftrag, der Agent weist jetzt darauf hin.
Auf Weisung eigens geprüft, mit pruefe_unversehrtheit.py — drei Wege, die einander nicht glauben müssen:
| Weg | Ergebnis |
|---|---|
| Durchsicht jeder schreibenden Zeile | 52 gefunden, alle führen in den Kursordner. Das Werkzeug löst dafür Namen auf, statt zu raten: PID_DATEI → ABLAGE → WURZEL. |
| Verbotsliste: 15 Befehle, die Windows verändern | keiner kommt vor — keine Registrierung, kein setx, kein Dienst, keine Aufgabenplanung, keine Rechteänderung |
| Messung eines echten Laufs | 159 933 Dateien außerhalb des Kursordners aufgenommen: 0 neu, 0 verschwunden, 1 verändert — und das eine ist vscode.lock der Entwicklungsumgebung, nicht des Pakets |
setlocal steht im Startskript: die 24 gesetzten Variablen wirken nur im eigenen Fenster.
Vier Fehler hat diese Prüfung gefunden — zwei im Paket, zwei in der Prüfung selbst:
| Fehler | Folge | |
|---|---|---|
| 1 | esp32_firmware lud fehlende Firmware aus dem Netz und legte sie nach paket\firmware\ |
verletzte A2 (kein Netz im Kurs) und C5 (paket\ wird nur gelesen). Entfernt: fehlt sie, wird das gesagt |
| 2 | umgebung_anlegen tat dasselbe mit Python und get-pip |
dito, entfernt |
| 3 | adafruit-ampy stand auf der Erlaubnisliste, lag aber nicht im Vorrat |
das Modell liest diese Liste und hätte es anfordern können; im Kurs ohne Netz wäre es gescheitert. Gestrichen, und E5 prüft das jetzt |
| 4 | Die Prüfung selbst übersah subprocess.run(["reg","add",…]) |
ein verbotener Befehl in Listenform blieb unsichtbar. Behoben; die Gegenprobe findet ihn jetzt |
Dazu drei Befunde, die bleiben und benannt sind:
%TEMP% ausdrücklich zu — Python arbeitet dort selbst. Steht jetzt als zweite Ausnahme in Gruppe C.| prüft | Gegenprobe | |
|---|---|---|
| B10 | jeder Programmstart reicht env=umgebung() weiter |
env= an einer Stelle entfernt → Zeilennummer gemeldet |
| E5 | jedes erlaubte Paket liegt bei, und jede geltende Abhängigkeit | ein Rad aus dem Vorrat genommen → gemeldet |
| I4 | die Unversehrtheitsfrage lässt sich selbst beantworten | Spur ins Benutzerprofil und setx eingebaut → beide als schwerwiegend gemeldet |
Zu E5: Die Bedingungen sind der Kern. typing-extensions steht in cryptography, aber nur für python_full_version < '3.11'; das Paket bringt 3.12.10 mit, die Zeile gilt also nicht. Wer sie mitzählt, jagt einem Phantom nach — wer alle Bedingungen ignoriert, übersieht die echten. Geprüft: 25 Pakete, 5 erlaubte, 13 geltende Anforderungen, jede liegt bei.
Zwölf, keiner davon war durch Lesen zu sehen.
| Fehler | Folge | |
|---|---|---|
| 1 | sys.path hat beim eingebetteten Python nur zwei Einträge |
Kein Werkzeug lief. „No module named _muster” |
| 2 | umgebung_anlegen sprang bei vorhandenem Python heraus |
pip wäre nie eingerichtet worden |
| 3 | Cannot import 'setuptools.build_meta' |
esptool ließ sich offline nicht bauen |
| 4 | colorama fehlte im Paket |
pip download wertet Windows-Marker nach dem laufenden System aus |
| 5 | Extras abgeschnitten (esp-pylib[cli,ide,serial]) |
websockets fehlte |
| 6 | machine.py unauffindbar — ._pth ignoriert Arbeitsverzeichnis und PYTHONPATH |
der Prüfschritt lief nicht |
| 7 | for %%Z in (muster) findet nichts |
„Das Paket ist nicht gefüllt”, obwohl es gefüllt war |
| 8 | Expand-Archive braucht PowerShell |
Auspacken scheiterte; jetzt liegt Python ausgepackt im Paket |
| 9 | Sonderzeichen in START.bat |
G�� statt —; die Datei ist jetzt reines ASCII |
| 10 | Ausgabe mit cp1252 gelesen, UTF-8 geschrieben | UnicodeDecodeError im Nebenlauf → leere Ausgabe bei Rückgabewert 0: Das Werkzeug lief, niemand erfuhr etwas |
| Fehler | Folge | |
|---|---|---|
| 11 | nachweis_autark nahm sys.executable als „Python des Rechners” |
Es maß unseren eigenen Ordner — ein beruhigendes Ergebnis ohne Bedeutung |
| 12 | Die Oberfläche beurteilte das Ergebnis ein zweites Mal, unvollständig | Bei bestandener Abnahme fehlte die Marke. Die Beurteilung steht jetzt an einer Stelle |
Dazu: Das Aufräumen kann sich nicht selbst löschen; webbrowser.open riss die Oberfläche mit; PYTHONPATH lud fremden Code in unseren Prozess.
Stand 05.10.2026, nachmittags. Die Säulen sind gemessen: Modell unter Smart App Control über den signierten Server, Agent, Werkzeuge, ESP32 an COM3 mit Rücklesung am Gerät. Offen ist, was ein kleines Modell nicht verlässlich kann — und was hier bewusst nicht gebaut wurde.
| warum | |
|---|---|
Das 3B-Modell trifft Zahlen nicht sicher (3 Hz, 0,5 Hz erst mit vorgerechneter Ersetzung), schreibt PWM statt Ein/Aus, kennt machine.delay, from machine import time; es erzählt Arbeit und plappert Agentensätze nach |
der Agent fängt jedes davon ab (J16–J24, K7), aber jede Abfangrunde kostet 10–60 s; zwei LEDs mit zwei Takten scheitern weiter |
| Qwen2.5-Coder-7B ist auf dem Prüfstand ohne Grafikkarte 3- bis 5-mal langsamer und nicht besser (Messreihe 3: Atmen nach 25 Schritten abgebrochen) | kein Ersatz für das 3B auf einem 8-GB-Laptop; ein 30B-A3B auf 24 GB ist nicht gemessen |
| Geräteanzeige und großer Fortschrittsbalken (J25) | im Quelltext, auf C: kopiert, aber oberflaeche.py ist der Server selbst: wirksam erst nach Neustart des Agenten (START.bat) |
| D6 Selbstlöschung aus der Kopie | Betriebsart [2] nicht am Laptop erprobt |
| CP210x-Treiber im Vorrat | Silicon Labs liefert nur an Browser; der Laptop hatte den Treiber schon |
| Lauf auf einem fremden Windows-Rechner ohne den Erbauer | nur fehlerbericht.txt und das Protokoll stünden dann zur Verfügung; nicht erprobt |
—|—| | Lauf auf echtem Windows | Wine bildet nach, beweist aber nicht. Dies ist der wichtigste offene Punkt | | B7, H1–H3 am Gerät | kein ESP32 vorhanden | | D6 Selbstlöschung | Betriebsart [2] nicht erprobt | | CP210x-Treiber | Silicon Labs sperrt diese Umgebung; auf einem gewöhnlichen Anschluss lädt hole_paket.py ihn mit | | Lauf mit Modell unter Windows | das Modell wurde in den Wine-Bereich nicht geladen (4,7 GB) |
Prof. Dr.-Ing. Ralph Wystup M.Sc. — erstellt mit KI und Agent (Claude Code, Anthropic)