HEUTE ZWEIMAL NUR GUTGEGANGEN. Zwei Claude-Sitzungen arbeiteten
gleichzeitig in diesem Verzeichnis, ohne voneinander zu wissen.
Keine hat etwas falsch gemacht — sie konnten es nicht wissen.
* Beide haben `git add -A` benutzt. Haette die eine
unfestgeschriebene Arbeit der anderen im Baum gehabt, waere sie
mitcommittet worden — unter fremdem Namen, in einer fremden
Begruendung, und niemandem waere es aufgefallen. Nachgesehen:
diesmal war nichts dabei.
* Beide haben den Stempellauf gestartet. Der schreibt 45 Dateien
um. Wer dort eine offen hatte, bekam sie unter den Haenden weg
geaendert.
Dasselbe hat in RunOne am 03.09.2026 sieben Minuten Ausfall
gekostet. Dort gibt es seitdem `arbeitsschloss.sh`; diese Fassung
uebernimmt seine Lehren.
WAS ES IST UND WAS NICHT. Es ist kein Riegel — wer wirklich muss,
kommt vorbei. Es beantwortet die eine Frage, die heute niemand
beantworten konnte: „arbeitet hier gerade sonst jemand?"
Die teuren Fehler liegen bei einem Schloss alle in derselben
Richtung: Es blockiert zu viel und wird deshalb abgeschafft. Also:
* Es blockiert NICHT, wenn das Schloss DEINES ist. RunOnes erste
Fassung fragte „ist abgeschlossen" statt „haelt es jemand
anders" — damit haette, wer ordentlich abschliesst, nie mehr
ausliefern koennen. Dafuer gibt es `fremd`.
* Es VERFAELLT nach zwei Stunden, und dass da jemand war, steht
beim Uebernehmen dabei.
* Es blockiert NICHT, wenn es selbst unlesbar ist — dritter
Ausgang, kein Stillstand.
* Notausgang: SCHLOSS_ZWANG=ja git commit …
DAS PROBLEM, AN DEM RUNONE HAENGT, IST HIER GELOEST. Dort faellt die
Kennung im Zweifel auf den Systembenutzer zurueck, und zwei
Claudian-Sitzungen laufen BEIDE als `claudian` — die Sicherung griff
ausgerechnet zwischen den zwei Faellen nicht, fuer die sie gebaut
wurde. Deshalb ist dort `export ARBEITER=…` Pflicht, und Pflicht
heisst: man vergisst es.
Hier steht `CLAUDE_CODE_SESSION_ID` in jeder Sitzung und ist je
Sitzung verschieden (nachgesehen, 36 Zeichen UUID). Zwei Sitzungen
auf demselben Windows-Benutzer unterscheiden sich damit von selbst,
ohne dass jemand etwas tun muss. Reihenfolge: ARBEITER, dann
Sitzungskennung, dann Benutzername MIT Warnung.
NIEMAND MUSS DARAN DENKEN:
* die beiden Stempelwerkzeuge nehmen es selbst und geben es selbst
frei — auch nach einem Absturz und bei Strg+C (wie `bauen.sh` im
Shop; eines, an das man denken muss, wird vergessen und ab da
umgangen)
* `tools/git-haken/pre-commit` bricht jeden Commit ab, solange
jemand ANDERS das Schloss haelt. Das ist die Stelle, die heute
gefehlt hat: `git add -A` ist der Griff, den man ohne Nachdenken
macht, und gegen einen Reflex hilft keine Regel auf Papier.
* `core.hooksPath` statt `.git/hooks` — letzteres ist nicht
versioniert und waere nach einem Klon genau dann leer, wenn es
gebraucht wird.
GEPRUEFT, server/pruef-arbeitsschloss.mjs: 33 Pruefungen, 0 Fehler —
in einem WEGWERF-Verzeichnis mit eigenem git, damit kein echtes
Schloss angefasst wird. Darunter am echten git:
ohne Schloss committen -> geht (0)
mit dem EIGENEN Schloss -> geht (0)
mit einem FREMDEN Schloss -> bricht ab (1), nennt wer und warum
und es stehen genau ZWEI Commits da, nicht drei
SCHLOSS_ZWANG=ja -> kommt vorbei
ohne das Schloss-Werkzeug -> laesst durch
Dazu: verfallenes Schloss laesst durch, mit laengerer Frist blockt
dasselbe Schloss wieder (Gegenprobe), unlesbarer Inhalt und
unlesbarer Zeitstempel blockieren nicht.
Portnummern nach der neuen Pruefdatei nachgemessen: Pruefbereich bis
5415, 462 Nummern, 0 Kollisionen. pruef-struktur 75/0,
pruef-fingermass 5/0, pruef-ports 10/0.
In DEPLOY.md steht es jetzt an erster Stelle — eine Sicherung, von
der nur der weiss, der sie gebaut hat, ist die erste, die umgangen
wird.
Co-Authored-By: Claude Opus 5 <[email protected]>
372 lines
16 KiB
JavaScript
372 lines
16 KiB
JavaScript
/* =====================================================================
|
|
arbeitsschloss.mjs — macht sichtbar, wer gerade in diesem
|
|
Verzeichnis arbeitet.
|
|
|
|
WARUM ES DAS GIBT (01.10.2026, nach zwei knappen Fällen an einem Tag)
|
|
|
|
An diesem Tag arbeiteten zwei Claude-Sitzungen gleichzeitig in
|
|
DogiHompage, ohne voneinander zu wissen. Keine hat etwas falsch
|
|
gemacht — sie konnten es nicht wissen. Zweimal ist es nur gut
|
|
gegangen:
|
|
|
|
* Beide haben `git add -A` benutzt. Hätte die eine
|
|
unfestgeschriebene Arbeit der anderen im Baum gehabt, wäre sie
|
|
mitcommittet worden. Nachgesehen: diesmal war nichts dabei.
|
|
* Beide haben `tools/workspace-stempel.mjs` laufen lassen. Der
|
|
schreibt 45 Dateien um. Wer dort gerade eine offen hatte,
|
|
bekam sie unter den Händen weg geändert.
|
|
|
|
Dasselbe hat in RunOne am 03.09.2026 sieben Minuten Ausfall
|
|
gekostet, und dort gibt es seitdem `arbeitsschloss.sh`. Diese
|
|
Fassung übernimmt dessen Lehren und löst zusätzlich das Problem,
|
|
an dem die dortige am meisten hängt — siehe „WER BIN ICH".
|
|
|
|
---------------------------------------------------------------------
|
|
WAS DIESES SCHLOSS IST UND WAS NICHT
|
|
|
|
Es ist kein Riegel. Es kann niemanden aussperren, und das soll es
|
|
auch nicht — wer wirklich muss, kommt vorbei. Es beantwortet eine
|
|
einzige Frage, die heute niemand beantworten konnte: „arbeitet
|
|
hier gerade sonst jemand?"
|
|
|
|
Ein Schloss, das das eigene Arbeiten blockiert, wird abgeschafft.
|
|
Deshalb drei Eigenschaften, alle drei teuer gelernt:
|
|
|
|
1. ES VERFÄLLT (nach zwei Stunden). Ein Schloss, das man
|
|
vergessen kann, blockiert irgendwann dauerhaft — und wird beim
|
|
ersten Ärger umgangen. Ab da ist es wertlos, obwohl es noch da
|
|
ist. Ein verfallenes Schloss gilt als frei, und dass da jemand
|
|
war, wird ausdrücklich gesagt.
|
|
|
|
2. DIE FRAGE IST „HÄLT ES JEMAND ANDERS", NICHT „IST
|
|
ABGESCHLOSSEN". RunOnes erste Fassung fragte das Zweite, und
|
|
das war falsch: Wer während seiner Arbeit ordentlich
|
|
abschließt — also genau das erwünschte Verhalten — hätte
|
|
danach nie mehr ausliefern können. Eine Sicherung, die das
|
|
richtige Verhalten bestraft, wird abgeschafft. Dafür gibt es
|
|
`fremd`.
|
|
|
|
3. WER ES NICHT LESEN KANN, WIRD NICHT GEBLOCKT. Ein kaputtes
|
|
Schloss darf nicht die Arbeit anhalten. Es meldet dann den
|
|
dritten Ausgang — „konnte nicht nachsehen" — und lässt
|
|
weiterlaufen. Eine Warnung, die bei jeder Störung die Arbeit
|
|
stoppt, wird als Erstes entfernt.
|
|
|
|
---------------------------------------------------------------------
|
|
WER BIN ICH — UND WARUM DAS DER SCHWIERIGE TEIL IST
|
|
|
|
RunOnes Fassung nimmt im Zweifel den Systembenutzer. Am 04.09.2026
|
|
stand dort dazu die bittere Notiz: Zwei Claudian-Sitzungen laufen
|
|
BEIDE als `claudian`, und ohne gesetztes `ARBEITER` sah das fremde
|
|
Schloss aus wie das eigene — die Sicherung griff ausgerechnet
|
|
zwischen den zwei Fällen nicht, für die sie gebaut wurde. Deshalb
|
|
ist dort `export ARBEITER=…` Pflicht.
|
|
|
|
Pflicht heißt: man vergisst es. Hier gibt es etwas Besseres:
|
|
`CLAUDE_CODE_SESSION_ID` steht in jeder Sitzung und ist je Sitzung
|
|
verschieden (nachgesehen, 36 Zeichen UUID). Zwei Sitzungen auf
|
|
demselben Windows-Benutzer unterscheiden sich damit von selbst,
|
|
ohne dass jemand etwas tun muss.
|
|
|
|
Die Reihenfolge ist deshalb:
|
|
1. `ARBEITER` — wenn jemand ausdrücklich einen Namen will
|
|
2. Sitzungskennung — der Normalfall, ohne Zutun
|
|
3. Benutzername + WARNUNG — der schlechte Fall, und er sagt es
|
|
|
|
---------------------------------------------------------------------
|
|
AUFRUFEN
|
|
|
|
node tools/arbeitsschloss.mjs nehmen ["was ich tue"]
|
|
node tools/arbeitsschloss.mjs freigeben
|
|
node tools/arbeitsschloss.mjs ansehen 0 = frei/verfallen, 1 = belegt
|
|
node tools/arbeitsschloss.mjs fremd 0 = frei oder MEINES, 1 = fremd
|
|
node tools/arbeitsschloss.mjs einrichten setzt den git-Haken
|
|
|
|
Die Stempelwerkzeuge nehmen es SELBST und geben es selbst wieder
|
|
frei — wie `bauen.sh` im Shop. Ein Schloss, das man von Hand nehmen
|
|
muss, wird vergessen; dann wird es umgangen und ist ab da nichts
|
|
mehr wert.
|
|
===================================================================== */
|
|
|
|
import { readFileSync, writeFileSync, unlinkSync, existsSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { hostname, userInfo } from "node:os";
|
|
import { execFileSync } from "node:child_process";
|
|
|
|
const WURZEL = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const DATEI = join(WURZEL, ".arbeitsschloss");
|
|
const HAKEN_ORDNER = "tools/git-haken";
|
|
|
|
/** Nach wie vielen Minuten ein Schloss als vergessen gilt. */
|
|
const VERFALL_MINUTEN = Number(process.env.SCHLOSS_VERFALL || 120);
|
|
|
|
const rot = (t) => `\x1b[31m${t}\x1b[0m`;
|
|
const gelb = (t) => `\x1b[33m${t}\x1b[0m`;
|
|
|
|
/** Wer bin ich? Siehe „WER BIN ICH" im Kopf. */
|
|
export function werIch() {
|
|
if (process.env.ARBEITER) return { name: process.env.ARBEITER, woher: "ARBEITER" };
|
|
const s = process.env.CLAUDE_CODE_SESSION_ID;
|
|
if (s && s.length >= 8) return { name: `claude-${s.slice(0, 8)}`, woher: "Sitzungskennung" };
|
|
return { name: userInfo().username, woher: "Benutzername", schwach: true };
|
|
}
|
|
|
|
/** Was steht im Schloss? `null` = frei, `undefined` = konnte nicht nachsehen. */
|
|
function lesen() {
|
|
if (!existsSync(DATEI)) return null;
|
|
try {
|
|
const roh = readFileSync(DATEI, "utf8");
|
|
const feld = (n) => (roh.match(new RegExp(`^${n}=(.*)$`, "m")) || [])[1]?.trim() || "";
|
|
const wer = feld("wer");
|
|
if (!wer) return null;
|
|
const seit = feld("seit");
|
|
const ms = Date.parse(seit);
|
|
/* EIN UNLESBARER ZEITSTEMPEL IST KEIN JUNGES SCHLOSS. Stünde hier
|
|
0, wäre das Schloss „gerade erst genommen" und würde ewig
|
|
blocken. Unlesbar heißt: als verfallen behandeln. */
|
|
const alterMin = Number.isNaN(ms) ? 99999 : Math.floor((Date.now() - ms) / 60000);
|
|
return { wer, seit, was: feld("was"), rechner: feld("rechner"), alterMin };
|
|
} catch (f) {
|
|
console.error(gelb(`[Schloss] Konnte nicht nachsehen: ${f?.message}`));
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
function schreiben(wer, was) {
|
|
writeFileSync(DATEI, [
|
|
`wer=${wer}`,
|
|
`seit=${new Date().toISOString()}`,
|
|
`was=${was || ""}`,
|
|
`rechner=${hostname()}`,
|
|
"",
|
|
].join("\n"), "utf8");
|
|
}
|
|
|
|
const verfallen = (s) => s.alterMin >= VERFALL_MINUTEN;
|
|
|
|
/* ---------------------------------------------------------------------
|
|
Der git-Haken
|
|
|
|
Hier liegt das Stück, das heute wirklich gefehlt hat: Beide
|
|
Sitzungen haben `git add -A` benutzt. Ein Haken ist die einzige
|
|
Stelle, an der sich das ABFANGEN lässt, ohne dass jemand daran
|
|
denken muss.
|
|
|
|
`core.hooksPath` statt `.git/hooks`: Letzteres wird nicht
|
|
versioniert und wäre nach jedem frischen Klon weg — also genau
|
|
dann nicht da, wenn es gebraucht wird. Der Ordner liegt deshalb im
|
|
Baum, und `einrichten` zeigt git darauf.
|
|
--------------------------------------------------------------------- */
|
|
function einrichten() {
|
|
let jetzt = "";
|
|
try {
|
|
jetzt = execFileSync("git", ["config", "--get", "core.hooksPath"],
|
|
{ cwd: WURZEL, encoding: "utf8" }).trim();
|
|
} catch { jetzt = ""; }
|
|
if (jetzt === HAKEN_ORDNER) {
|
|
console.log(`Der git-Haken ist eingerichtet (core.hooksPath = ${HAKEN_ORDNER}).`);
|
|
return 0;
|
|
}
|
|
if (jetzt) {
|
|
console.error(rot(`core.hooksPath zeigt auf "${jetzt}", nicht auf "${HAKEN_ORDNER}".`));
|
|
console.error(" Das überschreibe ich nicht von mir aus — dort hängt vielleicht");
|
|
console.error(" etwas anderes dran. Von Hand:");
|
|
console.error(` git config core.hooksPath ${HAKEN_ORDNER}`);
|
|
return 1;
|
|
}
|
|
execFileSync("git", ["config", "core.hooksPath", HAKEN_ORDNER], { cwd: WURZEL });
|
|
console.log(`Eingerichtet: core.hooksPath = ${HAKEN_ORDNER}`);
|
|
return 0;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
Für andere Werkzeuge: selbst nehmen, selbst freigeben
|
|
--------------------------------------------------------------------- */
|
|
|
|
/** Nimmt das Schloss für die Dauer von `tun()` und gibt es danach frei.
|
|
*
|
|
* GIBT AUCH BEI EINEM FEHLER FREI. Ein Schloss, das nach einem
|
|
* Absturz liegen bleibt, ist der Anfang vom Umgehen — es verfällt
|
|
* zwar nach zwei Stunden, aber zwei Stunden sind lang.
|
|
*
|
|
* UND ES GIBT NICHT FREI, WAS IHM NICHT GEHÖRT: Hielt ich das
|
|
* Schloss schon vorher (weil jemand es von Hand genommen hat),
|
|
* bleibt es danach stehen. Sonst nähme ein Stempellauf dem
|
|
* Menschen sein Schloss weg.
|
|
*/
|
|
export async function mitSchloss(was, tun) {
|
|
const ich = werIch();
|
|
const vorher = lesen();
|
|
const schonMeins = vorher && vorher.wer === ich.name && !verfallen(vorher);
|
|
const lage = fremdLage(ich);
|
|
if (lage.fremd) {
|
|
console.error(rot("\nABBRUCH: In diesem Verzeichnis arbeitet gerade jemand anders."));
|
|
console.error(` Wer: ${lage.wer}`);
|
|
console.error(` Seit: vor ${lage.alterMin} Minuten`);
|
|
if (lage.was) console.error(` Was: ${lage.was}`);
|
|
console.error("");
|
|
console.error(` „${was}" schreibt Dateien um, die dort offen sein könnten.`);
|
|
console.error(" Genau daraus wurde am 01.10.2026 zweimal fast ein Schaden.");
|
|
console.error(" Erst abstimmen. Wenn das Schloss liegen geblieben ist:");
|
|
console.error(" node tools/arbeitsschloss.mjs ansehen");
|
|
process.exit(9);
|
|
}
|
|
if (!schonMeins) schreiben(ich.name, was);
|
|
try {
|
|
return await tun();
|
|
} finally {
|
|
if (!schonMeins) {
|
|
try { unlinkSync(DATEI); } catch { /* war schon weg -- in Ordnung */ }
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Dasselbe wie `mitSchloss`, aber in EINER Zeile am Kopf eines
|
|
* Werkzeugs — ohne dass es seinen Inhalt in eine Funktion packen
|
|
* muss.
|
|
*
|
|
* WARUM ES DAS ZUSAETZLICH GIBT: Die Stempelwerkzeuge sind von oben
|
|
* nach unten geschrieben. Sie für `mitSchloss` umzubauen wäre mehr
|
|
* Risiko als Nutzen — und ein Schloss, dessen Einbau riskant ist,
|
|
* wird nicht eingebaut.
|
|
*
|
|
* Gibt beim Programmende frei, auch nach einem Absturz: Ein Schloss,
|
|
* das liegen bleibt, ist der Anfang vom Umgehen.
|
|
*/
|
|
export function schlossKurz(was) {
|
|
const ich = werIch();
|
|
const lage = fremdLage(ich);
|
|
if (lage.fremd) {
|
|
console.error(rot("\nABBRUCH: In diesem Verzeichnis arbeitet gerade jemand anders."));
|
|
console.error(` Wer: ${lage.wer}`);
|
|
console.error(` Seit: vor ${lage.alterMin} Minuten`);
|
|
if (lage.was) console.error(` Was: ${lage.was}`);
|
|
console.error("");
|
|
console.error(` „${was}" schreibt viele Dateien um — auch solche, die dort`);
|
|
console.error(" gerade offen sein könnten. Am 01.10.2026 ist genau das");
|
|
console.error(" zweimal nur gutgegangen.");
|
|
console.error("");
|
|
console.error(" Erst abstimmen. Nachsehen: node tools/arbeitsschloss.mjs ansehen");
|
|
process.exit(9);
|
|
}
|
|
if (lage.eigenes) return; /* nicht wegnehmen, was schon meins ist */
|
|
schreiben(ich.name, was);
|
|
let weg = false;
|
|
const loesen = () => {
|
|
if (weg) return;
|
|
weg = true;
|
|
try { unlinkSync(DATEI); } catch { /* war schon weg */ }
|
|
};
|
|
process.on("exit", loesen);
|
|
/* Auch bei Strg+C -- sonst bleibt es nach jedem Abbruch liegen. */
|
|
for (const art of ["SIGINT", "SIGTERM"]) {
|
|
process.on(art, () => { loesen(); process.exit(130); });
|
|
}
|
|
}
|
|
|
|
/** Hält das Schloss JEMAND ANDERS? Siehe Punkt 2 im Kopf. */
|
|
export function fremdLage(ich = werIch()) {
|
|
const s = lesen();
|
|
if (s === undefined) return { unklar: true, fremd: false };
|
|
if (s === null) return { frei: true, fremd: false };
|
|
if (verfallen(s)) return { verfallen: true, fremd: false, ...s };
|
|
if (s.wer === ich.name) return { eigenes: true, fremd: false, ...s };
|
|
return { fremd: true, ...s };
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
Aufruf von der Befehlszeile
|
|
--------------------------------------------------------------------- */
|
|
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
const befehl = process.argv[2] || "ansehen";
|
|
const ich = werIch();
|
|
if (ich.schwach && befehl !== "ansehen") {
|
|
console.error(gelb(
|
|
`[Schloss] Kennung ist nur der Benutzername ("${ich.name}").`));
|
|
console.error(gelb(
|
|
" Zwei Sitzungen auf demselben Benutzer sehen damit gleich aus — genau"));
|
|
console.error(gelb(
|
|
" dafür hat RunOne am 04.09.2026 bezahlt. Besser: ARBEITER=<name> setzen."));
|
|
}
|
|
|
|
if (befehl === "nehmen") {
|
|
const grund = process.argv[3] || "";
|
|
const s = lesen();
|
|
if (s === undefined) {
|
|
console.error(gelb("[Schloss] Nicht lesbar — ich nehme es trotzdem und sage es."));
|
|
schreiben(ich.name, grund);
|
|
process.exit(0);
|
|
}
|
|
if (s && s.wer === ich.name && !verfallen(s)) {
|
|
schreiben(ich.name, grund);
|
|
console.log(`Schloss war schon deins ("${ich.name}"), Zeit erneuert.`);
|
|
process.exit(0);
|
|
}
|
|
if (s && verfallen(s)) {
|
|
console.log(gelb(`Achtung: "${s.wer}" hatte das Schloss seit ${s.alterMin} Minuten`));
|
|
console.log(gelb("und hat es nicht freigegeben. Es gilt als verfallen."));
|
|
if (s.was) console.log(` Was dort lief: ${s.was}`);
|
|
schreiben(ich.name, grund);
|
|
process.exit(0);
|
|
}
|
|
if (s) {
|
|
console.error(rot("HIER ARBEITET GERADE JEMAND ANDERS."));
|
|
console.error(` Wer: ${s.wer}`);
|
|
console.error(` Seit: ${s.seit} (vor ${s.alterMin} Minuten)`);
|
|
if (s.was) console.error(` Was: ${s.was}`);
|
|
if (s.rechner) console.error(` Rechner: ${s.rechner}`);
|
|
console.error("");
|
|
console.error(" Nicht einfach weitermachen. Erst abstimmen — bei zwei");
|
|
console.error(" Claude-Sitzungen geht das mit SendMessage.");
|
|
process.exit(1);
|
|
}
|
|
schreiben(ich.name, grund);
|
|
console.log(`Schloss genommen von "${ich.name}" (${ich.woher})`
|
|
+ `${grund ? ` — ${grund}` : ""}.`);
|
|
process.exit(0);
|
|
}
|
|
|
|
if (befehl === "freigeben") {
|
|
const s = lesen();
|
|
if (!s) { console.log("Es war gar nicht abgeschlossen."); process.exit(0); }
|
|
if (s.wer !== ich.name && process.env.SCHLOSS_ZWANG !== "ja") {
|
|
console.error(rot(`Das Schloss gehört "${s.wer}", nicht "${ich.name}".`));
|
|
console.error(" Wenn du sicher bist: SCHLOSS_ZWANG=ja node tools/arbeitsschloss.mjs freigeben");
|
|
process.exit(1);
|
|
}
|
|
unlinkSync(DATEI);
|
|
console.log("Schloss freigegeben.");
|
|
process.exit(0);
|
|
}
|
|
|
|
if (befehl === "ansehen") {
|
|
const s = lesen();
|
|
if (s === undefined) { console.log("konnte nicht nachsehen"); process.exit(0); }
|
|
if (s === null) { console.log("frei"); process.exit(0); }
|
|
if (verfallen(s)) {
|
|
console.log(`verfallen: "${s.wer}" seit ${s.alterMin} Minuten`
|
|
+ `${s.was ? ` (${s.was})` : ""}`);
|
|
process.exit(0);
|
|
}
|
|
console.log(`belegt: "${s.wer}" seit ${s.alterMin} Minuten${s.was ? ` (${s.was})` : ""}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (befehl === "fremd") {
|
|
const l = fremdLage(ich);
|
|
if (l.unklar) { console.log("konnte nicht nachsehen"); process.exit(0); }
|
|
if (l.frei) { console.log("frei"); process.exit(0); }
|
|
if (l.verfallen) { console.log(`verfallen: "${l.wer}" seit ${l.alterMin} Minuten`); process.exit(0); }
|
|
if (l.eigenes) { console.log(`dein eigenes Schloss (seit ${l.alterMin} Minuten)`); process.exit(0); }
|
|
console.log(`belegt von "${l.wer}" seit ${l.alterMin} Minuten${l.was ? ` (${l.was})` : ""}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (befehl === "einrichten") process.exit(einrichten());
|
|
|
|
console.error("Aufruf: node tools/arbeitsschloss.mjs"
|
|
+ " {nehmen|freigeben|ansehen|fremd|einrichten} [\"was ich tue\"]");
|
|
process.exit(2);
|
|
}
|