kimal3 0.1.2 → 0.1.3

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.
@@ -1,9 +1,9 @@
1
1
  import { zerlege } from "../argumente.js";
2
2
  import { feld, ruf } from "../api.js";
3
3
  import { schlussFehler } from "../fehler.js";
4
- import { firmenZeilen } from "../firmen-liste.js";
4
+ import { firmenIdZeilen, firmenZeilen } from "../firmen-liste.js";
5
5
  import { BASIS_URL } from "../anmeldung.js";
6
- const ERLAUBT = ["firma"];
6
+ const ERLAUBT = ["firma", "firma-id"];
7
7
  /**
8
8
  * Die Firmendaten holen — als JSON, unveraendert.
9
9
  *
@@ -17,14 +17,18 @@ const ERLAUBT = ["firma"];
17
17
  * Ueberschrift dazudruckt, macht die Ausgabe als JSON unlesbar — alles fuer
18
18
  * Menschen gehoert nach stderr (`console.error`).
19
19
  */
20
- const HILFE = `
21
- kimal3 firma daten [--firma "Name"]
22
-
23
- Holt die Daten deiner Firma als JSON: Kennzahlen, Menschen, Projekte.
24
- Die Auswertung macht Claude daraus selbst.
25
-
26
- --firma "Name" Noetig, wenn du zu mehreren Firmen gehoerst.
27
- Die Absage nennt dir die Namen als fertige Befehle.
20
+ const HILFE = `
21
+ kimal3 firma daten [--firma "Name" | --firma-id "…"]
22
+
23
+ Holt die Daten deiner Firma als JSON: Kennzahlen, Menschen, Projekte.
24
+ Die Auswertung macht Claude daraus selbst.
25
+
26
+ --firma "Name" Noetig, wenn du zu mehreren Firmen gehoerst.
27
+ Die Absage nennt dir die Namen als fertige Befehle.
28
+
29
+ --firma-id "…" Fuer den Fall, dass zwei deiner Firmen GLEICH heissen.
30
+ Auch diese Absage nennt dir fertige Befehle -- du musst
31
+ nichts umbenennen und nichts nachschlagen.
28
32
  `;
29
33
  export async function firmaDaten(argv) {
30
34
  // ⚠️ VOR `zerlege`, genau wie bei `projekt neu`: Ein Schalter ist keine
@@ -46,9 +50,22 @@ export async function firmaDaten(argv) {
46
50
  // das ab. Wer hier auf Wahrheit prueft, wirft beides zusammen: `--firma=`
47
51
  // lieferte dann die Daten der einzigen Firma, als haette niemand gefragt.
48
52
  const wunsch = zerlegt.werte.optionen.firma;
49
- const pfad = wunsch !== undefined
50
- ? `/api/cli/firma?firma=${encodeURIComponent(wunsch)}`
51
- : "/api/cli/firma";
53
+ /*
54
+ 🔑 **`--firma-id` ist der Ausweg fuer doppelt benannte Firmen** (B-5,
55
+ zweite Haelfte, 2026-08-18 spaet). Vorher endete die Absage bei „benenne
56
+ eine davon um" -- und das setzt Admin-Rechte in einer FREMDEN Firma
57
+ voraus. *Eine Absage ohne Ausweg ist eine Sackgasse mit Begruendung.*
58
+
59
+ ⚠️ Beides zusammen weist der Server ab, nicht diese Zeile: Die Regel
60
+ gehoert an die Grenze, nicht in die Optik. Hier wird nur weitergereicht.
61
+ */
62
+ const wunschId = zerlegt.werte.optionen["firma-id"];
63
+ const suche = new URLSearchParams();
64
+ if (wunsch !== undefined)
65
+ suche.set("firma", wunsch);
66
+ if (wunschId !== undefined)
67
+ suche.set("firma-id", wunschId);
68
+ const pfad = suche.toString() ? `/api/cli/firma?${suche.toString()}` : "/api/cli/firma";
52
69
  const antwort = await ruf(pfad, { methode: "GET", mitAusweis: true });
53
70
  if (antwort.status === 200) {
54
71
  // 🔴 Ein `200` mit unlesbarem Rumpf ist KEIN Erfolg (Review-Befund Runde 1):
@@ -83,17 +100,34 @@ export async function firmaDaten(argv) {
83
100
  ? koerper.firmen.filter((x) => typeof x === "string")
84
101
  : [];
85
102
  console.error(meldung);
86
- // Die Namen als FERTIGE Befehle ausgeben, nicht als blosse Liste: Der
87
- // naechste Schritt ist dann Kopieren statt Abtippen -- und ein Firmenname
88
- // mit Leerzeichen braucht Anfuehrungszeichen, an die sonst niemand denkt.
89
- //
90
- // ⚠️ Welche Namen einen Befehl bekommen, entscheidet `firmenZeilen` (B-5):
91
- // Ein doppelt vergebener Name bekommt KEINEN -- er waere ein Vorschlag,
92
- // der garantiert wieder in derselben Absage endet.
93
- const zeilen = firmenZeilen(namen);
94
- if (zeilen.length > 0) {
95
- console.error("\n Deine Firmen:");
96
- zeilen.forEach((z) => console.error(z));
103
+ /*
104
+ 🔑 **Bei gleichnamigen Firmen fuehrt der Weg ueber die ID** (B-5, zweite
105
+ Haelfte). Die Route legt dafuer `auswahl` bei -- und erst damit ist die
106
+ Absage keine Sackgasse mehr.
107
+ */
108
+ const auswahl = Array.isArray(koerper.auswahl)
109
+ ? koerper.auswahl.filter((x) => !!x &&
110
+ typeof x === "object" &&
111
+ typeof x.id === "string" &&
112
+ typeof x.name === "string")
113
+ : [];
114
+ if (auswahl.length > 0) {
115
+ console.error("\n Diese beiden heissen gleich — nimm die ID:");
116
+ firmenIdZeilen(auswahl).forEach((z) => console.error(z));
117
+ }
118
+ else {
119
+ // Die Namen als FERTIGE Befehle ausgeben, nicht als blosse Liste: Der
120
+ // naechste Schritt ist dann Kopieren statt Abtippen -- und ein Firmenname
121
+ // mit Leerzeichen braucht Anfuehrungszeichen, an die sonst niemand denkt.
122
+ //
123
+ // ⚠️ Welche Namen einen Befehl bekommen, entscheidet `firmenZeilen` (B-5):
124
+ // Ein doppelt vergebener Name bekommt KEINEN -- er waere ein Vorschlag,
125
+ // der garantiert wieder in derselben Absage endet.
126
+ const zeilen = firmenZeilen(namen);
127
+ if (zeilen.length > 0) {
128
+ console.error("\n Deine Firmen:");
129
+ zeilen.forEach((z) => console.error(z));
130
+ }
97
131
  }
98
132
  if (grund === "keine-firma") {
99
133
  console.error(`\n Eine Firma anlegen: ${BASIS_URL}/firma/neu`);
@@ -50,3 +50,21 @@ export function firmenZeilen(namen) {
50
50
  }
51
51
  return zeilen;
52
52
  }
53
+ /**
54
+ * Die Zeilen für den Fall, dass zwei Firmen **gleich heissen**.
55
+ *
56
+ * 🔑 **Das ist die zweite Haelfte von B-5** (2026-08-18 spaet). Die erste
57
+ * Haelfte nahm dem doppelten Namen seinen Befehl, damit niemand einen Ausweg
58
+ * vorgespielt bekommt, den es nicht gibt. Damit war die Irrefuehrung weg --
59
+ * aber an die Daten kam man immer noch nicht. Die Absage sagte „benenne eine
60
+ * davon um", und das setzt **Admin-Rechte in einer fremden Firma** voraus.
61
+ *
62
+ * *Eine Absage ohne Ausweg ist eine Sackgasse mit Begruendung.*
63
+ *
64
+ * Jetzt liefert die Route die IDs mit, und hier entstehen daraus wieder
65
+ * kopierfertige Befehle. Der Name steht als Kommentar dahinter -- eine nackte
66
+ * UUID sagt einem Menschen nichts, und zwei davon untereinander noch weniger.
67
+ */
68
+ export function firmenIdZeilen(auswahl) {
69
+ return auswahl.map((f, i) => ` kimal3 firma daten --firma-id "${f.id}" # ${f.name} (${i + 1}.)`);
70
+ }
package/dist/kimal3.js CHANGED
@@ -71,10 +71,28 @@ function versionsZeilen() {
71
71
  }
72
72
  return ` kimal3 ${version}\n spricht mit ${BASIS_URL}`;
73
73
  }
74
+ /**
75
+ * Was diese Zeile sagen KANN — und was nicht.
76
+ *
77
+ * 🔴 **Sie liest nur die Datei, sie fragt den Server nicht** (Befund L-9,
78
+ * 2026-08-18). Hier stand vorher „● Angemeldet als …" — und genau das hat am
79
+ * selben Abend zehn Minuten Fehlersuche gekostet: Der Ausweis war
80
+ * serverseitig nicht mehr gueltig, die Zeile behauptete trotzdem munter
81
+ * „Angemeldet", und die Suche begann an der falschen Stelle.
82
+ *
83
+ * *Eine Behauptung ist keine Messung.* Der Zustand, den die Datei kennt,
84
+ * heisst „hier liegt ein Ausweis" — ob der Server ihn noch annimmt, weiss
85
+ * allein der Server.
86
+ *
87
+ * ⚠️ Bewusst wird trotzdem NICHT nachgefragt: `--version` soll ohne Netz
88
+ * antworten und darf keine Sekunde haengen. Der ehrliche Weg ist deshalb
89
+ * nicht mehr Auskunft, sondern **weniger Behauptung**.
90
+ */
74
91
  function zustandsZeile() {
75
92
  const a = leseAnmeldung();
76
93
  return a
77
- ? ` ● Angemeldet als ${a.email}`
94
+ ? ` ● Ausweis hinterlegt für ${a.email}\n` +
95
+ " (ob er noch gilt, zeigt erst der nächste Befehl)"
78
96
  : " ● Nicht angemeldet. → kimal3 login";
79
97
  }
80
98
  async function haupt() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kimal3",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Trag deine KI-Projekte dort ein, wo sie entstehen: im Terminal.",
5
5
  "type": "module",
6
6
  "bin": {