kimal3 0.2.10 → 0.3.1
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 +137 -2
- 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 +143 -104
- package/dist/befehle-katalog-en.js +185 -0
- package/dist/befehle-katalog.js +11 -50
- 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 +79 -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 +3 -3
- package/skill/SKILL.md +9 -9
- package/skill/commands/k3.md +7 -4
- 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
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
export const BEFEHLE_EN = {
|
|
2
|
+
"kimal3 login": {
|
|
3
|
+
stempel: "013360ee",
|
|
4
|
+
befehl: "kimal3 login",
|
|
5
|
+
tippen: "! kimal3 login",
|
|
6
|
+
terminal: "kimal3 login",
|
|
7
|
+
beschreibung: "Connect this computer to your account",
|
|
8
|
+
rhythmusOderSatz: "once per computer",
|
|
9
|
+
details: [
|
|
10
|
+
"It shows you an address and a code: open the address in your browser and type in the code. The terminal picks up the confirmation automatically — you have ten minutes.",
|
|
11
|
+
"After that, it stays that way. Your sign-in is saved as a file in your user folder and survives IDE restarts, computer restarts and updates. If the connection does break after a long pause, a command will tell you — then just run kimal3 login once more; that's not an error.",
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
"kimal3 skill install": {
|
|
15
|
+
stempel: "8491e5d6",
|
|
16
|
+
befehl: "kimal3 skill install",
|
|
17
|
+
tippen: "! kimal3 skill install",
|
|
18
|
+
terminal: "kimal3 skill install",
|
|
19
|
+
beschreibung: "Teach Claude to use this tool — and give you the /k3 commands",
|
|
20
|
+
rhythmusOderSatz: "once — and again after every update",
|
|
21
|
+
details: [
|
|
22
|
+
"The command that makes the others useful: it sets up 🤖 Claude's instructions (the “skill”) and 🧑 your slash commands.",
|
|
23
|
+
"It does NOT run automatically — run it once after installing and again after every update. Otherwise Claude keeps working with the old instructions.",
|
|
24
|
+
"You'll know it worked when it reports “Skill created.” and lists the slash commands. Claude only picks up both in your NEXT session — restart the current one.",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
"kimal3 arbeitsplatz neu": {
|
|
28
|
+
stempel: "231b90bf",
|
|
29
|
+
befehl: "kimal3 workplace new",
|
|
30
|
+
tippen: "! kimal3 workplace new",
|
|
31
|
+
terminal: "kimal3 workplace new",
|
|
32
|
+
beschreibung: "Create the whole AI Workplace — company level and workbench",
|
|
33
|
+
rhythmusOderSatz: "once per company",
|
|
34
|
+
details: [
|
|
35
|
+
"Fetches the template from your Pro account and creates it here as a real folder — CLAUDE.md, routine commands, the workbench for your projects. The same package is available to download on /pro.",
|
|
36
|
+
"The folder is called AI-Workplace (KI-Arbeitsplatz for a German-speaking company). To keep several companies apart, use the folder above it, e.g. Clients/ARNO/AI-Workplace. Add your first name and your workbench inside it is called workbench-sabine: kimal3 workplace new sabine.",
|
|
37
|
+
"If the target folder already exists and isn't empty, the command stops instead of overwriting anything — your work is safe. You'll know it worked when it tells you how many files it created.",
|
|
38
|
+
"⚠️ It also creates the company level (context/ with brand, systems, security — kontext/ in a German workplace). If that already exists, you need kimal3 workbench new — otherwise you end up with a second company inside the first.",
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
"kimal3 werkbank neu": {
|
|
42
|
+
stempel: "da69f97f",
|
|
43
|
+
befehl: "kimal3 workbench new",
|
|
44
|
+
tippen: "! kimal3 workbench new",
|
|
45
|
+
terminal: "kimal3 workbench new",
|
|
46
|
+
beschreibung: "Only create your own workbench in an existing company",
|
|
47
|
+
rhythmusOderSatz: "once per person",
|
|
48
|
+
details: [
|
|
49
|
+
"For everyone except the first person: the company folder is already there (context/ with brand, systems, security — kontext/ in a German workplace) — you only need your own workbench inside it.",
|
|
50
|
+
"🔴 It doesn't touch the company level. Not a single byte in context/, CLAUDE.md or README.md — not even by writing an ‘identical’ copy over it.",
|
|
51
|
+
"It only runs if you really are in a company folder. If the company level next to it is missing, it stops and tells you — a workbench without it leads nowhere, because its settings refer to ../context (../kontext in a German workplace).",
|
|
52
|
+
"Add your first name — the folder is named after it: sabine becomes workbench-sabine. Without it, the server builds the name from your sign-in address. That way you can see later whose workbench is whose.",
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
"kimal3 kontext runter": {
|
|
56
|
+
stempel: "9ccf1083",
|
|
57
|
+
befehl: "kimal3 context download",
|
|
58
|
+
tippen: "! kimal3 context download",
|
|
59
|
+
terminal: "kimal3 context download",
|
|
60
|
+
beschreibung: "Fetch the company context — CLAUDE.md and the five files in context/",
|
|
61
|
+
rhythmusOderSatz: "whenever the company might have changed something",
|
|
62
|
+
details: [
|
|
63
|
+
"Fetches CLAUDE.md and the five files in context/ (kontext/ in a German workplace) from your company and puts them in your AI Workplace. Anything you've changed locally is left alone — it tells you how to send it up.",
|
|
64
|
+
"If you changed a file locally AND the company has changed it too in the meantime, it saves your version in context/before-<date>/ (kontext/vorher-<datum>/ in a German workplace) first, then replaces it — nothing gets lost.",
|
|
65
|
+
"You'll know it worked when it names the updated files or says “Your company context is up to date.”",
|
|
66
|
+
"⚠️ Like kimal3 workbench new, it needs your own Pro account. Without one you get exit code 4 — then don't retry.",
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
"kimal3 kontext fragen": {
|
|
70
|
+
stempel: "34decb4c",
|
|
71
|
+
befehl: "kimal3 context questions",
|
|
72
|
+
tippen: "/k3context",
|
|
73
|
+
terminal: "kimal3 context questions",
|
|
74
|
+
beschreibung: "Answer the questions about your company — Claude takes you through them",
|
|
75
|
+
rhythmusOderSatz: "let's answer the questions about my company",
|
|
76
|
+
details: [
|
|
77
|
+
"Reads the five files in context/ (kontext/ in a German workplace) and prints every question that has nothing written under it yet — with file, question and hint. If all are answered, it says so in one sentence.",
|
|
78
|
+
"It only reads: no network, no sign-in, no writing. That's why it comes first — Claude then asks you the questions one by one and writes your answers into the files.",
|
|
79
|
+
"After that, kimal3 context upload sends them to the company. Only the company admin may do that; everyone else passes their answers on.",
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
"kimal3 kontext hoch": {
|
|
83
|
+
stempel: "5926c657",
|
|
84
|
+
befehl: "kimal3 context upload",
|
|
85
|
+
tippen: "! kimal3 context upload",
|
|
86
|
+
terminal: "kimal3 context upload",
|
|
87
|
+
beschreibung: "Upload your local changes to the five company texts",
|
|
88
|
+
rhythmusOderSatz: "after you've edited context/*.md — company admin only",
|
|
89
|
+
details: [
|
|
90
|
+
"Sends all five company texts to your company — the files in context/ (profile.md, company.md, brand.md, systems.md, security.md; in a German workplace kontext/ with kurzprofil.md, firma.md, marke.md, systeme.md, sicherheit.md). That way they also reach your colleagues with their next kimal3 context download.",
|
|
91
|
+
"🔴 Only the company admin may do this. If you're not one, it tells you — then pass your addition on to the company admin; trying again won't change that.",
|
|
92
|
+
"⚠️ If something goes wrong, what counts is the MESSAGE, not the number after it. Exit code 1 stands for ‘you're not an admin’, ‘there's no workplace here’, ‘someone else has changed it in the meantime’ (way out: --overwrite) and several more. The same code also appears under “The company has saved your changes — only the local tracking file couldn't be written”, which only says that a file on your disk couldn't be written. That is a success: everything reached the company. Read the sentence, not the number.",
|
|
93
|
+
"If one of the five files no longer has its original questions — for example because something else was copied over it — it stops and sends nothing, not even the other four. kimal3 context download brings the file back.",
|
|
94
|
+
"You'll know it worked when it reports “✓ changed at the company:” with the file names.",
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
"kimal3 projekt neu …": {
|
|
98
|
+
stempel: "34505297",
|
|
99
|
+
befehl: "kimal3 project new …",
|
|
100
|
+
tippen: "/k3project <what you built>",
|
|
101
|
+
terminal: 'kimal3 project new --title "Quote generator" --hours 4 --result 1200',
|
|
102
|
+
beschreibung: "Add a project to your success profile",
|
|
103
|
+
rhythmusOderSatz: "add this as a project",
|
|
104
|
+
details: [
|
|
105
|
+
"Just say so when you've finished something. Claude puts together the title, time saved and net result itself — it knows the numbers from your conversation. The slash command is the same route, just one step quicker.",
|
|
106
|
+
"It runs kimal3 project new. Only the title is required; kimal3 project new --help shows all the options.",
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
"kimal3 projekt liste": {
|
|
110
|
+
stempel: "87d02e68",
|
|
111
|
+
befehl: "kimal3 project list",
|
|
112
|
+
tippen: "/k3list",
|
|
113
|
+
terminal: "kimal3 project list",
|
|
114
|
+
beschreibung: "Show the projects you've added",
|
|
115
|
+
rhythmusOderSatz: "show my projects",
|
|
116
|
+
details: [
|
|
117
|
+
"Shows what's already in your success profile — with dates and numbers.",
|
|
118
|
+
"What it's really for: Claude looks here BEFORE adding a project. Without that check, the same project would sooner or later appear twice on a public page that carries your name.",
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
"kimal3 firma daten": {
|
|
122
|
+
stempel: "3195364c",
|
|
123
|
+
befehl: "kimal3 company data",
|
|
124
|
+
tippen: "/k3analyse <your question>",
|
|
125
|
+
terminal: 'kimal3 company data --company "Nordwind Handel GmbH"',
|
|
126
|
+
beschreibung: "Fetch your company's data so Claude can analyse it",
|
|
127
|
+
rhythmusOderSatz: "analyse my company",
|
|
128
|
+
details: [
|
|
129
|
+
"Fetches the key figures, people and projects of your company — Claude does the analysis. Just ask: “Which three projects bring in the most measurable return?”",
|
|
130
|
+
"If you belong to several companies, it never quietly picks one; it lays them out for you as ready-made commands. If two have the SAME name, --company-id helps — also ready to copy, you don't have to rename anything.",
|
|
131
|
+
"⚠️ This is personal data about your colleagues. For use in a real company you need a commercial Claude account with a data processing agreement. If employees' performance is analysed, in Germany this requires the works council's agreement (co-determination).",
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
"kimal3 wache": {
|
|
135
|
+
stempel: "2daae4e2",
|
|
136
|
+
befehl: "kimal3 watch",
|
|
137
|
+
tippen: "! kimal3 watch",
|
|
138
|
+
terminal: "kimal3 watch",
|
|
139
|
+
beschreibung: "Check whether your access is valid and whether anything is pending",
|
|
140
|
+
rhythmusOderSatz: "automatically when Claude starts",
|
|
141
|
+
details: [
|
|
142
|
+
"The daily check runs by itself when Claude Code starts — you don't have to call it. Silent when there's nothing to do; an open task (access, version, skill) is reported in every session until it's done.",
|
|
143
|
+
"If it stays silent, everything is fine: no line means no problem. It only speaks up when your access has expired, a message is waiting, a new version is available or your skill files are out of date.",
|
|
144
|
+
"If it can't reach our server, it says nothing about access and messages — but still reports a new version if npm knows one. The two questions don't depend on each other.",
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
"kimal3 logout": {
|
|
148
|
+
stempel: "9dfc20d7",
|
|
149
|
+
befehl: "kimal3 logout",
|
|
150
|
+
tippen: "! kimal3 logout",
|
|
151
|
+
terminal: "kimal3 logout",
|
|
152
|
+
beschreibung: "Disconnect this computer",
|
|
153
|
+
rhythmusOderSatz: "only when needed",
|
|
154
|
+
details: [
|
|
155
|
+
"Disconnects this one computer — useful on someone else's or a shared device, or if a computer goes missing. Your other computers stay signed in.",
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Der Fingerabdruck der deutschen Felder eines Katalog-Eintrags: FNV-1a ueber 32 Bit, 8 Hex-Zeichen.
|
|
161
|
+
* Ein eigener kleiner Hash statt `node:crypto`, damit die Datei importfrei bleibt; er muss keinem
|
|
162
|
+
* Angreifer standhalten, nur eine Textaenderung bemerken.
|
|
163
|
+
*/
|
|
164
|
+
export function fingerabdruck(b) {
|
|
165
|
+
const text = JSON.stringify([b.beschreibung, b.wer === "du" ? b.rhythmus : b.ausloeser, b.tippen, b.terminal, b.details]);
|
|
166
|
+
let h = 0x811c9dc5;
|
|
167
|
+
for (let i = 0; i < text.length; i++) {
|
|
168
|
+
h ^= text.charCodeAt(i);
|
|
169
|
+
h = Math.imul(h, 0x01000193);
|
|
170
|
+
}
|
|
171
|
+
return (h >>> 0).toString(16).padStart(8, "0");
|
|
172
|
+
}
|
|
173
|
+
/** Was ein Katalog-Eintrag in einer Sprache anzeigt -- deutsch unveraendert aus dem Katalog. */
|
|
174
|
+
export function anzeigeIn(eintrag, sprache) {
|
|
175
|
+
if (sprache === "en")
|
|
176
|
+
return BEFEHLE_EN[eintrag.befehl];
|
|
177
|
+
return {
|
|
178
|
+
befehl: eintrag.befehl,
|
|
179
|
+
tippen: eintrag.tippen,
|
|
180
|
+
terminal: eintrag.terminal,
|
|
181
|
+
beschreibung: eintrag.beschreibung,
|
|
182
|
+
rhythmusOderSatz: eintrag.wer === "du" ? eintrag.rhythmus : eintrag.ausloeser,
|
|
183
|
+
details: eintrag.details,
|
|
184
|
+
};
|
|
185
|
+
}
|
package/dist/befehle-katalog.js
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
* NodeNext (Import-Pfade enden auf `.js`), die App mit dem Bundler. Eine Datei
|
|
12
12
|
* ohne eigene Importe liest sich aus beiden Welten ohne Uebersetzung.
|
|
13
13
|
*
|
|
14
|
+
* 🌐 Englisch steht in `befehle-katalog-en.ts` daneben (Teil 3, T3-11) -- eine Datei waere
|
|
15
|
+
* ueber 300 Code-Zeilen. Die Terminal-Hilfe baut `hilfe.ts` aus beiden.
|
|
16
|
+
*
|
|
14
17
|
* ⚠️ Der Katalog beschreibt, WAS ES GIBT — nicht, wer es darf. Die Pro-Schranke
|
|
15
18
|
* sitzt in der Route und im Befehl, nicht hier.
|
|
16
19
|
*/
|
|
@@ -62,7 +65,7 @@ export const BEFEHLE = [
|
|
|
62
65
|
terminal: "kimal3 arbeitsplatz neu",
|
|
63
66
|
details: [
|
|
64
67
|
"Holt die Vorlage von deinem Pro-Konto und legt sie hier als echten Ordner an — CLAUDE.md, Takt-Befehle, die Werkbank für deine Projekte. Dasselbe Paket, das auch als Download auf /pro liegt.",
|
|
65
|
-
"Der Ordner heißt
|
|
68
|
+
"Der Ordner heißt KI-Arbeitsplatz (bei einer englischsprachigen Firma AI-Workplace) — mehrere Firmen trennst du über den Ordner darüber, z. B. Kunden/ARNO/KI-Arbeitsplatz. Gib deinen Vornamen mit, dann heißt deine Werkbank darin werkbank-sabine (bei einem englischen Konto workbench-sabine): kimal3 arbeitsplatz neu sabine.",
|
|
66
69
|
"Gibt es den Zielordner schon und ist er nicht leer, bricht der Befehl ab, statt etwas zu überschreiben — deine Arbeit ist sicher. Geklappt hat es, wenn er die Zahl der angelegten Dateien nennt.",
|
|
67
70
|
"⚠️ Er legt auch die Firmenebene an (kontext/ mit Marke, Systemen, Sicherheit). Steht die schon, brauchst du kimal3 werkbank neu — sonst entsteht eine zweite Firma in der ersten.",
|
|
68
71
|
],
|
|
@@ -87,7 +90,7 @@ export const BEFEHLE = [
|
|
|
87
90
|
"Für alle außer der ersten Person: Der Firmen-Ordner steht schon (kontext/ mit Marke, Systemen, Sicherheit) — du brauchst nur deinen eigenen Arbeitsplatz darin.",
|
|
88
91
|
"🔴 Er fasst die Firmenebene nicht an. Kein Byte in kontext/, CLAUDE.md oder README.md — auch nicht schreibend „identisch drüber“.",
|
|
89
92
|
"Er läuft nur, wenn du wirklich in einem Firmen-Ordner stehst. Fehlt die Firmenebene daneben, bricht er ab und sagt es — eine Werkbank ohne sie zeigt ins Leere, weil ihre Einstellungen auf ../kontext verweisen.",
|
|
90
|
-
"Gib deinen Vornamen mit — der Ordner trägt ihn: aus sabine wird werkbank-sabine. Ohne Angabe bildet der Server ihn aus deiner Anmelde-Adresse. So sieht man später, wem welche Werkbank gehört.",
|
|
93
|
+
"Gib deinen Vornamen mit — der Ordner trägt ihn: aus sabine wird werkbank-sabine (bei einem englischen Konto workbench-sabine). Ohne Angabe bildet der Server ihn aus deiner Anmelde-Adresse. So sieht man später, wem welche Werkbank gehört.",
|
|
91
94
|
],
|
|
92
95
|
},
|
|
93
96
|
/*
|
|
@@ -137,7 +140,7 @@ export const BEFEHLE = [
|
|
|
137
140
|
"🔴 Nur der Firmen-Admin darf das. Bist du keiner, sagt er es dir — dann gib deine Ergänzung an den Admin weiter, ein zweiter Versuch ändert daran nichts.",
|
|
138
141
|
"⚠️ Klappt etwas nicht, zählt die MELDUNG, nicht die Zahl dahinter: Dieselbe 1 steht für „du bist kein Admin“, „hier steht kein Arbeitsplatz“, „jemand anderes hat inzwischen geändert“ (Ausweg --ueberschreiben) und mehreres mehr. Sie steht sogar unter einer Meldung, die mit „Die Firma hat deine Änderungen gespeichert“ beginnt und nur sagt, dass eine Datei auf deiner Platte nicht geschrieben werden konnte — DAS ist ein Erfolg: alles ist oben angekommen. Lies den Satz, nicht die Zahl.",
|
|
139
142
|
"Sieht eine der fünf Dateien nicht mehr aus wie ihre Frageliste — etwa weil etwas Fremdes darüberkopiert wurde —, bricht er ab und schickt gar nichts, auch die vier anderen nicht. kimal3 kontext runter holt die Datei zurück.",
|
|
140
|
-
"Geklappt hat es, wenn er „✓
|
|
143
|
+
"Geklappt hat es, wenn er „✓ geändert bei der Firma:“ mit den Dateinamen meldet.",
|
|
141
144
|
],
|
|
142
145
|
},
|
|
143
146
|
{
|
|
@@ -180,9 +183,11 @@ export const BEFEHLE = [
|
|
|
180
183
|
/*
|
|
181
184
|
🔴 Dieser Eintrag steht bewusst NICHT im "Weg, den ein Mensch geht" --
|
|
182
185
|
niemand muss ihn selbst tippen. Er wird bei jedem Start von Claude Code
|
|
183
|
-
von selbst aufgerufen (Aufgabe 8)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
+
von selbst aufgerufen (Aufgabe 8). Er steht hier noch, obwohl `tippen()`
|
|
187
|
+
in `wache-rechnung.ts` seit Teil 3 (Task 15) die Befehlswoerter aus
|
|
188
|
+
`befehlswoerter.ts` liest und den Katalog nicht mehr braucht. Die Zeile
|
|
189
|
+
bleibt sichtbar (Task 16): Die deutsche Hilfe bleibt Zeichen fuer Zeichen,
|
|
190
|
+
und ein Mensch, der `kimal3 wache` sucht, findet es hier.
|
|
186
191
|
*/
|
|
187
192
|
{
|
|
188
193
|
befehl: "kimal3 wache",
|
|
@@ -209,47 +214,3 @@ export const BEFEHLE = [
|
|
|
209
214
|
],
|
|
210
215
|
},
|
|
211
216
|
];
|
|
212
|
-
/**
|
|
213
|
-
* Die Terminal-Hilfe, gebaut aus dem Katalog.
|
|
214
|
-
*
|
|
215
|
-
* Die Spalten richten sich an der laengsten Befehlszeile aus — von Hand
|
|
216
|
-
* gesetzte Leerzeichen waeren beim naechsten laengeren Befehl krumm.
|
|
217
|
-
*
|
|
218
|
-
* 📌 Sie nimmt bewusst NUR `befehl` und `beschreibung`: Im Terminal ist eine
|
|
219
|
-
* Uebersicht gefragt, kein Handbuch. Die langen `details` haben ihren Platz auf
|
|
220
|
-
* `/pro`, wo man sie auf- und zuklappen kann — `--help` je Befehl bleibt der
|
|
221
|
-
* Weg im Terminal.
|
|
222
|
-
*/
|
|
223
|
-
export function hilfeText() {
|
|
224
|
-
const breite = Math.max(...BEFEHLE.map((b) => b.befehl.length));
|
|
225
|
-
const zeilen = BEFEHLE.map((b) => ` ${b.befehl.padEnd(breite + 2)}${b.beschreibung}`).join("\n");
|
|
226
|
-
return `
|
|
227
|
-
kimal3 — trag deine KI-Projekte dort ein, wo sie entstehen.
|
|
228
|
-
|
|
229
|
-
${zeilen}
|
|
230
|
-
|
|
231
|
-
Mehr zu einem Befehl: kimal3 projekt neu --help
|
|
232
|
-
`;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Wie ein Befehl **getippt** wird — aus dem Katalog geholt, nicht abgeschrieben.
|
|
236
|
-
*
|
|
237
|
-
* 🔑 **Warum das eine eigene Funktion ist** (2026-08-20): Auf `/pro` stand
|
|
238
|
-
* `const ANMELDEN = "! kimal3 login"` als Zeichenkette im Seitencode — eine
|
|
239
|
-
* zweite Wahrheit ueber einen Befehl, den der Katalog schon fuehrt. Wer im
|
|
240
|
-
* Katalog umbenennt, laesst sie stehen, und die Seite zeigt weiter den alten
|
|
241
|
-
* Aufruf. Dieselbe Klasse Fehler wie der fest getippte `cd`-Pfad in Runde 3.
|
|
242
|
-
*
|
|
243
|
-
* ⚠️ Sie **wirft**, statt einen leeren Text zu liefern. Die Aufrufer sind
|
|
244
|
-
* Modul-Konstanten — ein falscher Name fliegt damit beim `npm run build` auf,
|
|
245
|
-
* nicht erst beim Kunden vor einem Kopier-Kasten, in dem nichts steht.
|
|
246
|
-
* *Ein stiller Fehler auf einer bezahlten Seite ist teurer als ein lauter im
|
|
247
|
-
* Build.*
|
|
248
|
-
*/
|
|
249
|
-
export function tippBefehl(befehl) {
|
|
250
|
-
const eintrag = BEFEHLE.find((b) => b.befehl === befehl);
|
|
251
|
-
if (!eintrag) {
|
|
252
|
-
throw new Error(`Kein Katalog-Eintrag fuer „${befehl}". Steht der Befehl noch in BEFEHLE?`);
|
|
253
|
-
}
|
|
254
|
-
return eintrag.tippen;
|
|
255
|
-
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export const BEFEHLSWOERTER = {
|
|
2
|
+
login: { de: "login", en: "login" },
|
|
3
|
+
logout: { de: "logout", en: "logout" },
|
|
4
|
+
"skill install": { de: "skill install", en: "skill install" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
5
|
+
"arbeitsplatz neu": { de: "arbeitsplatz neu", en: "workplace new" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
6
|
+
"werkbank neu": { de: "werkbank neu", en: "workbench new" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
7
|
+
"kontext runter": { de: "kontext runter", en: "context download" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
8
|
+
"kontext hoch": { de: "kontext hoch", en: "context upload" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
9
|
+
"kontext fragen": { de: "kontext fragen", en: "context questions" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
10
|
+
"projekt neu": { de: "projekt neu", en: "project new" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
11
|
+
"projekt liste": { de: "projekt liste", en: "project list" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
12
|
+
"firma daten": { de: "firma daten", en: "company data" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
13
|
+
wache: { de: "wache", en: "watch" },
|
|
14
|
+
"wache an": { de: "wache an", en: "watch on" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
15
|
+
"wache aus": { de: "wache aus", en: "watch off" }, // kein-anzeigetext: Befehlswörter (Spec Abschnitt 6)
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Welcher Befehl steht vorne in `argv` -- und was bleibt dahinter?
|
|
19
|
+
* Zwei Woerter vor einem: `watch on` ist `wache an`, nicht `wache` mit Rest `on`.
|
|
20
|
+
* `null` heisst: kein Befehl, auch kein halber. Ob der Rest zum Befehl passt, entscheidet der
|
|
21
|
+
* Verteiler (`kimal3 login extra` bleibt dort unbekannt, wie bisher).
|
|
22
|
+
*/
|
|
23
|
+
export function erkenneBefehl(argv) {
|
|
24
|
+
const namen = Object.keys(BEFEHLSWOERTER);
|
|
25
|
+
for (const laenge of [2, 1]) {
|
|
26
|
+
if (argv.length < laenge)
|
|
27
|
+
continue;
|
|
28
|
+
const vorne = argv.slice(0, laenge).join(" ");
|
|
29
|
+
for (const name of namen) {
|
|
30
|
+
const w = BEFEHLSWOERTER[name];
|
|
31
|
+
if (w.de.split(" ").length !== laenge)
|
|
32
|
+
continue;
|
|
33
|
+
if (vorne === w.de || vorne === w.en)
|
|
34
|
+
return { name, rest: argv.slice(laenge) };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/** Das Befehlswort in der Sprache des Satzes, der es nennt -- ohne `kimal3` davor. */
|
|
40
|
+
export function befehlIn(name, sprache) {
|
|
41
|
+
return BEFEHLSWOERTER[name][sprache];
|
|
42
|
+
}
|
|
43
|
+
/** Englischer Schalter -> deutscher Name, unter dem der Wert abgelegt und zum Server geschickt wird. */
|
|
44
|
+
export const SCHALTER_EN = {
|
|
45
|
+
company: "firma",
|
|
46
|
+
"company-id": "firma-id",
|
|
47
|
+
"no-company": "ohne-firma",
|
|
48
|
+
overwrite: "ueberschreiben",
|
|
49
|
+
title: "titel",
|
|
50
|
+
description: "beschreibung",
|
|
51
|
+
icon: "symbol",
|
|
52
|
+
hours: "stunden",
|
|
53
|
+
result: "ergebnis",
|
|
54
|
+
revenue: "umsatz",
|
|
55
|
+
impact: "wirkung",
|
|
56
|
+
"impact-label": "wirkung-label",
|
|
57
|
+
"live-since": "live-seit",
|
|
58
|
+
};
|
|
59
|
+
/** `company` -> `firma`; ein deutscher (oder unbekannter) Name bleibt, wie er ist. */
|
|
60
|
+
export function deutscherSchalter(getippt) {
|
|
61
|
+
return Object.hasOwn(SCHALTER_EN, getippt) ? SCHALTER_EN[getippt] : getippt;
|
|
62
|
+
}
|
|
63
|
+
/** Der Schalter in der Sprache des Satzes, der ihn nennt (ohne `--`). */
|
|
64
|
+
export function schalterIn(deutsch, sprache) {
|
|
65
|
+
if (sprache === "de")
|
|
66
|
+
return deutsch;
|
|
67
|
+
const treffer = Object.entries(SCHALTER_EN).find(([, d]) => d === deutsch);
|
|
68
|
+
return treffer ? treffer[0] : deutsch;
|
|
69
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* Woran wir einen Eintrag als UNSEREN erkennen -- unabhaengig davon, welche
|
|
14
14
|
* Argumente wir spaeter einmal anhaengen. Siehe `istUnserer`.
|
|
15
15
|
*/
|
|
16
|
-
export const WACHE_MARKE = "kimal3 wache";
|
|
16
|
+
export const WACHE_MARKE = "kimal3 wache"; // kein-anzeigetext: Startbefehl in Claudes Einstellungen, bleibt deutsch (T3-5)
|
|
17
17
|
/**
|
|
18
18
|
* Der Befehl, der in die Einstellungen eingetragen wird.
|
|
19
19
|
*
|
|
@@ -37,7 +37,7 @@ export const WACHE_MARKE = "kimal3 wache";
|
|
|
37
37
|
* der JSON-Form, die Claude Code fuer Startbefehle vorsieht, und die wird
|
|
38
38
|
* AUCH BEI RUECKGABEWERT 127 gelesen (ebenfalls gemessen).
|
|
39
39
|
*/
|
|
40
|
-
export const WACHE_BEFEHL = `${WACHE_MARKE} --hook`;
|
|
40
|
+
export const WACHE_BEFEHL = `${WACHE_MARKE} --hook`; // kein-anzeigetext: Startbefehl in Claudes Einstellungen, bleibt deutsch (T3-5)
|
|
41
41
|
/**
|
|
42
42
|
* Wie lange Claude auf die Wache wartet, in Sekunden.
|
|
43
43
|
*
|
|
@@ -2,6 +2,9 @@ import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { WACHE_BEFEHL, mischeEinstellungen } from "./einstellungen-mischen.js";
|
|
5
|
+
/** Die Kontrolle nach dem Schreiben fand unseren Eintrag nicht -- eigener Fall, damit `detail` `null` sein kann. */
|
|
6
|
+
class EintragFehlt extends Error {
|
|
7
|
+
}
|
|
5
8
|
export function einstellungenDatei() {
|
|
6
9
|
return join(homedir(), ".claude", "settings.json");
|
|
7
10
|
}
|
|
@@ -24,7 +27,7 @@ export function trageWacheEin() {
|
|
|
24
27
|
-- wer beide gleich behandelt, legt eine neue an und der Mensch
|
|
25
28
|
verliert alles, was drinstand.
|
|
26
29
|
*/
|
|
27
|
-
return { art: "gescheitert",
|
|
30
|
+
return { art: "gescheitert", schritt: "lesen", detail: e.message };
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
const ergebnis = mischeEinstellungen(alt, WACHE_BEFEHL);
|
|
@@ -43,7 +46,7 @@ export function trageWacheEin() {
|
|
|
43
46
|
ist, im Fehlerfall zurueckzukoennen -- ohne Kopie gibt es kein Zurueck,
|
|
44
47
|
und dann ist Schreiben die schlechtere Wahl als Nichtstun.
|
|
45
48
|
*/
|
|
46
|
-
return { art: "gescheitert",
|
|
49
|
+
return { art: "gescheitert", schritt: "sichern", detail: e.message };
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
// --- Schritt 3: schreiben ---
|
|
@@ -53,19 +56,19 @@ export function trageWacheEin() {
|
|
|
53
56
|
}
|
|
54
57
|
catch (e) {
|
|
55
58
|
zurueck(gabEsSchon);
|
|
56
|
-
return { art: "gescheitert",
|
|
59
|
+
return { art: "gescheitert", schritt: "schreiben", detail: e.message };
|
|
57
60
|
}
|
|
58
61
|
// --- Schritt 4: zuruecklesen und erneut pruefen ---
|
|
59
62
|
try {
|
|
60
63
|
const zurueckgelesen = readFileSync(datei, "utf8");
|
|
61
64
|
const geparst = JSON.parse(zurueckgelesen);
|
|
62
65
|
if (!zurueckgelesen.includes(WACHE_BEFEHL) || geparst === null) {
|
|
63
|
-
throw new
|
|
66
|
+
throw new EintragFehlt();
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
catch (e) {
|
|
67
70
|
zurueck(gabEsSchon);
|
|
68
|
-
return { art: "gescheitert",
|
|
71
|
+
return { art: "gescheitert", schritt: "kontrolle", detail: e instanceof EintragFehlt ? null : e.message };
|
|
69
72
|
}
|
|
70
73
|
return { art: "eingetragen" };
|
|
71
74
|
}
|
package/dist/fehler.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* zieht ueber `anmeldung.ts` das Dateisystem nach; wer von dort importiert,
|
|
9
9
|
* kann die Rechnung nicht mehr allein pruefen.
|
|
10
10
|
*/
|
|
11
|
+
import { ALLGEMEIN_TEXTE } from "./texte/allgemein.js";
|
|
11
12
|
/**
|
|
12
13
|
* ⚠️ **404 ist KEIN Eingabefehler** (QA-Befund B-7, 2026-08-18).
|
|
13
14
|
*
|
|
@@ -33,11 +34,11 @@
|
|
|
33
34
|
* bereits "nochmal versuchen kann helfen" -- und ein paar Minuten spaeter ist
|
|
34
35
|
* das Deployment durch.
|
|
35
36
|
*/
|
|
36
|
-
export function schlussFehler(status, meldung) {
|
|
37
|
+
export function schlussFehler(status, meldung, sprache) {
|
|
38
|
+
const t = ALLGEMEIN_TEXTE[sprache];
|
|
37
39
|
if (status === 404) {
|
|
38
40
|
return {
|
|
39
|
-
text:
|
|
40
|
-
"Hast du gerade aktualisiert, versuch es in ein paar Minuten noch einmal.",
|
|
41
|
+
text: t.appDoesNotKnowCommand,
|
|
41
42
|
wert: 3,
|
|
42
43
|
};
|
|
43
44
|
}
|
|
@@ -57,8 +58,7 @@ export function schlussFehler(status, meldung) {
|
|
|
57
58
|
*/
|
|
58
59
|
if (status === 408 || status === 429) {
|
|
59
60
|
return {
|
|
60
|
-
text:
|
|
61
|
-
"Versuch es in einem Moment noch einmal.",
|
|
61
|
+
text: t.serverOverloaded,
|
|
62
62
|
wert: 3,
|
|
63
63
|
};
|
|
64
64
|
}
|
package/dist/firmen-liste.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* reine Rechnung, der Import bricht das also nicht.
|
|
7
7
|
*/
|
|
8
8
|
import { alsWort } from "./argumente.js";
|
|
9
|
+
import { befehlIn, schalterIn } from "./befehlswoerter.js";
|
|
10
|
+
import { ALLGEMEIN_TEXTE } from "./texte/allgemein.js";
|
|
9
11
|
/**
|
|
10
12
|
* Aus den Namen der eigenen Firmen die Zeilen bauen, die unter „Deine Firmen:"
|
|
11
13
|
* stehen.
|
|
@@ -31,7 +33,8 @@ import { alsWort } from "./argumente.js";
|
|
|
31
33
|
* Diese Funktion sorgt nur dafuer, dass niemand mehr einen Ausweg vorgespielt
|
|
32
34
|
* bekommt, den es nicht gibt.
|
|
33
35
|
*/
|
|
34
|
-
export function firmenZeilen(namen) {
|
|
36
|
+
export function firmenZeilen(namen, s) {
|
|
37
|
+
const t = ALLGEMEIN_TEXTE[s];
|
|
35
38
|
const anzahl = (name) => namen.filter((n) => n === name).length;
|
|
36
39
|
const gesehen = new Set();
|
|
37
40
|
const zeilen = [];
|
|
@@ -44,10 +47,10 @@ export function firmenZeilen(namen) {
|
|
|
44
47
|
// Fertiger Befehl statt blosser Liste: Der naechste Schritt ist dann
|
|
45
48
|
// Kopieren statt Abtippen -- und ein Name mit Leerzeichen braucht
|
|
46
49
|
// Anfuehrungszeichen, an die sonst niemand denkt.
|
|
47
|
-
zeilen.push(
|
|
50
|
+
zeilen.push(t.companyLine(befehlIn("firma daten", s), schalterIn("firma", s), alsWort(name, true))); // kein-anzeigetext: Befehlsschluessel
|
|
48
51
|
}
|
|
49
52
|
else {
|
|
50
|
-
zeilen.push(
|
|
53
|
+
zeilen.push(t.nameNotUnique(name, wieOft));
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
return zeilen;
|
|
@@ -67,8 +70,8 @@ export function firmenZeilen(namen) {
|
|
|
67
70
|
* kopierfertige Befehle. Der Name steht als Kommentar dahinter -- eine nackte
|
|
68
71
|
* UUID sagt einem Menschen nichts, und zwei davon untereinander noch weniger.
|
|
69
72
|
*/
|
|
70
|
-
export function firmenIdZeilen(auswahl) {
|
|
71
|
-
return auswahl.map((f, i) =>
|
|
73
|
+
export function firmenIdZeilen(auswahl, s) {
|
|
74
|
+
return auswahl.map((f, i) => ALLGEMEIN_TEXTE[s].companyIdLine(befehlIn("firma daten", s), schalterIn("firma-id", s), f.id, f.name, i + 1));
|
|
72
75
|
}
|
|
73
76
|
/**
|
|
74
77
|
* Die Namen der eigenen Firmen aus einer `409`-Antwort -- was nicht als Text
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const REGION = { de: "de-DE", en: "en-GB" };
|
|
2
|
+
const MONATE_DE = [
|
|
3
|
+
"Januar", "Februar", "März", "April", "Mai", "Juni", // kein-anzeigetext: deutsche Monatsnamen als Handliste (T3-13, ICU-unabhaengig); Englisch kommt aus Intl
|
|
4
|
+
"Juli", "August", "September", "Oktober", "November", "Dezember", // kein-anzeigetext: siehe Zeile 13
|
|
5
|
+
];
|
|
6
|
+
/**
|
|
7
|
+
* "2026-07-01" -> "1. Juli 2026" / "1 July 2026". Aus der Zeichenkette, nie ueber die Ortszeit
|
|
8
|
+
* (ein ISO-Datum ohne Uhrzeit gilt als UTC-Mitternacht und kippt sonst einen Tag zurueck).
|
|
9
|
+
* ⚠️ Erwartet ein REINES Datum (`JJJJ-MM-TT`); passt es nicht, steht lieber das rohe Datum da
|
|
10
|
+
* als ein kaputter Satz ("NaN. August 2026", der Fehler vom 2026-08-12).
|
|
11
|
+
*/
|
|
12
|
+
export function datumLang(isoDatum, s) {
|
|
13
|
+
const [jahr, monat, tag] = isoDatum.split("-").map(Number);
|
|
14
|
+
// 🔑 Deutsch aus der Handliste (T3-13): Die deutsche Ausgabe haengt nicht an der ICU-Fassung des Rechners.
|
|
15
|
+
if (s === "de") {
|
|
16
|
+
const name = MONATE_DE[monat - 1];
|
|
17
|
+
return !name || !jahr || !Number.isFinite(tag) ? isoDatum : `${tag}. ${name} ${jahr}`;
|
|
18
|
+
}
|
|
19
|
+
if (!jahr || !(monat >= 1 && monat <= 12) || !tag)
|
|
20
|
+
return isoDatum;
|
|
21
|
+
return new Intl.DateTimeFormat(REGION[s], { day: "numeric", month: "long", year: "numeric", timeZone: "UTC" })
|
|
22
|
+
.format(new Date(Date.UTC(jahr, monat - 1, tag, 12)));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* "1200" -> "1.200 €" / "€1,200"; "0.1" -> "0,10 €" / "€0.10". Cent nur, wenn welche dastehen:
|
|
26
|
+
* "1.200,00 €" taeuscht eine Genauigkeit vor, "0 €" bei 0,10 € verschweigt eine, die dasteht.
|
|
27
|
+
* Euro bleibt Euro (Teil 1).
|
|
28
|
+
*/
|
|
29
|
+
export function euro(wert, s) {
|
|
30
|
+
const stellen = Math.round(wert * 100) % 100 !== 0 ? 2 : 0;
|
|
31
|
+
if (s === "de") {
|
|
32
|
+
return `${new Intl.NumberFormat("de-DE", { minimumFractionDigits: stellen, maximumFractionDigits: stellen }).format(wert)} €`;
|
|
33
|
+
}
|
|
34
|
+
return new Intl.NumberFormat("en-GB", {
|
|
35
|
+
style: "currency", currency: "EUR", minimumFractionDigits: stellen, maximumFractionDigits: stellen,
|
|
36
|
+
}).format(wert);
|
|
37
|
+
}
|
|
38
|
+
/** "6" -> "6", "6.5" -> "6,5" / "6.5". Die Spalte ist numeric(6,2). */
|
|
39
|
+
export function stunden(wert, s) {
|
|
40
|
+
return new Intl.NumberFormat(REGION[s], { maximumFractionDigits: 2 }).format(wert);
|
|
41
|
+
}
|
package/dist/fragen-lesen.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
🔴 WARUM DAS NICHT NUR BEQUEM, SONDERN DAS EINZIG EHRLICHE IST: Die CLI kann
|
|
13
13
|
nichts aus `src/` importieren (eigenes Paket, eigenes tsconfig -- s. Kopf von
|
|
14
14
|
`kontext-stand.ts`). Ein Katalog in `cli/src/` waere eine ZWEITE Fassung der
|
|
15
|
-
|
|
15
|
+
Fragen, und sie friert in dem Moment ein, in dem `npm publish` laeuft: Der
|
|
16
16
|
Kunde hat dann eine CLI von gestern und Dateien von heute. Die Datei auf
|
|
17
17
|
seiner Platte kommt dagegen IMMER vom Server -- sie ist die einzige Quelle,
|
|
18
18
|
die nicht gegenueber dem abweichen kann, was er wirklich vor sich hat.
|
|
@@ -158,14 +158,14 @@ export function fragenAus(text) {
|
|
|
158
158
|
*
|
|
159
159
|
* 🔑 **WORAN ERKANNT WIRD: an mindestens einem Anker, der zu DIESER Datei
|
|
160
160
|
* gehoert.** Die Anker sind je Datei benannt (`marke_anrede`, `firma_angebot`,
|
|
161
|
-
* `kurz_kunden` …), und `
|
|
161
|
+
* `kurz_kunden` …), und `firmenTexte` (`kontext-stand.ts`) fuehrt je Datei
|
|
162
162
|
* ihren Praefix. Damit faellt nicht nur die voellig fremde Datei durch, sondern
|
|
163
163
|
* auch der haeufigere Unfall: `marke.md` ueber `firma.md` kopiert. Ein blosses
|
|
164
164
|
* "irgendein Anker steht drin" haette genau den durchgewunken.
|
|
165
165
|
*
|
|
166
166
|
* ⚠️ **Dass die Praefixe wirklich passen, ist keine Verabredung, sondern eine
|
|
167
167
|
* Messung:** `check:kontext` haelt jeden Anker aus `FRAGEN` (der App) gegen den
|
|
168
|
-
* Praefix, den `
|
|
168
|
+
* Praefix, den `firmenTexte` fuer seine Datei nennt.
|
|
169
169
|
*
|
|
170
170
|
* 📌 **Der Preis, ausgesprochen:** Wer ALLE Anker einer Datei loescht und nur
|
|
171
171
|
* die Ueberschriften stehen laesst, bekommt hier ein Nein, obwohl die App den
|
package/dist/hilfe.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BEFEHLE } from "./befehle-katalog.js";
|
|
2
|
+
import { anzeigeIn } from "./befehle-katalog-en.js";
|
|
3
|
+
import { ALLGEMEIN_TEXTE } from "./texte/allgemein.js";
|
|
4
|
+
/**
|
|
5
|
+
* Die Terminal-Hilfe, gebaut aus dem Katalog (umgezogen aus `befehle-katalog.ts`, Teil 3,
|
|
6
|
+
* T3-11: Sie braucht jetzt beide Katalog-Dateien, und der Katalog bleibt importfrei).
|
|
7
|
+
*
|
|
8
|
+
* Die Spalten richten sich an der laengsten Befehlszeile aus -- von Hand gesetzte Leerzeichen
|
|
9
|
+
* waeren beim naechsten laengeren Befehl krumm.
|
|
10
|
+
*
|
|
11
|
+
* 📌 Sie nimmt bewusst NUR `befehl` und `beschreibung`: Im Terminal ist eine Uebersicht gefragt,
|
|
12
|
+
* kein Handbuch. Die langen `details` haben ihren Platz auf `/pro`.
|
|
13
|
+
*
|
|
14
|
+
* 🔴 Deutsch Zeichen fuer Zeichen wie vorher; Englisch mit EINER Zeile mehr (T3-13): die deutschen
|
|
15
|
+
* Befehlswoerter laufen ebenfalls. Der Rahmen (Leerzeichen, Zeilenumbrueche) steht IN den
|
|
16
|
+
* Textschluesseln, nicht hier (TU-2).
|
|
17
|
+
*/
|
|
18
|
+
export function hilfeText(s) {
|
|
19
|
+
const t = ALLGEMEIN_TEXTE[s];
|
|
20
|
+
const eintraege = BEFEHLE.map((b) => anzeigeIn(b, s));
|
|
21
|
+
const breite = Math.max(...eintraege.map((e) => e.befehl.length));
|
|
22
|
+
const zeilen = eintraege.map((e) => ` ${e.befehl.padEnd(breite + 2)}${e.beschreibung}`).join("\n");
|
|
23
|
+
return `${t.helpTagline}${zeilen}${t.helpGermanWordsToo}${t.helpMore}`;
|
|
24
|
+
}
|