kimal3 0.2.6 โ 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/kimal3.js +113 -0
- package/dist/zz-kaputt.js +1 -0
- package/package.json +1 -1
package/dist/kimal3.js
CHANGED
|
@@ -32,6 +32,119 @@ import { projektListe } from "./befehle/projekt-liste.js";
|
|
|
32
32
|
import { projektNeu } from "./befehle/projekt-neu.js";
|
|
33
33
|
import { skillDatei, skillInstall } from "./befehle/skill-install.js";
|
|
34
34
|
import { wache, wacheSchalten } from "./befehle/wache.js";
|
|
35
|
+
/** Eine Meldung pro Programmlauf -- s. "Einmal-Riegel" im Block darunter. */
|
|
36
|
+
let schonGemeldet = false;
|
|
37
|
+
/**
|
|
38
|
+
* Die gekappte Leitung macht keinen Laerm mehr (D-27).
|
|
39
|
+
*
|
|
40
|
+
* ๐ด WARUM DAS HIER STEHT UND NICHT IN `endeMitHinweis`: Ein Schreibfehler auf
|
|
41
|
+
* STDOUT/STDERR kommt NICHT als Wurf zurueck, den ein try/catch faengt --
|
|
42
|
+
* er kommt als `'error'`-EREIGNIS auf dem Kanal selbst. Ohne angemeldeten
|
|
43
|
+
* Empfaenger behandelt Node ein unbehandeltes `'error'`-Ereignis als
|
|
44
|
+
* Programmabbruch, egal WELCHE Zeile gerade schreibt. Und geschrieben wird
|
|
45
|
+
* schon lange vor `endeMitHinweis` -- `haupt()` gibt bei `--version`, `--help`
|
|
46
|
+
* und jedem Befehl selbst aus. Der Empfaenger muss deshalb angemeldet sein,
|
|
47
|
+
* BEVOR die erste Zeile faellt: hier, auf Modulebene, noch vor jedem Aufruf.
|
|
48
|
+
*
|
|
49
|
+
* Gemessen (`npm run check:cli-live`, Fall a): Leitet ein Kunde
|
|
50
|
+
* `kimal3 --version | head -1`, schliesst `head` die Leitung, sobald es seine
|
|
51
|
+
* eine Zeile hat -- der naechste Schreibversuch von kimal3 trifft auf einen
|
|
52
|
+
* toten Empfaenger. Ohne diesen Empfaenger hier wirft das eine rote
|
|
53
|
+
* Stapelspur auf den Bildschirm, fuer einen Befehl, der laengst fertig war.
|
|
54
|
+
*
|
|
55
|
+
* โ ๏ธ EPIPE SCHLUCKEN, ABER NICHT ALLES (Technische Notiz der Aufgabe): Eine
|
|
56
|
+
* gekappte Leitung ist kein Fehler, den man MELDEN koennte -- der Empfaenger
|
|
57
|
+
* ist weg, niemand liest eine Meldung. Jeder ANDERE Kanalfehler ist einer und
|
|
58
|
+
* darf nicht stillschweigend verschwinden -- sonst truege ein Fehlerfall
|
|
59
|
+
* denselben Namen wie ein Erfolgsfall (vgl. die Regel zu `bestaetigungen-
|
|
60
|
+
* Aktivieren` in der Projekt-CLAUDE.md). Deshalb wird der Rueckgabewert auf 1
|
|
61
|
+
* gesetzt -- und die Meldung geht, wenn ueberhaupt, auf den FEHLERkanal.
|
|
62
|
+
*
|
|
63
|
+
* ๐ด UND DIE MELDUNG GEHT NIE IN DEN DATENKANAL -- die Ungleichheit der zwei
|
|
64
|
+
* Kanaele IST der Bauplan, keine Ausnahme (Befund W-1a der Gesamt-Durchsicht,
|
|
65
|
+
* 2026-09-12). Hier stand vorher "sag es auf dem JEWEILS ANDEREN Kanal", und
|
|
66
|
+
* das war fuer einen der zwei Faelle falsch:
|
|
67
|
+
* ยท Bricht der DATENkanal (stdout), darf auf dem Fehlerkanal gemeldet
|
|
68
|
+
* werden -- der ist genau dafuer da.
|
|
69
|
+
* ยท Bricht der FEHLERkanal (stderr), wird NIRGENDS gemeldet. Auf stdout
|
|
70
|
+
* liegt die Maschinenform: das JSON von `firma daten` und die JSON-Huelle
|
|
71
|
+
* von `wache --hook`, die Claude Code parst. Ein deutscher Satz
|
|
72
|
+
* mittendrin macht `JSON.parse` ueber die ganze Ausgabe unmoeglich -- und
|
|
73
|
+
* genau das verbietet US-1 ("nie mittendrin") schon fuer den
|
|
74
|
+
* Update-Hinweis in `endeMitHinweis`. Dann ist der Rueckgabewert die
|
|
75
|
+
* ehrliche Auskunft; der Datenkanal ist keine Protokollzeile wert.
|
|
76
|
+
* Gemessen vor der Reparatur: `quatschbefehl` mit nur-lesbarem stderr legte
|
|
77
|
+
* `kimal3: Ausgabekanal-Fehler -- EBADF ...` auf stdout.
|
|
78
|
+
*
|
|
79
|
+
* ๐ด UND EIN EINMAL-RIEGEL, DAMIT DAS PROGRAMM UEBERHAUPT ENDET (Befund W-1b,
|
|
80
|
+
* dieselbe Durchsicht): Solange beide Empfaenger einander anschrieben, erzeugte
|
|
81
|
+
* jeder Schreibversuch das naechste `'error'`-Ereignis auf dem anderen Kanal --
|
|
82
|
+
* bei ZWEI kaputten Kanaelen (eine volle Platte genuegt:
|
|
83
|
+
* `kimal3 firma daten > a.json 2> b.txt` -> ENOSPC auf beiden) endete das
|
|
84
|
+
* Programm damit NIE. Gemessen: nach 8 Sekunden noch da, musste abgeschossen
|
|
85
|
+
* werden; dieselbe Lage ohne die Empfaenger endete in 36 ms. Und die
|
|
86
|
+
* 2-Sekunden-Notbremse half nicht: Sie wird erst IN `endeMitHinweis` gestellt
|
|
87
|
+
* und vom Ereignis-Pingpong ausgehungert. `schonGemeldet` schneidet das ab --
|
|
88
|
+
* eine Meldung pro Programmlauf, mehr braucht niemand.
|
|
89
|
+
*
|
|
90
|
+
* ๐ KEIN `process.exit` HIER (Constraint 2): Nur `exitCode` wird gesetzt --
|
|
91
|
+
* das Programm endet von selbst, sobald kein Ereignis mehr nachkommt, und
|
|
92
|
+
* genau dafuer sorgt der Einmal-Riegel.
|
|
93
|
+
*
|
|
94
|
+
* Registriert wird das genau EINMAL pro Kanal, hier -- nicht an jeder
|
|
95
|
+
* einzelnen Schreibstelle. `console.log`/`console.error` UND die zwei
|
|
96
|
+
* direkten `process.stdout.write`/`process.stderr.write`-Aufrufe in
|
|
97
|
+
* `endeMitHinweis` schreiben alle auf DIESELBEN zwei Stream-Objekte
|
|
98
|
+
* (`process.stdout`, `process.stderr` sind pro Prozess EINMALIG vorhanden);
|
|
99
|
+
* ein Empfaenger auf dem Stream selbst deckt deshalb jede Schreibstelle im
|
|
100
|
+
* ganzen Programm ab, auch die in den einzelnen `befehle/*.ts`-Dateien.
|
|
101
|
+
*/
|
|
102
|
+
/**
|
|
103
|
+
* @param meldenAuf Wohin die Meldung darf -- oder `null` fuer "nirgends".
|
|
104
|
+
* `null` steht fuer den Fehlerkanal selbst: Ist ER kaputt, bleibt nur der
|
|
105
|
+
* Rueckgabewert, denn der Datenkanal gehoert der Maschinenform.
|
|
106
|
+
*/
|
|
107
|
+
function gegenUnbehandelteKanalfehlerAbsichern(kanal, meldenAuf) {
|
|
108
|
+
kanal.on("error", (fehler) => {
|
|
109
|
+
if (fehler.code === "EPIPE")
|
|
110
|
+
return;
|
|
111
|
+
/*
|
|
112
|
+
๐ด NUR SETZEN, WENN NOCH KEIN FEHLSCHLAG VERMERKT IST (Befund des
|
|
113
|
+
Koordinators, Fix-Runde 1). Ein Kanalfehler kann auftreten, WAEHREND
|
|
114
|
+
gerade eine viel genauere Fehlermeldung geschrieben wird -- der
|
|
115
|
+
`.catch`-Zweig am Dateiende setzt `process.exitCode = 2` ("bitte
|
|
116
|
+
einloggen") bzw. `3` ("nicht erreichbar") direkt NACH dem
|
|
117
|
+
`console.error`-Aufruf, der den Kanalfehler ueberhaupt erst ausloest.
|
|
118
|
+
Ein bedingungsloses `process.exitCode = 1` hier ueberschreibt diese
|
|
119
|
+
genauere Zahl mit der ungenaueren -- gemessen (Koordinator): Ausweis
|
|
120
|
+
fehlt, `projekt liste`, Fehlerkanal nur zum Lesen geoeffnet -> `2` geht
|
|
121
|
+
verloren, es bleibt nur `1`. Das ist derselbe Fehler wie bei
|
|
122
|
+
`bestaetigungenAktivieren` in der Projekt-CLAUDE.md: Ein Fehlerfall darf
|
|
123
|
+
nicht in einen anderen zusammenfallen, denn die Seite (hier: Claude)
|
|
124
|
+
kann nur unterscheiden, was der Rueckgabewert noch unterscheidet.
|
|
125
|
+
|
|
126
|
+
Deshalb: Nur ein UNDEFINIERTER oder ein ERFOLGREICHER (`0`) Stand gilt
|
|
127
|
+
als "noch kein Fehlschlag vermerkt" -- ausdruecklich BEIDE pruefen,
|
|
128
|
+
nicht nur auf `0`, denn `process.exitCode` ist am Programmanfang
|
|
129
|
+
`undefined`, nicht `0`. Jede bereits gesetzte Zahl ungleich `0`
|
|
130
|
+
(`1`, `2`, `3`, `4`) ist die genauere Auskunft und bleibt stehen.
|
|
131
|
+
*/
|
|
132
|
+
if (process.exitCode === undefined || process.exitCode === 0)
|
|
133
|
+
process.exitCode = 1;
|
|
134
|
+
if (meldenAuf === null || schonGemeldet)
|
|
135
|
+
return;
|
|
136
|
+
schonGemeldet = true;
|
|
137
|
+
try {
|
|
138
|
+
meldenAuf.write(`kimal3: Ausgabekanal-Fehler -- ${fehler.message}\n`);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Auch der Fehlerkanal kann kaputt sein -- dann bleibt wenigstens der
|
|
142
|
+
// Rueckgabewert (oben gesetzt) die ehrliche Auskunft.
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
gegenUnbehandelteKanalfehlerAbsichern(process.stdout, process.stderr);
|
|
147
|
+
gegenUnbehandelteKanalfehlerAbsichern(process.stderr, null);
|
|
35
148
|
// ๐ Kein handgeschriebener Block mehr (2026-08-18): Die Liste wohnt in
|
|
36
149
|
// `befehle-katalog.ts` und wird von dort AUCH im Pro-Bereich der App angezeigt.
|
|
37
150
|
// Zwei Listen ueber dieselben Befehle driften โ die eine bekaeme den naechsten
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const x = "das ist keine Zahl";
|