@cachly-dev/mcp-server 0.10.124 → 0.10.126
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/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/src/aussetzer.d.ts +67 -0
- package/dist/src/aussetzer.js +82 -0
- package/dist/src/aussetzer.js.map +1 -0
- package/dist/src/autor-abzeichen.d.ts +41 -0
- package/dist/src/autor-abzeichen.js +56 -0
- package/dist/src/autor-abzeichen.js.map +1 -0
- package/dist/src/autor.d.ts +101 -0
- package/dist/src/autor.js +136 -0
- package/dist/src/autor.js.map +1 -0
- package/dist/src/bauabdruck-daten.generiert.json +5 -0
- package/dist/src/bauabdruck.d.ts +38 -0
- package/dist/src/bauabdruck.js +93 -0
- package/dist/src/bauabdruck.js.map +1 -0
- package/dist/src/bedeutung.d.ts +175 -0
- package/dist/src/bedeutung.js +254 -0
- package/dist/src/bedeutung.js.map +1 -0
- package/dist/src/brain-export.d.ts +24 -0
- package/dist/src/brain-export.js +31 -1
- package/dist/src/brain-export.js.map +1 -1
- package/dist/src/deutsch.d.ts +98 -0
- package/dist/src/deutsch.js +223 -0
- package/dist/src/deutsch.js.map +1 -0
- package/dist/src/eingaenge-nachruesten.d.ts +41 -0
- package/dist/src/eingaenge-nachruesten.js +290 -0
- package/dist/src/eingaenge-nachruesten.js.map +1 -0
- package/dist/src/eingaenge.d.ts +135 -0
- package/dist/src/eingaenge.js +228 -0
- package/dist/src/eingaenge.js.map +1 -0
- package/dist/src/geliefert.d.ts +63 -0
- package/dist/src/geliefert.js +114 -0
- package/dist/src/geliefert.js.map +1 -0
- package/dist/src/handlers/advanced.js +7 -3
- package/dist/src/handlers/advanced.js.map +1 -1
- package/dist/src/handlers/brain.d.ts +19 -0
- package/dist/src/handlers/brain.js +536 -48
- package/dist/src/handlers/brain.js.map +1 -1
- package/dist/src/handlers/instances.d.ts +24 -0
- package/dist/src/handlers/instances.js +49 -1
- package/dist/src/handlers/instances.js.map +1 -1
- package/dist/src/handlers/team.js +105 -0
- package/dist/src/handlers/team.js.map +1 -1
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.js +272 -26
- package/dist/src/index.js.map +1 -1
- package/dist/src/lesson-preview.d.ts +81 -0
- package/dist/src/lesson-preview.js +133 -0
- package/dist/src/lesson-preview.js.map +1 -0
- package/dist/src/rangfolge.d.ts +169 -0
- package/dist/src/rangfolge.js +214 -0
- package/dist/src/rangfolge.js.map +1 -0
- package/dist/src/raumkorrektur.d.ts +100 -0
- package/dist/src/raumkorrektur.js +197 -0
- package/dist/src/raumkorrektur.js.map +1 -0
- package/dist/src/recall-tiefe.d.ts +48 -0
- package/dist/src/recall-tiefe.js +42 -0
- package/dist/src/recall-tiefe.js.map +1 -0
- package/dist/src/rerank.d.ts +0 -14
- package/dist/src/rerank.js +39 -2
- package/dist/src/rerank.js.map +1 -1
- package/dist/src/search.d.ts +56 -17
- package/dist/src/search.js +335 -73
- package/dist/src/search.js.map +1 -1
- package/dist/src/seltenheitsbestand.d.ts +53 -0
- package/dist/src/seltenheitsbestand.js +92 -0
- package/dist/src/seltenheitsbestand.js.map +1 -0
- package/dist/src/spuren.d.ts +97 -0
- package/dist/src/spuren.js +150 -0
- package/dist/src/spuren.js.map +1 -0
- package/dist/src/tools.js +1 -1
- package/dist/src/tools.js.map +1 -1
- package/dist/src/versuch.d.ts +179 -0
- package/dist/src/versuch.js +250 -0
- package/dist/src/versuch.js.map +1 -0
- package/dist/src/vorspann.d.ts +73 -0
- package/dist/src/vorspann.js +146 -0
- package/dist/src/vorspann.js.map +1 -0
- package/dist/src/werkzeug-nutzung.d.ts +62 -0
- package/dist/src/werkzeug-nutzung.js +72 -0
- package/dist/src/werkzeug-nutzung.js.map +1 -0
- package/dist/src/wertbeitrag.d.ts +57 -0
- package/dist/src/wertbeitrag.js +73 -0
- package/dist/src/wertbeitrag.js.map +1 -0
- package/glama.json +1 -1
- package/package.json +12 -4
- package/server.json +2 -2
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './src/index.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Kompatibilitäts-Einstieg: Plattformen wie Glama erzeugen ihre Build-Specs
|
|
2
|
+
// automatisch und starten mit `node dist/index.js`. tsc (rootDir ".") legt den
|
|
3
|
+
// echten Einstieg aber unter dist/src/index.js ab. Diese Datei kompiliert nach
|
|
4
|
+
// dist/index.js und startet dort denselben Server — der Import genügt, weil
|
|
5
|
+
// src/index.ts auf Modul-Ebene startet.
|
|
6
|
+
import './src/index.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,wCAAwC;AACxC,OAAO,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meldestelle fuer stille Aussetzer.
|
|
3
|
+
*
|
|
4
|
+
* ── Warum es das gibt ───────────────────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* Am 20.08.2026 wurde am Produktionsspeicher gemessen: `cachly:lesson:vec:*`
|
|
7
|
+
* war LEER — 0 Vektoren bei 506 Lektionen. Der Recall-Pfad steigt bei
|
|
8
|
+
* `vektorbestand.groesse === 0` aus und faellt auf den reinen Wortabgleich
|
|
9
|
+
* zurueck. Er tut das STUMM.
|
|
10
|
+
*
|
|
11
|
+
* Von aussen ist dieser Zustand von "alles in Ordnung" nicht zu
|
|
12
|
+
* unterscheiden: die Suche liefert weiter Ergebnisse, nur schlechtere. Die am
|
|
13
|
+
* 19.08. gemessene Verbesserung von 21 auf 40 Prozent existierte in
|
|
14
|
+
* Produktion nie, und nichts hat es gesagt.
|
|
15
|
+
*
|
|
16
|
+
* Das ist die Fehlerklasse "Stille wird als gruen gebucht". Diese Datei ist
|
|
17
|
+
* die Gegenmassnahme an der billigsten Stelle: eine Zeile im Protokoll.
|
|
18
|
+
*
|
|
19
|
+
* ── Warum nur EINMAL je Grund ───────────────────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* Der Recall-Pfad laeuft bei jeder Anfrage. Eine Zeile je Anfrage waere nach
|
|
22
|
+
* einer Stunde ein Protokoll, das niemand mehr liest — und ein Protokoll, das
|
|
23
|
+
* niemand liest, ist wieder Stille. Einmal je Grund und Prozess ist die
|
|
24
|
+
* Menge, die auffaellt, ohne zu ermueden.
|
|
25
|
+
*
|
|
26
|
+
* ── Warum stderr und nicht stdout ───────────────────────────────────────────
|
|
27
|
+
*
|
|
28
|
+
* Ueber stdout laeuft das MCP-Protokoll. Eine Zeile Text dort ist kein
|
|
29
|
+
* Hinweis, sondern ein Verbindungsabbruch.
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* Meldet einen Aussetzer genau einmal je Grund und Prozess.
|
|
33
|
+
*
|
|
34
|
+
* @param grund kurzer Schluessel, z. B. 'bedeutung-ohne-vektoren'
|
|
35
|
+
* @param text was ausgefallen ist und was das fuer das Ergebnis heisst
|
|
36
|
+
* @returns true, wenn diese Meldung wirklich hinausging
|
|
37
|
+
*/
|
|
38
|
+
export declare function meldeEinmal(grund: string, text: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Wurde dieser Grund in diesem Prozess schon gemeldet?
|
|
41
|
+
*
|
|
42
|
+
* Fuer `brain_doctor`: dort soll stehen, was hier passiert ist, ohne dass
|
|
43
|
+
* jemand ein Protokoll durchsuchen muss.
|
|
44
|
+
*/
|
|
45
|
+
export declare function schonGemeldet(grund: string): boolean;
|
|
46
|
+
/** Alle bisher gemeldeten Gruende, in der Reihenfolge des Auftretens. */
|
|
47
|
+
export declare function gemeldeteGruende(): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Setzt die Merkliste zurueck.
|
|
50
|
+
*
|
|
51
|
+
* Nur fuer Tests. Ohne das wuerde die erste Testdatei alle weiteren blind
|
|
52
|
+
* machen — genau der Fehler, gegen den diese Datei antritt.
|
|
53
|
+
*/
|
|
54
|
+
export declare function setzeAussetzerZurueck(): void;
|
|
55
|
+
/** Der Grund, um den es beim Anlass ging: Bedeutungsabgleich ohne Vektoren. */
|
|
56
|
+
export declare const OHNE_VEKTOREN = "bedeutung-ohne-vektoren";
|
|
57
|
+
/** Der Nachbarfall: es gibt gar keinen Dienst zum Einbetten. */
|
|
58
|
+
export declare const OHNE_DIENST = "bedeutung-ohne-dienst";
|
|
59
|
+
/**
|
|
60
|
+
* Der Bestand ist da, aber die FRAGE liess sich nicht einbetten.
|
|
61
|
+
*
|
|
62
|
+
* Eigener Grund und nicht mit OHNE_VEKTOREN zusammengelegt: hier ist der
|
|
63
|
+
* Bestand gesund und der fremde Dienst hat gerade nicht geantwortet. Das ist
|
|
64
|
+
* ein Netzproblem und keine fehlende Nachruestung — wer beides unter einem
|
|
65
|
+
* Namen fuehrt, sucht spaeter an der falschen Stelle.
|
|
66
|
+
*/
|
|
67
|
+
export declare const OHNE_FRAGEVEKTOR = "bedeutung-ohne-fragevektor";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meldestelle fuer stille Aussetzer.
|
|
3
|
+
*
|
|
4
|
+
* ── Warum es das gibt ───────────────────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* Am 20.08.2026 wurde am Produktionsspeicher gemessen: `cachly:lesson:vec:*`
|
|
7
|
+
* war LEER — 0 Vektoren bei 506 Lektionen. Der Recall-Pfad steigt bei
|
|
8
|
+
* `vektorbestand.groesse === 0` aus und faellt auf den reinen Wortabgleich
|
|
9
|
+
* zurueck. Er tut das STUMM.
|
|
10
|
+
*
|
|
11
|
+
* Von aussen ist dieser Zustand von "alles in Ordnung" nicht zu
|
|
12
|
+
* unterscheiden: die Suche liefert weiter Ergebnisse, nur schlechtere. Die am
|
|
13
|
+
* 19.08. gemessene Verbesserung von 21 auf 40 Prozent existierte in
|
|
14
|
+
* Produktion nie, und nichts hat es gesagt.
|
|
15
|
+
*
|
|
16
|
+
* Das ist die Fehlerklasse "Stille wird als gruen gebucht". Diese Datei ist
|
|
17
|
+
* die Gegenmassnahme an der billigsten Stelle: eine Zeile im Protokoll.
|
|
18
|
+
*
|
|
19
|
+
* ── Warum nur EINMAL je Grund ───────────────────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* Der Recall-Pfad laeuft bei jeder Anfrage. Eine Zeile je Anfrage waere nach
|
|
22
|
+
* einer Stunde ein Protokoll, das niemand mehr liest — und ein Protokoll, das
|
|
23
|
+
* niemand liest, ist wieder Stille. Einmal je Grund und Prozess ist die
|
|
24
|
+
* Menge, die auffaellt, ohne zu ermueden.
|
|
25
|
+
*
|
|
26
|
+
* ── Warum stderr und nicht stdout ───────────────────────────────────────────
|
|
27
|
+
*
|
|
28
|
+
* Ueber stdout laeuft das MCP-Protokoll. Eine Zeile Text dort ist kein
|
|
29
|
+
* Hinweis, sondern ein Verbindungsabbruch.
|
|
30
|
+
*/
|
|
31
|
+
/** Welche Gruende schon gemeldet wurden. Je Prozess, nicht je Anfrage. */
|
|
32
|
+
const gemeldet = new Set();
|
|
33
|
+
/**
|
|
34
|
+
* Meldet einen Aussetzer genau einmal je Grund und Prozess.
|
|
35
|
+
*
|
|
36
|
+
* @param grund kurzer Schluessel, z. B. 'bedeutung-ohne-vektoren'
|
|
37
|
+
* @param text was ausgefallen ist und was das fuer das Ergebnis heisst
|
|
38
|
+
* @returns true, wenn diese Meldung wirklich hinausging
|
|
39
|
+
*/
|
|
40
|
+
export function meldeEinmal(grund, text) {
|
|
41
|
+
if (gemeldet.has(grund))
|
|
42
|
+
return false;
|
|
43
|
+
gemeldet.add(grund);
|
|
44
|
+
console.error(`[aussetzer] ${grund}: ${text}`);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Wurde dieser Grund in diesem Prozess schon gemeldet?
|
|
49
|
+
*
|
|
50
|
+
* Fuer `brain_doctor`: dort soll stehen, was hier passiert ist, ohne dass
|
|
51
|
+
* jemand ein Protokoll durchsuchen muss.
|
|
52
|
+
*/
|
|
53
|
+
export function schonGemeldet(grund) {
|
|
54
|
+
return gemeldet.has(grund);
|
|
55
|
+
}
|
|
56
|
+
/** Alle bisher gemeldeten Gruende, in der Reihenfolge des Auftretens. */
|
|
57
|
+
export function gemeldeteGruende() {
|
|
58
|
+
return [...gemeldet];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Setzt die Merkliste zurueck.
|
|
62
|
+
*
|
|
63
|
+
* Nur fuer Tests. Ohne das wuerde die erste Testdatei alle weiteren blind
|
|
64
|
+
* machen — genau der Fehler, gegen den diese Datei antritt.
|
|
65
|
+
*/
|
|
66
|
+
export function setzeAussetzerZurueck() {
|
|
67
|
+
gemeldet.clear();
|
|
68
|
+
}
|
|
69
|
+
/** Der Grund, um den es beim Anlass ging: Bedeutungsabgleich ohne Vektoren. */
|
|
70
|
+
export const OHNE_VEKTOREN = 'bedeutung-ohne-vektoren';
|
|
71
|
+
/** Der Nachbarfall: es gibt gar keinen Dienst zum Einbetten. */
|
|
72
|
+
export const OHNE_DIENST = 'bedeutung-ohne-dienst';
|
|
73
|
+
/**
|
|
74
|
+
* Der Bestand ist da, aber die FRAGE liess sich nicht einbetten.
|
|
75
|
+
*
|
|
76
|
+
* Eigener Grund und nicht mit OHNE_VEKTOREN zusammengelegt: hier ist der
|
|
77
|
+
* Bestand gesund und der fremde Dienst hat gerade nicht geantwortet. Das ist
|
|
78
|
+
* ein Netzproblem und keine fehlende Nachruestung — wer beides unter einem
|
|
79
|
+
* Namen fuehrt, sucht spaeter an der falschen Stelle.
|
|
80
|
+
*/
|
|
81
|
+
export const OHNE_FRAGEVEKTOR = 'bedeutung-ohne-fragevektor';
|
|
82
|
+
//# sourceMappingURL=aussetzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aussetzer.js","sourceRoot":"","sources":["../../src/aussetzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,0EAA0E;AAC1E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,IAAY;IACrD,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,OAAO,CAAC,KAAK,CAAC,eAAe,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB;IACnC,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,aAAa,GAAG,yBAAyB,CAAC;AAEvD,gEAAgE;AAChE,MAAM,CAAC,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wer hat diese Lektion geschrieben — ich oder jemand anderes?
|
|
3
|
+
*
|
|
4
|
+
* `session_start_summary` nimmt seit jeher einen Parameter `author` entgegen
|
|
5
|
+
* und beschreibt ihn in der Werkzeug-Spezifikation so:
|
|
6
|
+
*
|
|
7
|
+
* "Your name or handle (optional). Same as session_start — used for team
|
|
8
|
+
* lesson filtering."
|
|
9
|
+
*
|
|
10
|
+
* Die Zusage wurde nie eingeloest. Der Handler holte den Wert aus den
|
|
11
|
+
* Argumenten und benutzte ihn danach nirgends; eslint meldete ihn seit
|
|
12
|
+
* Monaten als ungenutzte Variable. Wer den Parameter setzte, bekam exakt
|
|
13
|
+
* dieselbe Ausgabe wie ohne ihn.
|
|
14
|
+
*
|
|
15
|
+
* Fehlerklasse: eine Zusage an zwei Orten — hier in der Spezifikation, dort
|
|
16
|
+
* im Code — und nur einer wurde gepflegt. Dieselbe Form wie die Kommentarzeile
|
|
17
|
+
* am Frei-Limit, die "the #1 result is always returned" versprach, waehrend
|
|
18
|
+
* der Zweig darunter null lieferte.
|
|
19
|
+
*
|
|
20
|
+
* Reines Modul, weil die Entscheidung eine Rechnung ist: dieselbe Regel, die
|
|
21
|
+
* `smart_recall` schon anwendet, an EINER Stelle statt zweimal abgeschrieben.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Das Abzeichen hinter einer Lektion — leer, wenn sie von mir selbst stammt
|
|
25
|
+
* oder niemand als Autor eingetragen ist.
|
|
26
|
+
*
|
|
27
|
+
* Bewusst KEIN Abzeichen fuer die eigenen Lektionen: in einem Brain, das
|
|
28
|
+
* ueberwiegend einer Person gehoert, stuende sonst hinter jeder Zeile derselbe
|
|
29
|
+
* Name, und das Abzeichen verlöre genau die Aussage, für die es da ist.
|
|
30
|
+
*/
|
|
31
|
+
export declare function autorAbzeichen(lektionsAutor: string | null | undefined, anfragender: string | null | undefined): string;
|
|
32
|
+
/**
|
|
33
|
+
* Wie viele der gezeigten Lektionen von jemand anderem stammen.
|
|
34
|
+
*
|
|
35
|
+
* Das ist der Wert, den nur ein GETEILTES Gedaechtnis liefert — und deshalb
|
|
36
|
+
* die Zahl, die es zu nennen lohnt. Ist sie null, wird auch nichts gesagt:
|
|
37
|
+
* "0 von Teamkollegen" ist keine Nachricht, sondern Rauschen.
|
|
38
|
+
*/
|
|
39
|
+
export declare function fremdanteil(lektionen: readonly {
|
|
40
|
+
author?: string | null;
|
|
41
|
+
}[], anfragender: string | null | undefined): number;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wer hat diese Lektion geschrieben — ich oder jemand anderes?
|
|
3
|
+
*
|
|
4
|
+
* `session_start_summary` nimmt seit jeher einen Parameter `author` entgegen
|
|
5
|
+
* und beschreibt ihn in der Werkzeug-Spezifikation so:
|
|
6
|
+
*
|
|
7
|
+
* "Your name or handle (optional). Same as session_start — used for team
|
|
8
|
+
* lesson filtering."
|
|
9
|
+
*
|
|
10
|
+
* Die Zusage wurde nie eingeloest. Der Handler holte den Wert aus den
|
|
11
|
+
* Argumenten und benutzte ihn danach nirgends; eslint meldete ihn seit
|
|
12
|
+
* Monaten als ungenutzte Variable. Wer den Parameter setzte, bekam exakt
|
|
13
|
+
* dieselbe Ausgabe wie ohne ihn.
|
|
14
|
+
*
|
|
15
|
+
* Fehlerklasse: eine Zusage an zwei Orten — hier in der Spezifikation, dort
|
|
16
|
+
* im Code — und nur einer wurde gepflegt. Dieselbe Form wie die Kommentarzeile
|
|
17
|
+
* am Frei-Limit, die "the #1 result is always returned" versprach, waehrend
|
|
18
|
+
* der Zweig darunter null lieferte.
|
|
19
|
+
*
|
|
20
|
+
* Reines Modul, weil die Entscheidung eine Rechnung ist: dieselbe Regel, die
|
|
21
|
+
* `smart_recall` schon anwendet, an EINER Stelle statt zweimal abgeschrieben.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Das Abzeichen hinter einer Lektion — leer, wenn sie von mir selbst stammt
|
|
25
|
+
* oder niemand als Autor eingetragen ist.
|
|
26
|
+
*
|
|
27
|
+
* Bewusst KEIN Abzeichen fuer die eigenen Lektionen: in einem Brain, das
|
|
28
|
+
* ueberwiegend einer Person gehoert, stuende sonst hinter jeder Zeile derselbe
|
|
29
|
+
* Name, und das Abzeichen verlöre genau die Aussage, für die es da ist.
|
|
30
|
+
*/
|
|
31
|
+
export function autorAbzeichen(lektionsAutor, anfragender) {
|
|
32
|
+
const autor = (lektionsAutor ?? '').trim();
|
|
33
|
+
if (!autor)
|
|
34
|
+
return '';
|
|
35
|
+
const ich = (anfragender ?? '').trim();
|
|
36
|
+
if (ich && autor === ich)
|
|
37
|
+
return '';
|
|
38
|
+
return ` · 👤 ${autor}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Wie viele der gezeigten Lektionen von jemand anderem stammen.
|
|
42
|
+
*
|
|
43
|
+
* Das ist der Wert, den nur ein GETEILTES Gedaechtnis liefert — und deshalb
|
|
44
|
+
* die Zahl, die es zu nennen lohnt. Ist sie null, wird auch nichts gesagt:
|
|
45
|
+
* "0 von Teamkollegen" ist keine Nachricht, sondern Rauschen.
|
|
46
|
+
*/
|
|
47
|
+
export function fremdanteil(lektionen, anfragender) {
|
|
48
|
+
const ich = (anfragender ?? '').trim();
|
|
49
|
+
if (!ich)
|
|
50
|
+
return 0;
|
|
51
|
+
return lektionen.filter(l => {
|
|
52
|
+
const autor = (l.author ?? '').trim();
|
|
53
|
+
return autor.length > 0 && autor !== ich;
|
|
54
|
+
}).length;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=autor-abzeichen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autor-abzeichen.js","sourceRoot":"","sources":["../../src/autor-abzeichen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,aAAwC,EAAE,WAAsC;IAC7G,MAAM,KAAK,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,GAAG,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,SAAS,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,SAAgD,EAChD,WAAsC;IAEtC,MAAM,GAAG,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAC;IACnB,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;QAC1B,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,KAAK,GAAG,CAAC;IAC3C,CAAC,CAAC,CAAC,MAAM,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wer hat diese Lektion geschrieben?
|
|
3
|
+
*
|
|
4
|
+
* ── Der Befund, gemessen am 19.08.2026 ──────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* 195 von 493 Lektionen tragen keinen Autor — zwei Fuenftel. Ohne Autor zaehlt
|
|
7
|
+
* keine Team-Wiederverwendung, brain_who_knows findet niemanden, und das
|
|
8
|
+
* Versprechen "geteiltes Gedaechtnis" ist von einer Notizdatei nicht zu
|
|
9
|
+
* unterscheiden.
|
|
10
|
+
*
|
|
11
|
+
* ── Und es war unser Fehler, nicht der der Nutzer ───────────────────────────
|
|
12
|
+
*
|
|
13
|
+
* Heinrich, 19.08.2026: "das mit dem Autor war doch eher ein Fehler von uns
|
|
14
|
+
* bzw. wie cachly die Anweisungen fuer das Brain geschrieben hat, denn der
|
|
15
|
+
* Autor steht doch in den Git-Zugangsdaten."
|
|
16
|
+
*
|
|
17
|
+
* Genau so ist es. `author` war ein OPTIONALES Feld, das ein Agent bei jedem
|
|
18
|
+
* Aufruf mitschicken sollte — und natuerlich vergisst. Dabei steht der Name
|
|
19
|
+
* seit jeher zwei Zeilen entfernt in `git config user.name`. Der Code holte
|
|
20
|
+
* ihn sogar schon, aber nur an einer anderen Stelle (index.ts, fuer die
|
|
21
|
+
* Demo-Ausgabe) und nie fuer die Lektion selbst.
|
|
22
|
+
*
|
|
23
|
+
* Ein Pflichtfeld, das man vergessen kann, ist kein Pflichtfeld. Ein Wert, der
|
|
24
|
+
* sich herleiten laesst, gehoert hergeleitet.
|
|
25
|
+
*
|
|
26
|
+
* ── Reihenfolge, absichtlich in dieser Richtung ─────────────────────────────
|
|
27
|
+
*
|
|
28
|
+
* 1. was ausdruecklich uebergeben wurde — der Aufrufer weiss es besser
|
|
29
|
+
* 2. CACHLY_AUTHOR — bewusst gesetzt, etwa in der CI
|
|
30
|
+
* 3. git config user.name — der angemeldete Mensch
|
|
31
|
+
* 4. git config user.email (Teil vor dem @)
|
|
32
|
+
* 5. leer — dann steht dort ehrlich nichts statt eines geratenen Namens
|
|
33
|
+
*
|
|
34
|
+
* Schritt 5 ist wichtig: lieber kein Autor als ein falscher. Ein erfundener
|
|
35
|
+
* Name macht aus einer fehlenden Zuordnung eine falsche, und die faellt
|
|
36
|
+
* niemandem mehr auf.
|
|
37
|
+
*/
|
|
38
|
+
/** Ein Git-Wert, oder leer. Wirft nie — Git kann fehlen, das ist kein Fehler. */
|
|
39
|
+
export type GitLeser = (schluessel: string) => string;
|
|
40
|
+
export declare const echterGitLeser: (cwd?: string) => GitLeser;
|
|
41
|
+
/**
|
|
42
|
+
* Einen Namen auf die Form bringen, in der Autoren gespeichert werden.
|
|
43
|
+
*
|
|
44
|
+
* Klein geschrieben und ohne Leerzeichen: "Heinrich Neb" wird zu "heinrich".
|
|
45
|
+
* Das ist keine Kosmetik — brain_who_knows, team_recall und die
|
|
46
|
+
* Wiederverwendungs-Zaehlung vergleichen Autoren als Zeichenketten. "Heinrich"
|
|
47
|
+
* und "heinrich" waeren zwei Menschen.
|
|
48
|
+
*/
|
|
49
|
+
export declare function normalisiere(roh: string): string;
|
|
50
|
+
export interface AutorHerkunft {
|
|
51
|
+
/** Der ermittelte Name, oder leer. */
|
|
52
|
+
autor: string;
|
|
53
|
+
/** Woher er kam — steht im Hinweis an den Aufrufer. */
|
|
54
|
+
quelle: 'uebergeben' | 'umgebung' | 'git-name' | 'git-mail' | 'anonym' | 'unbekannt';
|
|
55
|
+
}
|
|
56
|
+
export declare function ermittleAutor(input: {
|
|
57
|
+
uebergeben?: string;
|
|
58
|
+
umgebung?: string;
|
|
59
|
+
git: GitLeser;
|
|
60
|
+
}): AutorHerkunft;
|
|
61
|
+
/**
|
|
62
|
+
* Der Mitautor — standardmaessig AUS.
|
|
63
|
+
*
|
|
64
|
+
* Heinrich: "Wir koennen im gleichen Zuge ja auch zum Beispiel claude als
|
|
65
|
+
* Co-Author nehmen, wenn der User das moechte? Einstellungssache,
|
|
66
|
+
* standardmaessig aber aus."
|
|
67
|
+
*
|
|
68
|
+
* Aus zwei Gruenden aus: erstens gehoert die Entscheidung dem Menschen, und
|
|
69
|
+
* zweitens wuerde ein automatisch gesetzter Mitautor die Zahl, um die es hier
|
|
70
|
+
* geht — wie viele Lektionen einen MENSCHEN als Autor haben — sofort wieder
|
|
71
|
+
* unbrauchbar machen.
|
|
72
|
+
*
|
|
73
|
+
* Eingeschaltet wird er mit
|
|
74
|
+
* brain_set_pref(key="coauthor", value="claude")
|
|
75
|
+
* und wieder aus mit value="" oder "off".
|
|
76
|
+
*/
|
|
77
|
+
export declare const COAUTHOR_PREF_KEY = "coauthor";
|
|
78
|
+
/** Aus dem gespeicherten Wert den Mitautor lesen — leer heisst aus. */
|
|
79
|
+
export declare function coautorAus(prefWert: string | null | undefined): string;
|
|
80
|
+
/**
|
|
81
|
+
* Wie der Autor gespeichert wird, wenn ein Mitautor eingeschaltet ist.
|
|
82
|
+
*
|
|
83
|
+
* "heinrich+claude" — ein Feld, kein zweites. Ein zweites Feld haette jede
|
|
84
|
+
* Abfrage im ganzen Haus anfassen muessen (who_knows, team_recall,
|
|
85
|
+
* reuse_pairs, das Briefing), und die Zahl "wie viele Lektionen haben einen
|
|
86
|
+
* Autor" waere dabei zweideutig geworden.
|
|
87
|
+
*
|
|
88
|
+
* Der Mensch steht VORN. Wer die Zeichenkette an "+" trennt, bekommt zuerst
|
|
89
|
+
* den, der die Entscheidung getroffen hat.
|
|
90
|
+
*/
|
|
91
|
+
export declare function mitCoautor(autor: string, coautor: string): string;
|
|
92
|
+
/** Nur der Mensch, ohne Mitautor — fuer Zaehlungen und Vergleiche. */
|
|
93
|
+
export declare function nurMensch(autorFeld: string): string;
|
|
94
|
+
/**
|
|
95
|
+
* Ein Satz an den Aufrufer, wenn kein Autor ermittelt werden konnte.
|
|
96
|
+
*
|
|
97
|
+
* Wieder ein HINWEIS und keine Ablehnung: eine abgelehnte Lektion ist immer
|
|
98
|
+
* schlechter als eine ohne Autor. Aber schweigen waere falsch — genau das
|
|
99
|
+
* Schweigen hat die 195 erzeugt.
|
|
100
|
+
*/
|
|
101
|
+
export declare function autorHinweis(h: AutorHerkunft): string | null;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
export const echterGitLeser = (cwd) => (schluessel) => {
|
|
3
|
+
try {
|
|
4
|
+
return execSync(`git config ${schluessel}`, {
|
|
5
|
+
cwd,
|
|
6
|
+
encoding: 'utf-8',
|
|
7
|
+
stdio: 'pipe',
|
|
8
|
+
timeout: 1500,
|
|
9
|
+
}).trim();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Einen Namen auf die Form bringen, in der Autoren gespeichert werden.
|
|
17
|
+
*
|
|
18
|
+
* Klein geschrieben und ohne Leerzeichen: "Heinrich Neb" wird zu "heinrich".
|
|
19
|
+
* Das ist keine Kosmetik — brain_who_knows, team_recall und die
|
|
20
|
+
* Wiederverwendungs-Zaehlung vergleichen Autoren als Zeichenketten. "Heinrich"
|
|
21
|
+
* und "heinrich" waeren zwei Menschen.
|
|
22
|
+
*/
|
|
23
|
+
export function normalisiere(roh) {
|
|
24
|
+
const t = (roh ?? '').trim();
|
|
25
|
+
if (!t)
|
|
26
|
+
return '';
|
|
27
|
+
// Nur der Rufname: Nachnamen aendern sich (Heirat), Rufnamen selten. Und
|
|
28
|
+
// ein Nachname im Autorenfeld ist eine Personendatei mehr, die niemand
|
|
29
|
+
// gebeten hat anzulegen.
|
|
30
|
+
const erster = t.split(/[\s.]+/)[0] ?? '';
|
|
31
|
+
return erster
|
|
32
|
+
.toLowerCase()
|
|
33
|
+
.replace(/[^a-z0-9_-]/g, '')
|
|
34
|
+
.slice(0, 32);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Ausdrueckliche Wortmeldung "ohne meinen Namen".
|
|
38
|
+
*
|
|
39
|
+
* Ohne diesen Weg gaebe es keinen mehr: seit der Name aus git hergeleitet
|
|
40
|
+
* wird, bekaeme JEDE Lektion einen Autor, auch die, bei der der Mensch das
|
|
41
|
+
* nicht will. Eine private Notiz ueber einen Kunden, ein Fund, den man nicht
|
|
42
|
+
* an sich haengen will — das muss weiterhin gehen, und zwar sichtbar statt
|
|
43
|
+
* durch Weglassen.
|
|
44
|
+
*
|
|
45
|
+
* Der Test, der beim Umbau rot wurde, hat genau diese Luecke gezeigt: er
|
|
46
|
+
* speicherte eine Lektion ohne Autor und erwartete, dass skill_gaps sie
|
|
47
|
+
* anmeckert. Das ging vorher versehentlich, jetzt geht es absichtlich.
|
|
48
|
+
*/
|
|
49
|
+
const ANONYM = new Set(['-', 'anonym', 'anonymous', 'none', 'kein', 'off']);
|
|
50
|
+
export function ermittleAutor(input) {
|
|
51
|
+
const rohUeb = (input.uebergeben ?? '').trim().toLowerCase();
|
|
52
|
+
if (ANONYM.has(rohUeb))
|
|
53
|
+
return { autor: '', quelle: 'anonym' };
|
|
54
|
+
const rohEnv = (input.umgebung ?? '').trim().toLowerCase();
|
|
55
|
+
if (ANONYM.has(rohEnv))
|
|
56
|
+
return { autor: '', quelle: 'anonym' };
|
|
57
|
+
const ueb = normalisiere(input.uebergeben ?? '');
|
|
58
|
+
if (ueb)
|
|
59
|
+
return { autor: ueb, quelle: 'uebergeben' };
|
|
60
|
+
const env = normalisiere(input.umgebung ?? '');
|
|
61
|
+
if (env)
|
|
62
|
+
return { autor: env, quelle: 'umgebung' };
|
|
63
|
+
const name = normalisiere(input.git('user.name'));
|
|
64
|
+
if (name)
|
|
65
|
+
return { autor: name, quelle: 'git-name' };
|
|
66
|
+
const mail = input.git('user.email');
|
|
67
|
+
const vorDemAt = normalisiere((mail ?? '').split('@')[0] ?? '');
|
|
68
|
+
if (vorDemAt)
|
|
69
|
+
return { autor: vorDemAt, quelle: 'git-mail' };
|
|
70
|
+
return { autor: '', quelle: 'unbekannt' };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Der Mitautor — standardmaessig AUS.
|
|
74
|
+
*
|
|
75
|
+
* Heinrich: "Wir koennen im gleichen Zuge ja auch zum Beispiel claude als
|
|
76
|
+
* Co-Author nehmen, wenn der User das moechte? Einstellungssache,
|
|
77
|
+
* standardmaessig aber aus."
|
|
78
|
+
*
|
|
79
|
+
* Aus zwei Gruenden aus: erstens gehoert die Entscheidung dem Menschen, und
|
|
80
|
+
* zweitens wuerde ein automatisch gesetzter Mitautor die Zahl, um die es hier
|
|
81
|
+
* geht — wie viele Lektionen einen MENSCHEN als Autor haben — sofort wieder
|
|
82
|
+
* unbrauchbar machen.
|
|
83
|
+
*
|
|
84
|
+
* Eingeschaltet wird er mit
|
|
85
|
+
* brain_set_pref(key="coauthor", value="claude")
|
|
86
|
+
* und wieder aus mit value="" oder "off".
|
|
87
|
+
*/
|
|
88
|
+
export const COAUTHOR_PREF_KEY = 'coauthor';
|
|
89
|
+
/** Aus dem gespeicherten Wert den Mitautor lesen — leer heisst aus. */
|
|
90
|
+
export function coautorAus(prefWert) {
|
|
91
|
+
const t = (prefWert ?? '').trim().toLowerCase();
|
|
92
|
+
if (!t || t === 'off' || t === 'false' || t === '0' || t === 'none')
|
|
93
|
+
return '';
|
|
94
|
+
return normalisiere(t);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Wie der Autor gespeichert wird, wenn ein Mitautor eingeschaltet ist.
|
|
98
|
+
*
|
|
99
|
+
* "heinrich+claude" — ein Feld, kein zweites. Ein zweites Feld haette jede
|
|
100
|
+
* Abfrage im ganzen Haus anfassen muessen (who_knows, team_recall,
|
|
101
|
+
* reuse_pairs, das Briefing), und die Zahl "wie viele Lektionen haben einen
|
|
102
|
+
* Autor" waere dabei zweideutig geworden.
|
|
103
|
+
*
|
|
104
|
+
* Der Mensch steht VORN. Wer die Zeichenkette an "+" trennt, bekommt zuerst
|
|
105
|
+
* den, der die Entscheidung getroffen hat.
|
|
106
|
+
*/
|
|
107
|
+
export function mitCoautor(autor, coautor) {
|
|
108
|
+
if (!autor)
|
|
109
|
+
return '';
|
|
110
|
+
if (!coautor || coautor === autor)
|
|
111
|
+
return autor;
|
|
112
|
+
return `${autor}+${coautor}`;
|
|
113
|
+
}
|
|
114
|
+
/** Nur der Mensch, ohne Mitautor — fuer Zaehlungen und Vergleiche. */
|
|
115
|
+
export function nurMensch(autorFeld) {
|
|
116
|
+
return (autorFeld ?? '').split('+')[0] ?? '';
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Ein Satz an den Aufrufer, wenn kein Autor ermittelt werden konnte.
|
|
120
|
+
*
|
|
121
|
+
* Wieder ein HINWEIS und keine Ablehnung: eine abgelehnte Lektion ist immer
|
|
122
|
+
* schlechter als eine ohne Autor. Aber schweigen waere falsch — genau das
|
|
123
|
+
* Schweigen hat die 195 erzeugt.
|
|
124
|
+
*/
|
|
125
|
+
export function autorHinweis(h) {
|
|
126
|
+
if (h.autor)
|
|
127
|
+
return null;
|
|
128
|
+
// Wer ausdruecklich anonym speichert, bekommt keine Belehrung.
|
|
129
|
+
if (h.quelle === 'anonym')
|
|
130
|
+
return null;
|
|
131
|
+
return (`👤 **Kein Autor ermittelt** — weder \`author\`, noch \`CACHLY_AUTHOR\`, noch \`git config user.name\`. ` +
|
|
132
|
+
`Ohne Autor zählt diese Lektion nicht als Team-Wissen: \`brain_who_knows\` findet niemanden und ` +
|
|
133
|
+
`Wiederverwendung über Personengrenzen bleibt ungezählt. Ein \`git config user.name "Vorname"\` ` +
|
|
134
|
+
`im Projekt genügt für alle künftigen Lektionen.`);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=autor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autor.js","sourceRoot":"","sources":["../../src/autor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface Bauabdruck {
|
|
2
|
+
version: string;
|
|
3
|
+
commit: string;
|
|
4
|
+
/** ISO-Zeitstempel, oder "unbekannt" solange nie gebaut wurde. */
|
|
5
|
+
gebautAm: string;
|
|
6
|
+
}
|
|
7
|
+
/** Rueckfall, solange kein Bauabdruck generiert wurde (kein Absturz, keine Erfindung). */
|
|
8
|
+
export declare const RUECKFALL_BAUABDRUCK: Bauabdruck;
|
|
9
|
+
/**
|
|
10
|
+
* Laedt den generierten Bauabdruck aus dem eigenen Verzeichnis.
|
|
11
|
+
*
|
|
12
|
+
* Faellt auf RUECKFALL_BAUABDRUCK zurueck, wenn die Datei fehlt, kein gueltiges
|
|
13
|
+
* JSON enthaelt oder die falsche Form hat — ein fehlender Bauabdruck ist kein
|
|
14
|
+
* Grund, den Server gar nicht erst zu starten.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ladeBauabdruck(verzeichnis?: string): Bauabdruck;
|
|
17
|
+
/** Der Bauabdruck dieses laufenden Prozesses — einmal beim Start geladen. */
|
|
18
|
+
export declare const bauabdruck: Bauabdruck;
|
|
19
|
+
/** Ab wie vielen Tagen der Bauabdruck in brain_doctor als alt gilt (🟡). */
|
|
20
|
+
export declare const ALTER_SCHWELLE_TAGE = 14;
|
|
21
|
+
/**
|
|
22
|
+
* Der Waechter: ist der Bauabdruck aelter als die Schwelle?
|
|
23
|
+
*
|
|
24
|
+
* Eigene Funktion, damit sie einzeln aufrufbar und pruefbar ist — aus
|
|
25
|
+
* demselben Grund wie beurteileDeckung in eingaenge.ts: ein Wächter, den man
|
|
26
|
+
* nicht einzeln aufrufen kann, ist ein Wächter, dessen Nein niemand je sieht.
|
|
27
|
+
* "unbekannt" gilt NICHT als alt — ein Server, der nie gebaut wurde, ist ein
|
|
28
|
+
* anderer Zustand als einer, der seit Wochen laeuft.
|
|
29
|
+
*/
|
|
30
|
+
export declare function istAlt(gebautAm: string, jetzt?: Date): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Baut die Zeile fuer brain_doctor — Form und Ton wie die Zeile
|
|
33
|
+
* "Semantic coverage" dort: Emoji, Fettdruck-Label, Zahlen statt Adjektive.
|
|
34
|
+
*
|
|
35
|
+
* Ein Server, der seit Wochen laeuft, ist kein Fehler — aber man muss es
|
|
36
|
+
* sehen koennen. Darum 🟡 statt ❌ fuer den Altersfall.
|
|
37
|
+
*/
|
|
38
|
+
export declare function formatiereBauabdruck(a: Bauabdruck, jetzt?: Date): string;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Bauabdruck: zeigt, welcher Stand des Servers gerade laeuft.
|
|
2
|
+
//
|
|
3
|
+
// Zwei Bauten koennen dieselbe Versionsnummer tragen und trotzdem
|
|
4
|
+
// verschiedenen Code ausfuehren. Gemessen am 20.08.2026: package.json sagte
|
|
5
|
+
// beim installierten UND beim aktuellen Server 0.10.124 — der installierte
|
|
6
|
+
// dist/ hatte den Code aus instances.ts (get_connection_string) trotzdem
|
|
7
|
+
// nicht. Von aussen war das nicht zu unterscheiden. Der Bauabdruck macht den
|
|
8
|
+
// Commit sichtbar, nicht nur die Versionsnummer.
|
|
9
|
+
//
|
|
10
|
+
// Die echten Werte kommen aus scripts/bauabdruck.mjs, das beim Bauen
|
|
11
|
+
// (`npm run build`) eine JSON-Datei daneben schreibt. Diese Datei ist
|
|
12
|
+
// generiert und steht darum in .gitignore. DIESE Datei (bauabdruck.ts) ist
|
|
13
|
+
// eingecheckt und bleibt es — sie ist die Rueckfall-Fassung, die einspringt,
|
|
14
|
+
// wenn noch nie gebaut wurde. Genau das prueft CI im Schritt "Type check":
|
|
15
|
+
// `tsc --noEmit` laeuft dort OHNE vorherigen `npm run build`.
|
|
16
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
/** Rueckfall, solange kein Bauabdruck generiert wurde (kein Absturz, keine Erfindung). */
|
|
20
|
+
export const RUECKFALL_BAUABDRUCK = {
|
|
21
|
+
version: 'unbekannt',
|
|
22
|
+
commit: 'unbekannt',
|
|
23
|
+
gebautAm: 'unbekannt',
|
|
24
|
+
};
|
|
25
|
+
function istBauabdruck(wert) {
|
|
26
|
+
if (typeof wert !== 'object' || wert === null)
|
|
27
|
+
return false;
|
|
28
|
+
const w = wert;
|
|
29
|
+
return typeof w.version === 'string' && typeof w.commit === 'string' && typeof w.gebautAm === 'string';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Laedt den generierten Bauabdruck aus dem eigenen Verzeichnis.
|
|
33
|
+
*
|
|
34
|
+
* Faellt auf RUECKFALL_BAUABDRUCK zurueck, wenn die Datei fehlt, kein gueltiges
|
|
35
|
+
* JSON enthaelt oder die falsche Form hat — ein fehlender Bauabdruck ist kein
|
|
36
|
+
* Grund, den Server gar nicht erst zu starten.
|
|
37
|
+
*/
|
|
38
|
+
export function ladeBauabdruck(verzeichnis = dirname(fileURLToPath(import.meta.url))) {
|
|
39
|
+
const pfad = join(verzeichnis, 'bauabdruck-daten.generiert.json');
|
|
40
|
+
if (!existsSync(pfad))
|
|
41
|
+
return RUECKFALL_BAUABDRUCK;
|
|
42
|
+
try {
|
|
43
|
+
const wert = JSON.parse(readFileSync(pfad, 'utf-8'));
|
|
44
|
+
return istBauabdruck(wert) ? wert : RUECKFALL_BAUABDRUCK;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return RUECKFALL_BAUABDRUCK;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Der Bauabdruck dieses laufenden Prozesses — einmal beim Start geladen. */
|
|
51
|
+
export const bauabdruck = ladeBauabdruck();
|
|
52
|
+
/** Ab wie vielen Tagen der Bauabdruck in brain_doctor als alt gilt (🟡). */
|
|
53
|
+
export const ALTER_SCHWELLE_TAGE = 14;
|
|
54
|
+
/**
|
|
55
|
+
* Der Waechter: ist der Bauabdruck aelter als die Schwelle?
|
|
56
|
+
*
|
|
57
|
+
* Eigene Funktion, damit sie einzeln aufrufbar und pruefbar ist — aus
|
|
58
|
+
* demselben Grund wie beurteileDeckung in eingaenge.ts: ein Wächter, den man
|
|
59
|
+
* nicht einzeln aufrufen kann, ist ein Wächter, dessen Nein niemand je sieht.
|
|
60
|
+
* "unbekannt" gilt NICHT als alt — ein Server, der nie gebaut wurde, ist ein
|
|
61
|
+
* anderer Zustand als einer, der seit Wochen laeuft.
|
|
62
|
+
*/
|
|
63
|
+
export function istAlt(gebautAm, jetzt = new Date()) {
|
|
64
|
+
const datum = new Date(gebautAm);
|
|
65
|
+
if (Number.isNaN(datum.getTime()))
|
|
66
|
+
return false;
|
|
67
|
+
const tage = (jetzt.getTime() - datum.getTime()) / 86_400_000;
|
|
68
|
+
return tage > ALTER_SCHWELLE_TAGE;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Baut die Zeile fuer brain_doctor — Form und Ton wie die Zeile
|
|
72
|
+
* "Semantic coverage" dort: Emoji, Fettdruck-Label, Zahlen statt Adjektive.
|
|
73
|
+
*
|
|
74
|
+
* Ein Server, der seit Wochen laeuft, ist kein Fehler — aber man muss es
|
|
75
|
+
* sehen koennen. Darum 🟡 statt ❌ fuer den Altersfall.
|
|
76
|
+
*/
|
|
77
|
+
export function formatiereBauabdruck(a, jetzt = new Date()) {
|
|
78
|
+
if (a.gebautAm === 'unbekannt') {
|
|
79
|
+
return `❔ **Bauabdruck: unbekannt** — noch kein \`npm run build\` gelaufen, Version/Commit nicht feststellbar`;
|
|
80
|
+
}
|
|
81
|
+
const datum = new Date(a.gebautAm);
|
|
82
|
+
const gueltigesDatum = !Number.isNaN(datum.getTime());
|
|
83
|
+
const alt = gueltigesDatum && istAlt(a.gebautAm, jetzt);
|
|
84
|
+
const tage = gueltigesDatum ? Math.floor((jetzt.getTime() - datum.getTime()) / 86_400_000) : null;
|
|
85
|
+
const alterText = tage === null ? '' : ` (vor ${tage} Tag${tage === 1 ? '' : 'en'})`;
|
|
86
|
+
const emoji = alt ? '🟡' : '✅';
|
|
87
|
+
const hinweis = alt
|
|
88
|
+
? ` — laeuft laenger als ${ALTER_SCHWELLE_TAGE} Tage. Kein Fehler, aber sichtbar.`
|
|
89
|
+
: '';
|
|
90
|
+
const datumsText = gueltigesDatum ? a.gebautAm.slice(0, 10) : a.gebautAm;
|
|
91
|
+
return `${emoji} **Bauabdruck:** v${a.version} · commit \`${a.commit}\` · gebaut am ${datumsText}${alterText}${hinweis}`;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=bauabdruck.js.map
|