kimal3 0.2.10 → 0.3.0
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/README.md +135 -0
- package/dist/api.js +16 -7
- package/dist/arbeitsplatz-dateien.js +23 -19
- package/dist/argumente.js +25 -97
- package/dist/befehle/arbeitsplatz.js +50 -68
- package/dist/befehle/firma-daten.js +24 -26
- package/dist/befehle/kontext-fragen.js +57 -47
- package/dist/befehle/kontext-gemeinsam.js +84 -40
- package/dist/befehle/kontext-hoch.js +40 -46
- package/dist/befehle/kontext-runter.js +70 -51
- package/dist/befehle/login.js +23 -9
- package/dist/befehle/logout.js +9 -4
- package/dist/befehle/projekt-liste.js +24 -29
- package/dist/befehle/projekt-neu.js +25 -31
- package/dist/befehle/skill-install.js +78 -49
- package/dist/befehle/skill-tausch.js +28 -0
- package/dist/befehle/wache.js +12 -6
- package/dist/befehle/werkbank.js +98 -87
- package/dist/befehle-katalog-en.js +185 -0
- package/dist/befehle-katalog.js +10 -49
- package/dist/befehlswoerter.js +69 -0
- package/dist/einstellungen-mischen.js +2 -2
- package/dist/einstellungen-schreiben.js +8 -5
- package/dist/fehler.js +5 -5
- package/dist/firmen-liste.js +8 -5
- package/dist/format.js +41 -0
- package/dist/fragen-lesen.js +3 -3
- package/dist/hilfe.js +24 -0
- package/dist/kimal3.js +77 -71
- package/dist/kontext-dateien.js +30 -23
- package/dist/kontext-hoch-zeile.js +5 -3
- package/dist/kontext-rat.js +151 -0
- package/dist/kontext-stand.js +64 -210
- package/dist/nachricht.js +39 -15
- package/dist/projekt-neu-firma.js +9 -9
- package/dist/projekt-zeilen.js +40 -54
- package/dist/slash-befehle.js +36 -0
- package/dist/sprache.js +114 -0
- package/dist/texte/allgemein.js +99 -0
- package/dist/texte/arbeitsplatz.js +135 -0
- package/dist/texte/kontext-hoch.js +128 -0
- package/dist/texte/kontext.js +171 -0
- package/dist/texte/projekte.js +126 -0
- package/dist/texte/skill.js +87 -0
- package/dist/texte/wache.js +36 -0
- package/dist/texte/werkbank.js +161 -0
- package/dist/wache-rechnung.js +27 -40
- package/dist/werkbank-name.js +28 -10
- package/dist/wort.js +98 -0
- package/package.json +2 -2
- package/skill/SKILL.md +9 -9
- package/skill/commands/k3.md +1 -1
- package/skill/commands/k3feierabend.md +99 -97
- package/skill/commands/k3kontext.md +1 -1
- package/skill/commands/k3kurs.md +6 -5
- package/skill/commands/k3start.md +2 -1
- package/skill/en/SKILL.md +451 -0
- package/skill/en/commands/k3.md +106 -0
- package/skill/en/commands/k3analyse.md +59 -0
- package/skill/en/commands/k3context.md +92 -0
- package/skill/en/commands/k3course.md +54 -0
- package/skill/en/commands/k3list.md +26 -0
- package/skill/en/commands/k3project.md +50 -0
- package/skill/en/commands/k3start.md +47 -0
- package/skill/en/commands/k3wrapup.md +99 -0
- package/dist/zz-kaputt.js +0 -1
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { feld } from "../api.js";
|
|
2
2
|
import { alsWort } from "../argumente.js";
|
|
3
3
|
import { schlussFehler } from "../fehler.js";
|
|
4
|
+
import { befehlIn, schalterIn } from "../befehlswoerter.js";
|
|
5
|
+
import { sprache } from "../sprache.js";
|
|
6
|
+
import { ALLGEMEIN_TEXTE } from "../texte/allgemein.js";
|
|
7
|
+
import { KONTEXT_TEXTE } from "../texte/kontext.js";
|
|
4
8
|
import { BASIS_URL } from "../anmeldung.js";
|
|
5
9
|
import { findeArbeitsplatz } from "../kontext-dateien.js";
|
|
10
|
+
import { ORDNER_NAMEN } from "../kontext-stand.js";
|
|
6
11
|
import { angeboteneFirmen } from "../firmen-liste.js";
|
|
7
12
|
/**
|
|
8
13
|
* Was `kontext runter` (`kontext-runter.ts`) und `kontext hoch`
|
|
@@ -36,28 +41,56 @@ import { angeboteneFirmen } from "../firmen-liste.js";
|
|
|
36
41
|
* stderr, der Aufrufer gibt nur noch `1` zurueck.
|
|
37
42
|
*/
|
|
38
43
|
export function arbeitsplatzOderAbsage() {
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
🔴 **ECHTE UMLAUTE** -- dieselbe Begruendung wie bei `fremdeDateiAbsage`
|
|
44
|
-
zwanzig Zeilen tiefer und in `kontext-fragen.ts:26`: Das hier liest ein
|
|
45
|
-
Kunde im Terminal. Bis Review-Runde 4 stand hier die ASCII-Umschrift,
|
|
46
|
-
waehrend die Schwesterfunktion in DERSELBEN Datei Umlaute setzte und es im
|
|
47
|
-
Kommentar begruendete -- eine Datei, zwei Schreibweisen.
|
|
48
|
-
|
|
49
|
-
⚠️ Der Umlaut-Fix an `kontext-hoch.ts` (Runde 3) hat diesen Zwilling
|
|
50
|
-
stehen lassen, und die Wache schlug nicht an: Sie prueft den zitierten
|
|
51
|
-
Ausschnitt „Hier steht kein KI-Arbeitsplatz", und der traegt zufaellig
|
|
52
|
-
keinen Umlaut. *Eine Wache deckt den Satz, den sie kennt -- nicht die
|
|
53
|
-
Regel dahinter.*
|
|
54
|
-
*/
|
|
55
|
-
console.error("Hier steht kein KI-Arbeitsplatz — ich suche von hier aufwärts nach einem");
|
|
56
|
-
console.error("Ordner, der `kontext/` UND `CLAUDE.md` enthält.");
|
|
57
|
-
console.error("");
|
|
58
|
-
console.error(" Wechsle in deinen Arbeitsplatz-Ordner und versuch es dort noch einmal.");
|
|
44
|
+
const fund = findeArbeitsplatz(process.cwd());
|
|
45
|
+
if (fund.art === "gefunden")
|
|
46
|
+
return { pfad: fund.pfad, sprache: fund.sprache };
|
|
47
|
+
arbeitsplatzAbsageZeilen(fund, sprache()).forEach((z) => console.error(z));
|
|
59
48
|
return null;
|
|
60
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Die Zeilen der Absage, wenn kein (eindeutiger) Arbeitsplatz da ist -- als reine Rechnung mit der
|
|
52
|
+
* Sprache als Pflichtwert, damit `check:cli` beide Sprachen misst (Teil 3, Task 10).
|
|
53
|
+
*
|
|
54
|
+
* 🔴 **ECHTE UMLAUTE** -- dieselbe Begruendung wie bei `fremdeDateiAbsage`
|
|
55
|
+
* weiter unten und in `kontext-fragen.ts`: Das hier liest ein Kunde im
|
|
56
|
+
* Terminal. Bis Review-Runde 4 stand hier die ASCII-Umschrift, waehrend die
|
|
57
|
+
* Schwesterfunktion in DERSELBEN Datei Umlaute setzte -- eine Datei, zwei
|
|
58
|
+
* Schreibweisen. ⚠️ Der Umlaut-Fix an `kontext-hoch.ts` (Runde 3) hat diesen
|
|
59
|
+
* Zwilling stehen lassen, und die Wache schlug nicht an: Sie prueft den
|
|
60
|
+
* zitierten Ausschnitt „Hier steht kein KI-Arbeitsplatz", und der traegt
|
|
61
|
+
* zufaellig keinen Umlaut. *Eine Wache deckt den Satz, den sie kennt -- nicht
|
|
62
|
+
* die Regel dahinter.*
|
|
63
|
+
*/
|
|
64
|
+
export function arbeitsplatzAbsageZeilen(fund, s) {
|
|
65
|
+
const t = KONTEXT_TEXTE[s];
|
|
66
|
+
// Spec 3.2: zwei Namen nebeneinander -- melden, nicht still einen waehlen, und nichts schreiben.
|
|
67
|
+
if (fund.art === "beide")
|
|
68
|
+
return [t.bothFolders1(fund.pfad), t.bothFolders2, "", t.bothFolders3];
|
|
69
|
+
return [t.noWorkplace1, t.noWorkplace2, "", t.noWorkplace3];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* US-13: Der Ordner hat die alte Sprache, die Firma inzwischen eine andere.
|
|
73
|
+
* Nichts schreiben (sonst stuenden zwei Sprachen nebeneinander), den Weg nennen.
|
|
74
|
+
* ⚠️ ECHTE UMLAUTE -- das liest ein Kunde.
|
|
75
|
+
* `firmenname` (aus der Antwort des Servers) kommt als `--firma "…"` in den Rat, damit
|
|
76
|
+
* `arbeitsplatz neu` bei mehreren Firmen nicht gleich zurueckfragt (Final-Review, Fund 3);
|
|
77
|
+
* `null` (aelterer Server ohne Namen) -> der Rat ohne `--firma`, wie bisher.
|
|
78
|
+
*/
|
|
79
|
+
export function fremdeSpracheAbsage(ordner, firma, firmenname) {
|
|
80
|
+
fremdeSpracheZeilen(ordner, firma, firmenname, sprache()).forEach((z) => console.error(z));
|
|
81
|
+
}
|
|
82
|
+
/** Die Zeilen von `fremdeSpracheAbsage` -- rein, Sprache des Menschen als Pflichtwert (`check:cli`). */
|
|
83
|
+
export function fremdeSpracheZeilen(ordner, firma, firmenname, s) {
|
|
84
|
+
const t = KONTEXT_TEXTE[s];
|
|
85
|
+
return [
|
|
86
|
+
t.languageChanged1(firma, ordner, ORDNER_NAMEN[ordner].kontext),
|
|
87
|
+
t.languageChanged2,
|
|
88
|
+
"",
|
|
89
|
+
t.languageChanged3,
|
|
90
|
+
t.languageChangedCommand(befehlIn("arbeitsplatz neu", s), schalterIn("firma", s), firmenname === null ? null : alsWort(firmenname, true)), // kein-anzeigetext: Befehlsschlüssel
|
|
91
|
+
t.languageChanged4,
|
|
92
|
+
];
|
|
93
|
+
}
|
|
61
94
|
/**
|
|
62
95
|
* Was ein Mensch liest, wenn eine der fuenf Dateien keine einzige ihrer Fragen
|
|
63
96
|
* mehr traegt -- **woertlich dieselben Zeilen fuer `kontext hoch` und
|
|
@@ -66,7 +99,7 @@ export function arbeitsplatzOderAbsage() {
|
|
|
66
99
|
* 🔴 **WARUM SIE GETEILT WIRD.** `kontext fragen` zaehlte eine solche Datei
|
|
67
100
|
* vorher stillschweigend mit NULL Fragen und liess sie aus beiden Summen
|
|
68
101
|
* fallen. Gemessen mit der ausgelieferten `README.md` als `kontext/marke.md`:
|
|
69
|
-
* „12 von 12 Fragen" statt
|
|
102
|
+
* „12 von 12 Fragen" statt der vollen Zahl, „Die Marke" nirgends genannt -- und nach zwoelf
|
|
70
103
|
* Antworten meldete der Befehl `✓ Alle 12 Fragen … sind beantwortet`, waehrend
|
|
71
104
|
* `kontext hoch` einen Schritt spaeter auf genau dieser Datei abbrach.
|
|
72
105
|
* *Der lesende Befehl gab die beruhigende Auskunft, der schreibende
|
|
@@ -83,10 +116,13 @@ export function arbeitsplatzOderAbsage() {
|
|
|
83
116
|
* 🔑 ECHTE UMLAUTE -- das hier liest ein Kunde im Terminal. Die ASCII-Umschrift
|
|
84
117
|
* dieses Ordners gilt nur fuer Kommentare.
|
|
85
118
|
*/
|
|
86
|
-
export function fremdeDateiAbsage(pfad,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
119
|
+
export function fremdeDateiAbsage(pfad, feld, ankerPraefix, folge) {
|
|
120
|
+
fremdeDateiZeilen(pfad, feld, ankerPraefix, folge, sprache()).forEach((z) => console.error(z));
|
|
121
|
+
}
|
|
122
|
+
/** Die Zeilen von `fremdeDateiAbsage` -- rein, Sprache des Menschen als Pflichtwert (`check:cli`). */
|
|
123
|
+
export function fremdeDateiZeilen(pfad, feld, ankerPraefix, folge, s) {
|
|
124
|
+
const t = KONTEXT_TEXTE[s];
|
|
125
|
+
return [t.fileNotLike(pfad, t.dateiTitel[feld], folge), t.noQuestionFound(ankerPraefix), t.fetchItBack];
|
|
90
126
|
}
|
|
91
127
|
/** `--firma`/`--firma-id` -- die einzigen Optionen, die beide Richtungen kennen. */
|
|
92
128
|
export const ERLAUBT = ["firma", "firma-id"];
|
|
@@ -111,19 +147,23 @@ export const ERLAUBT = ["firma", "firma-id"];
|
|
|
111
147
|
* den Ausweg (`--ueberschreiben`) -- sie kommt woertlich vom Server und wird
|
|
112
148
|
* hier nur ausgegeben, nicht neu formuliert.
|
|
113
149
|
*/
|
|
114
|
-
export function absage(antwort, befehl) {
|
|
115
|
-
const
|
|
150
|
+
export function absage(antwort, befehl, optionen) {
|
|
151
|
+
const s = sprache();
|
|
152
|
+
const t = ALLGEMEIN_TEXTE[s];
|
|
153
|
+
const meldung = feld(antwort.koerper, "meldung") ?? t.genericFailure;
|
|
116
154
|
if (antwort.status === 402) {
|
|
117
155
|
console.error(meldung);
|
|
118
156
|
return 4;
|
|
119
157
|
}
|
|
120
158
|
if (antwort.status === 401) {
|
|
121
|
-
console.error(`${meldung}
|
|
159
|
+
console.error(`${meldung}${t.pleaseSignIn}`);
|
|
122
160
|
return 2;
|
|
123
161
|
}
|
|
124
162
|
if (antwort.status === 409) {
|
|
125
163
|
const grund = feld(antwort.koerper, "grund");
|
|
126
|
-
|
|
164
|
+
// Teil 2: `update-noetig` und `sprache-anders` (Task 14) kommen wie `veraltet` als fertiger
|
|
165
|
+
// Satz in der Kontosprache -- keine Firmenliste darunter, die mit der Lage nichts zu tun hat.
|
|
166
|
+
if (grund === "veraltet" || grund === "update-noetig" || grund === "sprache-anders") {
|
|
127
167
|
console.error(meldung);
|
|
128
168
|
return 1;
|
|
129
169
|
}
|
|
@@ -137,22 +177,22 @@ export function absage(antwort, befehl) {
|
|
|
137
177
|
typeof x.name === "string")
|
|
138
178
|
: [];
|
|
139
179
|
if (auswahl.length > 0) {
|
|
140
|
-
console.error(
|
|
141
|
-
firmenIdZeilenKontext(auswahl, befehl).forEach((z) => console.error(z));
|
|
180
|
+
console.error(t.sameNameUseId);
|
|
181
|
+
firmenIdZeilenKontext(auswahl, befehl, optionen, s).forEach((z) => console.error(z));
|
|
142
182
|
}
|
|
143
183
|
else {
|
|
144
|
-
const zeilen = firmenZeilenKontext(namen, befehl);
|
|
184
|
+
const zeilen = firmenZeilenKontext(namen, befehl, optionen, s);
|
|
145
185
|
if (zeilen.length > 0) {
|
|
146
|
-
console.error(
|
|
186
|
+
console.error(t.yourCompanies);
|
|
147
187
|
zeilen.forEach((z) => console.error(z));
|
|
148
188
|
}
|
|
149
189
|
}
|
|
150
190
|
if (grund === "keine-firma") {
|
|
151
|
-
console.error(
|
|
191
|
+
console.error(t.createCompany(BASIS_URL));
|
|
152
192
|
}
|
|
153
193
|
return 1;
|
|
154
194
|
}
|
|
155
|
-
const schluss = schlussFehler(antwort.status, meldung);
|
|
195
|
+
const schluss = schlussFehler(antwort.status, meldung, s);
|
|
156
196
|
console.error(schluss.text);
|
|
157
197
|
return schluss.wert;
|
|
158
198
|
}
|
|
@@ -160,7 +200,10 @@ export function absage(antwort, befehl) {
|
|
|
160
200
|
* `firmenZeilen` aus `firmen-liste.ts`, nur mit dem richtigen Befehl in der
|
|
161
201
|
* Zeile -- s. Kommentar an `absage`.
|
|
162
202
|
*/
|
|
163
|
-
function firmenZeilenKontext(namen, befehl) {
|
|
203
|
+
export function firmenZeilenKontext(namen, befehl, optionen, s) {
|
|
204
|
+
const t = ALLGEMEIN_TEXTE[s];
|
|
205
|
+
// Befehl, schon getippte Optionen, dann der Firmen-Schalter -- in der Sprache des Satzes.
|
|
206
|
+
const vorne = `${befehlIn(befehl, s)}${optionen}`;
|
|
164
207
|
const anzahl = (name) => namen.filter((n) => n === name).length;
|
|
165
208
|
const gesehen = new Set();
|
|
166
209
|
const zeilen = [];
|
|
@@ -170,15 +213,16 @@ function firmenZeilenKontext(namen, befehl) {
|
|
|
170
213
|
gesehen.add(name);
|
|
171
214
|
const wieOft = anzahl(name);
|
|
172
215
|
if (wieOft === 1) {
|
|
173
|
-
zeilen.push(
|
|
216
|
+
zeilen.push(t.companyLine(vorne, schalterIn("firma", s), alsWort(name, true)));
|
|
174
217
|
}
|
|
175
218
|
else {
|
|
176
|
-
zeilen.push(
|
|
219
|
+
zeilen.push(t.nameNotUnique(name, wieOft));
|
|
177
220
|
}
|
|
178
221
|
}
|
|
179
222
|
return zeilen;
|
|
180
223
|
}
|
|
181
224
|
/** `firmenIdZeilen` aus `firmen-liste.ts`, nur mit dem richtigen Befehl. */
|
|
182
|
-
function firmenIdZeilenKontext(auswahl, befehl) {
|
|
183
|
-
|
|
225
|
+
export function firmenIdZeilenKontext(auswahl, befehl, optionen, s) {
|
|
226
|
+
const vorne = `${befehlIn(befehl, s)}${optionen}`;
|
|
227
|
+
return auswahl.map((f, i) => ALLGEMEIN_TEXTE[s].companyIdLine(vorne, schalterIn("firma-id", s), f.id, f.name, i + 1));
|
|
184
228
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { zerlege } from "../argumente.js";
|
|
1
|
+
import { schalterOhneWert, zerlege } from "../argumente.js";
|
|
2
|
+
import { sprache } from "../sprache.js";
|
|
3
|
+
import { ALLGEMEIN_TEXTE } from "../texte/allgemein.js";
|
|
4
|
+
import { KONTEXT_HOCH_TEXTE } from "../texte/kontext-hoch.js";
|
|
2
5
|
import { ruf } from "../api.js";
|
|
3
|
-
import {
|
|
6
|
+
import { firmenTexte, alsMerkzettel, bekannterStandAus, merkzettelNachHoch, } from "../kontext-stand.js";
|
|
4
7
|
import { traegtFragenVon } from "../fragen-lesen.js";
|
|
5
8
|
import { leseEineDatei, leseMerkzettelDatei, schreibeMerkzettelDatei } from "../kontext-dateien.js";
|
|
6
9
|
import { ERLAUBT, absage, arbeitsplatzOderAbsage, fremdeDateiAbsage } from "./kontext-gemeinsam.js";
|
|
@@ -12,7 +15,7 @@ import { hochZeile } from "../kontext-hoch-zeile.js";
|
|
|
12
15
|
`marke_md`). Fuer vier der fuenf Dateien war das richtig; die fuenfte,
|
|
13
16
|
`kontext/kurzprofil.md`, fuellt `drei_saetze` und haette daraus `kurzprofil_md`
|
|
14
17
|
bekommen -- ein Feld, das die Route nicht kennt. Die Zuordnung steht jetzt als
|
|
15
|
-
Tabelle in `
|
|
18
|
+
Tabelle in `firmenTexte` (`../kontext-stand.js`), und dass sie mit `FELDER`
|
|
16
19
|
in der App uebereinstimmt, prueft `check:kontext`.
|
|
17
20
|
*/
|
|
18
21
|
// 📌 `bekannterStandAus` wohnte hier (Fix-Runde 1, Review-Fund 1) und ist seit
|
|
@@ -21,25 +24,10 @@ import { hochZeile } from "../kontext-hoch-zeile.js";
|
|
|
21
24
|
// von HIER haette `api.ts` in einen Kreisimport mit sich selbst gezwungen
|
|
22
25
|
// (diese Datei importiert `ruf` aus `../api.js`). Die volle Begruendung der
|
|
23
26
|
// Rechnung selbst steht jetzt dort.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
fuer den Firmen-Admin. Nur wer Admin ist, darf das; die App entscheidet.
|
|
29
|
-
|
|
30
|
-
Die fuenf sind die Dateien in kontext/: kurzprofil.md, firma.md, marke.md,
|
|
31
|
-
systeme.md, sicherheit.md.
|
|
32
|
-
|
|
33
|
-
Welche Fragen darin noch offen sind, zeigt "kimal3 kontext fragen".
|
|
34
|
-
|
|
35
|
-
--firma "Name" Noetig, wenn du zu mehreren Firmen gehoerst.
|
|
36
|
-
Die Absage nennt dir die Namen als fertige Befehle.
|
|
37
|
-
|
|
38
|
-
--firma-id "…" Fuer den Fall, dass zwei deiner Firmen GLEICH heissen.
|
|
39
|
-
|
|
40
|
-
--ueberschreiben Speichert auch dann, wenn die Firma inzwischen von
|
|
41
|
-
jemand anderem geaendert wurde (§7d).
|
|
42
|
-
`;
|
|
27
|
+
/** Die Hilfe von `kontext hoch` / `context upload` in der Sprache des Menschen. */
|
|
28
|
+
export function hilfe(s) {
|
|
29
|
+
return KONTEXT_HOCH_TEXTE[s].uploadHelp;
|
|
30
|
+
}
|
|
43
31
|
/**
|
|
44
32
|
* Schickt die fuenf Firmen-Texte des gefundenen Arbeitsplatzes nach oben --
|
|
45
33
|
* die Gegenrichtung zu `kontextRunter` (`kontext-runter.ts`). Fundregel,
|
|
@@ -58,20 +46,21 @@ const HILFE_HOCH = `
|
|
|
58
46
|
* 🔴 **Importiert bewusst KEIN `FELDER` aus `src/app/firma/kontext-felder.ts`.**
|
|
59
47
|
* `cli/src/` ist ein eigenes Paket mit eigenem `tsconfig` und darf nichts aus
|
|
60
48
|
* `src/` importieren (s. Kopf von `kontext-stand.ts`). Welche Datei welches
|
|
61
|
-
* Feld fuellt, steht deshalb in `
|
|
49
|
+
* Feld fuellt, steht deshalb in `firmenTexte` -- und dass diese Tabelle mit
|
|
62
50
|
* `FELDER` uebereinstimmt, ist eine Pruefung in `check:kontext`.
|
|
63
51
|
*/
|
|
64
52
|
export async function kontextHoch(argv) {
|
|
53
|
+
let s = sprache();
|
|
54
|
+
let t = KONTEXT_HOCH_TEXTE[s];
|
|
65
55
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
66
|
-
console.log(
|
|
56
|
+
console.log(hilfe(s));
|
|
67
57
|
return 0;
|
|
68
58
|
}
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
// deshalb VOR der Zerlegung herausgefiltert, genau wie `--help`/`-h` oben
|
|
59
|
+
// ⚠️ `zerlege` kennt keine Optionen ohne Wert -- `--ueberschreiben` (englisch `--overwrite`)
|
|
60
|
+
// wird deshalb VOR der Zerlegung herausgefiltert, genau wie `--help`/`-h` oben
|
|
72
61
|
// nie an `zerlege` gereicht werden.
|
|
73
|
-
const ohneFlag = argv
|
|
74
|
-
const zerlegt = zerlege(ohneFlag, ERLAUBT);
|
|
62
|
+
const { gesetzt: ueberschreiben, rest: ohneFlag } = schalterOhneWert(argv, "ueberschreiben");
|
|
63
|
+
const zerlegt = zerlege(ohneFlag, ERLAUBT, s);
|
|
75
64
|
if (!zerlegt.ok) {
|
|
76
65
|
console.error(zerlegt.meldung);
|
|
77
66
|
return 1;
|
|
@@ -83,8 +72,8 @@ export async function kontextHoch(argv) {
|
|
|
83
72
|
// (`bekannterStandAus`), nicht nur aus den Dateien, die gleich gelesen
|
|
84
73
|
// werden. Die Firmenzeile traegt genau EIN `geaendert_am` fuer alle fuenf
|
|
85
74
|
// Felder -- jeder nicht-leere Eintrag kennt es also, auch der der `CLAUDE.md`.
|
|
86
|
-
const lokalerMerkzettel = leseMerkzettelDatei(ordner);
|
|
87
|
-
const bekannterStand = bekannterStandAus(lokalerMerkzettel);
|
|
75
|
+
const lokalerMerkzettel = leseMerkzettelDatei(ordner.pfad);
|
|
76
|
+
const bekannterStand = bekannterStandAus(lokalerMerkzettel, ordner.sprache);
|
|
88
77
|
/*
|
|
89
78
|
---- die fuenf Texte lesen ---------------------------------------------
|
|
90
79
|
|
|
@@ -95,15 +84,15 @@ export async function kontextHoch(argv) {
|
|
|
95
84
|
benennen kann, ist teurer als ein Abbruch, der klar sagt, warum.*
|
|
96
85
|
*/
|
|
97
86
|
const werte = {};
|
|
98
|
-
for (const datei of
|
|
99
|
-
const gelesen = leseEineDatei(ordner, datei.pfad);
|
|
87
|
+
for (const datei of firmenTexte(ordner.sprache)) {
|
|
88
|
+
const gelesen = leseEineDatei(ordner.pfad, datei.pfad);
|
|
100
89
|
if (!gelesen.ok) {
|
|
101
90
|
console.error(gelesen.meldung);
|
|
102
91
|
return 1;
|
|
103
92
|
}
|
|
104
93
|
if (gelesen.inhalt === null) {
|
|
105
|
-
console.error(
|
|
106
|
-
console.error(
|
|
94
|
+
console.error(t.uploadFileMissing(datei.pfad));
|
|
95
|
+
console.error(t.uploadFetchFirst);
|
|
107
96
|
return 1;
|
|
108
97
|
}
|
|
109
98
|
/*
|
|
@@ -121,7 +110,7 @@ export async function kontextHoch(argv) {
|
|
|
121
110
|
angelegt hat, weil `kontext runter` noch nie lief.
|
|
122
111
|
*/
|
|
123
112
|
if (!traegtFragenVon(gelesen.inhalt, datei.ankerPraefix)) {
|
|
124
|
-
fremdeDateiAbsage(datei.pfad, datei.
|
|
113
|
+
fremdeDateiAbsage(datei.pfad, datei.feld, datei.ankerPraefix, t.nothingSaved);
|
|
125
114
|
return 1;
|
|
126
115
|
}
|
|
127
116
|
werte[datei.feld] = gelesen.inhalt;
|
|
@@ -134,23 +123,28 @@ export async function kontextHoch(argv) {
|
|
|
134
123
|
suche.set("firma", wunsch);
|
|
135
124
|
if (wunschId !== undefined)
|
|
136
125
|
suche.set("firma-id", wunschId);
|
|
137
|
-
const pfad = suche.toString() ? `/api/cli/kontext?${suche.toString()}` : "/api/cli/kontext";
|
|
138
|
-
|
|
126
|
+
const pfad = suche.toString() ? `/api/cli/kontext?${suche.toString()}` : "/api/cli/kontext"; // kein-anzeigetext: Pfad der Schnittstelle
|
|
127
|
+
// 🌐 Teil 2: Die Sprache des ORDNERS geht mit. Der Server haelt sie gegen die Firmensprache und
|
|
128
|
+
// sagt `sprache-anders` (409), statt deutsche Texte in eine englische Firma zu schreiben (US-13).
|
|
129
|
+
const koerper = { stand: bekannterStand, ...werte, sprache: ordner.sprache };
|
|
139
130
|
if (ueberschreiben)
|
|
140
131
|
koerper.ueberschreiben = true;
|
|
141
|
-
const antwort = await ruf(pfad, { methode: "POST", mitAusweis: true, koerper });
|
|
132
|
+
const antwort = await ruf(pfad, { methode: "POST", mitAusweis: true, koerper }); // kein-anzeigetext: HTTP-Verb
|
|
133
|
+
// 🌐 Die Antwort kann die Kontosprache umgestellt haben (Spec 3.2, Schritt 3): Was ab hier gedruckt wird, in der neuen.
|
|
134
|
+
s = sprache();
|
|
135
|
+
t = KONTEXT_HOCH_TEXTE[s];
|
|
142
136
|
if (antwort.status !== 200) {
|
|
143
|
-
return absage(antwort, "kontext hoch");
|
|
137
|
+
return absage(antwort, "kontext hoch", ""); // kein-anzeigetext: Befehlsschlüssel
|
|
144
138
|
}
|
|
145
139
|
// 🔴 Ein `200` mit unlesbarem Rumpf ist KEIN Erfolg -- dasselbe Muster wie
|
|
146
140
|
// in `kontextRunter` und in `firma-daten.ts`.
|
|
147
141
|
if (antwort.koerper === null || typeof antwort.koerper !== "object") {
|
|
148
|
-
console.error(
|
|
142
|
+
console.error(ALLGEMEIN_TEXTE[s].unreadableAnswer);
|
|
149
143
|
return 3;
|
|
150
144
|
}
|
|
151
145
|
const ergebnis = alsHochAntwort(antwort.koerper);
|
|
152
146
|
if (ergebnis === null) {
|
|
153
|
-
console.error(
|
|
147
|
+
console.error(ALLGEMEIN_TEXTE[s].unreadableAnswer);
|
|
154
148
|
return 3;
|
|
155
149
|
}
|
|
156
150
|
/*
|
|
@@ -173,7 +167,7 @@ export async function kontextHoch(argv) {
|
|
|
173
167
|
CLAUDE.md" und riete zu `kontext hoch` -- dem Befehl, der sie gar nicht
|
|
174
168
|
mitnimmt. Gemessen auf der Kundenstrecke am 2026-08-25.
|
|
175
169
|
*/
|
|
176
|
-
const zuSchreiben = merkzettelNachHoch(ergebnis.merkzettel, lokalerMerkzettel,
|
|
170
|
+
const zuSchreiben = merkzettelNachHoch(ergebnis.merkzettel, lokalerMerkzettel, firmenTexte(ordner.sprache).map((d) => d.pfad), ordner.sprache);
|
|
177
171
|
/*
|
|
178
172
|
🔴 **DIE ERFOLGSMELDUNG STEHT VOR DEM MERKZETTEL** (Review-Runde 4).
|
|
179
173
|
|
|
@@ -186,8 +180,8 @@ export async function kontextHoch(argv) {
|
|
|
186
180
|
was daneben schiefging. Was hochgeschickt wurde, haengt nicht daran, ob ein
|
|
187
181
|
Merkzettel auf der Platte landet.
|
|
188
182
|
*/
|
|
189
|
-
console.log(hochZeile(ergebnis.uebernommen));
|
|
190
|
-
const merkzettelSchreiben = schreibeMerkzettelDatei(ordner, zuSchreiben);
|
|
183
|
+
console.log(hochZeile(ergebnis.uebernommen, s));
|
|
184
|
+
const merkzettelSchreiben = schreibeMerkzettelDatei(ordner.pfad, zuSchreiben);
|
|
191
185
|
if (!merkzettelSchreiben.ok) {
|
|
192
186
|
/*
|
|
193
187
|
🔴 **ECHTE UMLAUTE -- das liest ein Kunde im Terminal** (Projektregel,
|
|
@@ -209,7 +203,7 @@ export async function kontextHoch(argv) {
|
|
|
209
203
|
verteilt und ist durch eine `includes`-Pruefung ohnehin nicht erfassbar.
|
|
210
204
|
*Wer den Satz hier aendert, aendert ihn dort von Hand mit.*
|
|
211
205
|
*/
|
|
212
|
-
console.error(
|
|
206
|
+
console.error(t.savedButTracking);
|
|
213
207
|
console.error(merkzettelSchreiben.meldung);
|
|
214
208
|
// B-d (Dennis, 17.09.): Das ist ein ERFOLG -- die Firma hat gespeichert.
|
|
215
209
|
// Der Rueckgabewert ist fuer Maschinen da, und fuer die ist "gespeichert"
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { zerlege } from "../argumente.js";
|
|
2
|
+
import { sprache } from "../sprache.js";
|
|
3
|
+
import { ALLGEMEIN_TEXTE } from "../texte/allgemein.js";
|
|
4
|
+
import { KONTEXT_TEXTE } from "../texte/kontext.js";
|
|
5
|
+
import { ratNachUnberuehrt } from "../kontext-rat.js";
|
|
2
6
|
import { ruf } from "../api.js";
|
|
3
7
|
import { heuteAus } from "../nachricht.js";
|
|
4
8
|
import { istUnsichererPfad } from "../arbeitsplatz-dateien.js";
|
|
5
|
-
import { LEER,
|
|
9
|
+
import { LEER, verwalteteDateien, alsMerkzettel, sicherungsOrdner, sicherungsZiel, lageAusMerkzetteln, } from "../kontext-stand.js";
|
|
6
10
|
import { leseEineDatei, leseMerkzettelDatei, schreibeMerkzettelDatei, schreibeVerwalteteDatei, sichereDatei, } from "../kontext-dateien.js";
|
|
7
|
-
import { ERLAUBT, absage, arbeitsplatzOderAbsage } from "./kontext-gemeinsam.js";
|
|
11
|
+
import { ERLAUBT, absage, arbeitsplatzOderAbsage, fremdeSpracheAbsage } from "./kontext-gemeinsam.js";
|
|
8
12
|
/**
|
|
9
13
|
* Holt den Firmenkontext von der App und legt ihn in den verwalteten Dateien
|
|
10
14
|
* des gefundenen Arbeitsplatzes ab -- `CLAUDE.md` und die fuenf Dateien in
|
|
@@ -21,7 +25,7 @@ import { ERLAUBT, absage, arbeitsplatzOderAbsage } from "./kontext-gemeinsam.js"
|
|
|
21
25
|
* Git benutzt.
|
|
22
26
|
*
|
|
23
27
|
* ⛔ **Unterhalb von `werkbank-<name>/` wird nichts geschrieben** (Spec §4).
|
|
24
|
-
* Dieser Befehl kennt genau die Pfade aus `
|
|
28
|
+
* Dieser Befehl kennt genau die Pfade aus `verwalteteDateien(sprache)`, und in keinem
|
|
25
29
|
* davon steht ein Personenname.
|
|
26
30
|
*
|
|
27
31
|
* 🔁 **Ruling T9-2:** Die Gegenrichtung, `kontextHoch`, wohnt seit dem Split
|
|
@@ -29,25 +33,18 @@ import { ERLAUBT, absage, arbeitsplatzOderAbsage } from "./kontext-gemeinsam.js"
|
|
|
29
33
|
* Firmenwahl-Absage und die `--firma`/`--firma-id`-Optionen ueber
|
|
30
34
|
* `kontext-gemeinsam.ts`.
|
|
31
35
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
ihn in deinem KI-Arbeitsplatz ab. Was du selbst geaendert hast, fasst der
|
|
37
|
-
Befehl nicht an -- er sagt dir, wie du es einbringst.
|
|
38
|
-
|
|
39
|
-
--firma "Name" Noetig, wenn du zu mehreren Firmen gehoerst.
|
|
40
|
-
Die Absage nennt dir die Namen als fertige Befehle.
|
|
41
|
-
|
|
42
|
-
--firma-id "…" Fuer den Fall, dass zwei deiner Firmen GLEICH heissen.
|
|
43
|
-
Auch diese Absage nennt dir fertige Befehle.
|
|
44
|
-
`;
|
|
36
|
+
/** Die Hilfe von `kontext runter` / `context download` in der Sprache des Menschen. */
|
|
37
|
+
export function hilfe(s) {
|
|
38
|
+
return KONTEXT_TEXTE[s].downloadHelp;
|
|
39
|
+
}
|
|
45
40
|
export async function kontextRunter(argv) {
|
|
41
|
+
let s = sprache();
|
|
42
|
+
let t = KONTEXT_TEXTE[s];
|
|
46
43
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
47
|
-
console.log(
|
|
44
|
+
console.log(hilfe(s));
|
|
48
45
|
return 0;
|
|
49
46
|
}
|
|
50
|
-
const zerlegt = zerlege(argv, ERLAUBT);
|
|
47
|
+
const zerlegt = zerlege(argv, ERLAUBT, s);
|
|
51
48
|
if (!zerlegt.ok) {
|
|
52
49
|
console.error(zerlegt.meldung);
|
|
53
50
|
return 1;
|
|
@@ -66,23 +63,32 @@ export async function kontextRunter(argv) {
|
|
|
66
63
|
suche.set("firma", wunsch);
|
|
67
64
|
if (wunschId !== undefined)
|
|
68
65
|
suche.set("firma-id", wunschId);
|
|
69
|
-
const pfad = suche.toString() ? `/api/cli/kontext?${suche.toString()}` : "/api/cli/kontext";
|
|
70
|
-
const antwort = await ruf(pfad, { methode: "GET", mitAusweis: true });
|
|
66
|
+
const pfad = suche.toString() ? `/api/cli/kontext?${suche.toString()}` : "/api/cli/kontext"; // kein-anzeigetext: Pfad der Schnittstelle
|
|
67
|
+
const antwort = await ruf(pfad, { methode: "GET", mitAusweis: true }); // kein-anzeigetext: HTTP-Verb
|
|
68
|
+
// 🌐 Die Antwort kann die Kontosprache umgestellt haben (Spec 3.2, Schritt 3): Was ab hier gedruckt wird, in der neuen.
|
|
69
|
+
s = sprache();
|
|
70
|
+
t = KONTEXT_TEXTE[s];
|
|
71
71
|
if (antwort.status !== 200) {
|
|
72
|
-
return absage(antwort, "kontext runter");
|
|
72
|
+
return absage(antwort, "kontext runter", ""); // kein-anzeigetext: Befehlsschlüssel
|
|
73
73
|
}
|
|
74
74
|
// 🔴 Ein `200` mit unlesbarem Rumpf ist KEIN Erfolg -- dasselbe Muster wie
|
|
75
75
|
// in `firma-daten.ts`. `ruf` verschluckt Parse-Fehler zu `null`.
|
|
76
76
|
if (antwort.koerper === null || typeof antwort.koerper !== "object") {
|
|
77
|
-
console.error(
|
|
77
|
+
console.error(ALLGEMEIN_TEXTE[s].unreadableAnswer);
|
|
78
78
|
return 3;
|
|
79
79
|
}
|
|
80
80
|
const daten = alsKontextAntwort(antwort.koerper);
|
|
81
81
|
if (daten === null) {
|
|
82
|
-
console.error(
|
|
82
|
+
console.error(ALLGEMEIN_TEXTE[s].unreadableAnswer);
|
|
83
83
|
return 3;
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
// 🔴 US-13: Die Firma spricht inzwischen eine andere Sprache als dieser Ordner. VOR der
|
|
86
|
+
// Schleife pruefen -- sonst stuenden nach dem Schreiben zwei Sprachen nebeneinander.
|
|
87
|
+
if (daten.sprache !== ordner.sprache) {
|
|
88
|
+
fremdeSpracheAbsage(ordner.sprache, daten.sprache, daten.firma.name);
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
const lokalerMerkzettel = leseMerkzettelDatei(ordner.pfad);
|
|
86
92
|
const heute = heuteAus(new Date());
|
|
87
93
|
const geschrieben = [];
|
|
88
94
|
// Punkt A-1: die Teilmenge von `geschrieben`, bei der NICHT die Firma etwas
|
|
@@ -92,23 +98,35 @@ export async function kontextRunter(argv) {
|
|
|
92
98
|
const vorlageErneuert = [];
|
|
93
99
|
const gesicherte = [];
|
|
94
100
|
const unberuehrt = [];
|
|
95
|
-
|
|
101
|
+
/*
|
|
102
|
+
🔴 **ERST ALLES PRUEFEN UND LESEN, DANN SCHREIBEN** (Final-Review, Fund 2).
|
|
103
|
+
Bis dahin lief Pruefen und Schreiben in EINER Schleife: Fehlte in der
|
|
104
|
+
Antwort die vierte Datei, waren `CLAUDE.md` und die ersten drei schon
|
|
105
|
+
ueberschrieben, der Merkzettel aber nicht -- ein halber Stand, den das
|
|
106
|
+
naechste `runter` falsch einordnet. Jetzt bricht eine unvollstaendige
|
|
107
|
+
Lieferung (oder eine unlesbare lokale Datei) ab, bevor ein Byte geschrieben ist.
|
|
108
|
+
*/
|
|
109
|
+
const vorbereitet = [];
|
|
110
|
+
for (const verwalteterPfad of verwalteteDateien(ordner.sprache)) {
|
|
96
111
|
const serverDatei = daten.dateien.find((d) => d.pfad === verwalteterPfad);
|
|
97
112
|
if (!serverDatei) {
|
|
98
|
-
console.error(
|
|
113
|
+
console.error(t.answerMissingFile(verwalteterPfad));
|
|
99
114
|
return 3;
|
|
100
115
|
}
|
|
101
116
|
// Zweites Netz -- s. Kommentar an `schreibeVerwalteteDatei`: `pfad` kommt
|
|
102
117
|
// hier aus der eigenen Iteration, nicht roh vom Server, trotzdem geprueft.
|
|
103
118
|
if (istUnsichererPfad(serverDatei.pfad)) {
|
|
104
|
-
console.error(
|
|
119
|
+
console.error(t.answerUnsafePath(serverDatei.pfad));
|
|
105
120
|
return 3;
|
|
106
121
|
}
|
|
107
|
-
const lokalGelesen = leseEineDatei(ordner, verwalteterPfad);
|
|
122
|
+
const lokalGelesen = leseEineDatei(ordner.pfad, verwalteterPfad);
|
|
108
123
|
if (!lokalGelesen.ok) {
|
|
109
124
|
console.error(lokalGelesen.meldung);
|
|
110
125
|
return 1;
|
|
111
126
|
}
|
|
127
|
+
vorbereitet.push({ pfad: verwalteterPfad, serverInhalt: serverDatei.inhalt, lokalerInhalt: lokalGelesen.inhalt });
|
|
128
|
+
}
|
|
129
|
+
for (const { pfad: verwalteterPfad, serverInhalt, lokalerInhalt } of vorbereitet) {
|
|
112
130
|
/*
|
|
113
131
|
🔴 **DIE BEIDEN MERKZETTEL GEHEN ALS GANZES HINEIN -- Punkt A-1,
|
|
114
132
|
2026-08-26.** Hier standen vorher drei Zeilen, die den Eintrag, den
|
|
@@ -125,15 +143,15 @@ export async function kontextRunter(argv) {
|
|
|
125
143
|
*/
|
|
126
144
|
const lage = lageAusMerkzetteln({
|
|
127
145
|
pfad: verwalteterPfad,
|
|
128
|
-
lokalerInhalt
|
|
129
|
-
serverInhalt
|
|
146
|
+
lokalerInhalt,
|
|
147
|
+
serverInhalt,
|
|
130
148
|
lokal: lokalerMerkzettel,
|
|
131
149
|
vomServer: daten.merkzettel,
|
|
132
150
|
});
|
|
133
151
|
if (lage === "beides") {
|
|
134
|
-
// `
|
|
152
|
+
// `lokalerInhalt` ist hier garantiert eine Zeichenkette:
|
|
135
153
|
// `lageFuerDatei` liefert "beides" nie, wenn `lokalerInhalt === null`.
|
|
136
|
-
const sicherung = sichereDatei(ordner, verwalteterPfad,
|
|
154
|
+
const sicherung = sichereDatei(ordner.pfad, verwalteterPfad, lokalerInhalt, heute, ordner.sprache);
|
|
137
155
|
if (!sicherung.ok) {
|
|
138
156
|
console.error(sicherung.meldung);
|
|
139
157
|
return 1;
|
|
@@ -163,7 +181,7 @@ export async function kontextRunter(argv) {
|
|
|
163
181
|
vermisst hat, weil ihn niemand erreichen konnte.
|
|
164
182
|
*/
|
|
165
183
|
if (lage === "server-neuer" || lage === "beides" || lage === "vorlage-neuer") {
|
|
166
|
-
const geschriebenErg = schreibeVerwalteteDatei(ordner, verwalteterPfad,
|
|
184
|
+
const geschriebenErg = schreibeVerwalteteDatei(ordner.pfad, verwalteterPfad, serverInhalt, ordner.sprache);
|
|
167
185
|
if (!geschriebenErg.ok) {
|
|
168
186
|
console.error(geschriebenErg.meldung);
|
|
169
187
|
return 1;
|
|
@@ -200,7 +218,7 @@ export async function kontextRunter(argv) {
|
|
|
200
218
|
dieselbe Sorte Fehlalarm wie eine, die nie ankommt.*
|
|
201
219
|
*/
|
|
202
220
|
const merkzettelZumSchreiben = { firma_id: daten.firma.id, dateien: daten.merkzettel.dateien };
|
|
203
|
-
const merkzettelSchreiben = schreibeMerkzettelDatei(ordner, merkzettelZumSchreiben);
|
|
221
|
+
const merkzettelSchreiben = schreibeMerkzettelDatei(ordner.pfad, merkzettelZumSchreiben);
|
|
204
222
|
if (!merkzettelSchreiben.ok) {
|
|
205
223
|
console.error(merkzettelSchreiben.meldung);
|
|
206
224
|
return 1;
|
|
@@ -217,49 +235,46 @@ export async function kontextRunter(argv) {
|
|
|
217
235
|
// (vor dem Ergebnis) und nennt den Ordner. Die eigentliche Reihenfolge
|
|
218
236
|
// (erst sichern, dann ueberschreiben) erzwingt schon der Code oben.
|
|
219
237
|
if (gesicherte.length > 0) {
|
|
220
|
-
console.log(
|
|
238
|
+
console.log(t.backupHeader(sicherungsOrdner(ordner.sprache, heute)));
|
|
221
239
|
for (const g of gesicherte) {
|
|
222
240
|
if (g.nebenVorhandener) {
|
|
223
|
-
const bisherige = sicherungsZiel(heute, g.pfad).split("/").pop();
|
|
241
|
+
const bisherige = sicherungsZiel(ordner.sprache, heute, g.pfad).split("/").pop();
|
|
224
242
|
const neue = g.ziel.split("/").pop();
|
|
225
|
-
console.log(
|
|
226
|
-
`unveraendert stehen. Deine neuere Fassung sichere ich zusaetzlich als ${neue}, ` +
|
|
227
|
-
"bevor ich die Datei im Ordner ersetze.");
|
|
243
|
+
console.log(t.backupAlreadyToday(g.pfad, bisherige, neue));
|
|
228
244
|
}
|
|
229
245
|
else {
|
|
230
|
-
console.log(
|
|
246
|
+
console.log(t.backupPlain(g.pfad, g.ziel.split("/").pop()));
|
|
231
247
|
}
|
|
232
248
|
}
|
|
233
249
|
}
|
|
234
250
|
if (geschrieben.length > 0) {
|
|
235
|
-
console.log(
|
|
251
|
+
console.log(t.updated(geschrieben.join(", ")));
|
|
236
252
|
}
|
|
237
253
|
// 🔴 Punkt A-1: Eine eigene Zeile, kein stilles Mitschreiben. „Aktualisiert"
|
|
238
254
|
// heisst fuer den Leser sonst automatisch „meine Firma hat etwas gesagt" --
|
|
239
255
|
// und dann sucht er in der App eine Aenderung, die es dort nicht gibt.
|
|
240
256
|
if (vorlageErneuert.length > 0) {
|
|
241
|
-
console.log(
|
|
242
|
-
console.log(
|
|
243
|
-
" von dir verloren gegangen. Hättest du seitdem etwas geändert, hätte ich vorher gesichert.");
|
|
257
|
+
console.log(t.fromOurTemplate(vorlageErneuert.join(", ")));
|
|
258
|
+
console.log(t.templateUnchanged);
|
|
244
259
|
}
|
|
245
260
|
// §8: Ein Fehlerfall darf nie denselben Namen tragen wie ein Erfolgsfall --
|
|
246
261
|
// "nichts geschrieben" heisst hier DREI verschiedene Dinge, und die Ausgabe
|
|
247
262
|
// muss sie unterscheiden, nicht nur die Rueckgabe (alle drei geben 0).
|
|
248
263
|
if (unberuehrt.length > 0) {
|
|
249
|
-
console.log(
|
|
264
|
+
console.log(t.leftAlone(unberuehrt.join(", ")));
|
|
250
265
|
// 🔴 Der Rat haengt an der DATEI, nicht nur an der Rolle -- s.
|
|
251
|
-
// `ratNachUnberuehrt` (kontext-
|
|
252
|
-
for (const zeile of ratNachUnberuehrt(unberuehrt, daten.rolle, daten.adminName)) {
|
|
266
|
+
// `ratNachUnberuehrt` (kontext-rat.ts), Review-Befund F-3.
|
|
267
|
+
for (const zeile of ratNachUnberuehrt(unberuehrt, daten.rolle, daten.adminName, ordner.sprache, s)) {
|
|
253
268
|
console.log(zeile);
|
|
254
269
|
}
|
|
255
270
|
}
|
|
256
271
|
if (geschrieben.length === 0 && unberuehrt.length === 0) {
|
|
257
|
-
const alleLeer =
|
|
272
|
+
const alleLeer = verwalteteDateien(ordner.sprache).every((p) => (daten.merkzettel.dateien[p]?.stand ?? LEER) === LEER);
|
|
258
273
|
if (alleLeer) {
|
|
259
|
-
console.log(
|
|
274
|
+
console.log(t.companyEmpty);
|
|
260
275
|
}
|
|
261
276
|
else {
|
|
262
|
-
console.log(
|
|
277
|
+
console.log(t.upToDate);
|
|
263
278
|
}
|
|
264
279
|
}
|
|
265
280
|
return 0;
|
|
@@ -277,6 +292,8 @@ function alsKontextAntwort(koerper) {
|
|
|
277
292
|
const firmaId = firmaRoh.id;
|
|
278
293
|
if (typeof firmaId !== "string" || firmaId.trim() === "")
|
|
279
294
|
return null;
|
|
295
|
+
const firmaNameRoh = firmaRoh.name;
|
|
296
|
+
const firmaName = typeof firmaNameRoh === "string" && firmaNameRoh.trim() !== "" ? firmaNameRoh : null;
|
|
280
297
|
const rolle = k.rolle;
|
|
281
298
|
if (rolle !== "admin" && rolle !== "member")
|
|
282
299
|
return null;
|
|
@@ -301,5 +318,7 @@ function alsKontextAntwort(koerper) {
|
|
|
301
318
|
const merkzettel = alsMerkzettel(k.merkzettel);
|
|
302
319
|
if (merkzettel === null)
|
|
303
320
|
return null;
|
|
304
|
-
|
|
321
|
+
// 🌐 Teil 2: die Firmensprache. Fehlt das Feld, antwortet ein Server vor 0.3.0 -- der kennt nur Deutsch.
|
|
322
|
+
const sprache = k.sprache === "en" ? "en" : "de";
|
|
323
|
+
return { firma: { id: firmaId, name: firmaName }, rolle, adminName, dateien, merkzettel, sprache };
|
|
305
324
|
}
|