Vierter Modus 'Idee': Produkt-Idee durchdenken statt Projekt starten

Fuer echte Software-Ideen (z.B. Game-Server-Management), die weder MC2/Lucy-
Umbau noch schon ein Zed-Projekt sind. Volle Denk-Kaskade mit PRODUKT-Blick
(was, fuer wen, was gibt es schon, kleinster Wurf, was spricht dagegen) statt
Umsetzungs-Blick. Ergebnis: NUR KONZEPT.md — keine Roadmap, kein Geruest, keine
Bau-Aufforderung; der Commander entscheidet danach. Kein Ziel-Schalter (eine
Idee braucht noch keine Plattform). Eigene Farbe (sky), Button 'Durchdenken'.
Nebenbei: projektstart-SOUL.md ist jetzt versioniert + deploy-fest (lag bisher
nur auf der Box).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-07-20 22:57:06 +02:00
parent 40c8ed4754
commit 7389386791
30 changed files with 247 additions and 98 deletions
+4 -2
View File
@@ -14,7 +14,8 @@ class IdeeIn(BaseModel):
notiz: str = "" notiz: str = ""
welt: str = "box" # "box" = Werkstatt baut · "ide" = vorbereiten für Zed welt: str = "box" # "box" = Werkstatt baut · "ide" = vorbereiten für Zed
tiefe: str = "" # nur ide: "simpel" | "gruendlich" (leer = Box schätzt selbst) tiefe: str = "" # nur ide: "simpel" | "gruendlich" (leer = Box schätzt selbst)
ziel: str = "" # nur ide: "lxc" | "docker" (leer = Box entscheidet) ziel: str = "" # nur ide-Projekt: "lxc" | "docker" (leer = Box entscheidet)
art: str = "projekt" # nur ide: "projekt" (Repo+Roadmap+Bau) | "idee" (nur durchdenken)
class TaskIn(BaseModel): class TaskIn(BaseModel):
@@ -33,7 +34,8 @@ def list_queue() -> dict:
@router.post("/ideen") @router.post("/ideen")
def add_idea(body: IdeeIn) -> dict: def add_idea(body: IdeeIn) -> dict:
res = ideen.add_idea(body.titel, body.notiz, welt=body.welt, tiefe=body.tiefe, ziel=body.ziel) res = ideen.add_idea(body.titel, body.notiz, welt=body.welt, tiefe=body.tiefe,
ziel=body.ziel, art=body.art)
if not res.get("ok"): if not res.get("ok"):
raise HTTPException(400, res.get("error", "Idee konnte nicht angelegt werden.")) raise HTTPException(400, res.get("error", "Idee konnte nicht angelegt werden."))
return res return res
+37 -7
View File
@@ -307,8 +307,26 @@ _INFRA_LXC = (
"aus per 'ssh pve' erreichbar (root, Key), Steuerung mit 'pct'. Was dort schon laeuft (Reverse-" "aus per 'ssh pve' erreichbar (root, Key), Steuerung mit 'pct'. Was dort schon laeuft (Reverse-"
"Proxy, DNS, Gitea usw.), schaust du bei Bedarf mit 'ssh pve pct list' nach — nicht annehmen.\n" "Proxy, DNS, Gitea usw.), schaust du bei Bedarf mit 'ssh pve pct list' nach — nicht annehmen.\n"
"· Gitea ist self-hosted im Heimnetz (CI-Pipelines moeglich).\n" "· Gitea ist self-hosted im Heimnetz (CI-Pipelines moeglich).\n"
"· Alles laeuft lokal — KEINE Cloud, kein fremder Hoster, keine Bezahl-Dienste.\n" "· Alles laeuft lokal — KEINE Cloud, kein fremder Hoster, keine Bezahl-Dienste.")
"Richte den Tech-Vorschlag an der gewaehlten ZIEL-PLATTFORM aus, nicht am Industrie-Default.")
_ZIEL_HINWEIS = ("Richte den Tech-Vorschlag an der gewaehlten ZIEL-PLATTFORM aus, "
"nicht am Industrie-Default.")
# Auftrags-Art „Idee pruefen": Produkt-Blick statt Umsetzungs-Blick, KEIN Projektstart.
_ART_IDEE = (
"AUFTRAGS-ART: IDEE PRUEFEN (KEIN Projektstart!). Der Commander will diese Produkt-Idee erst "
"einmal DURCHDACHT haben — er hat sich NICHT entschieden, sie zu bauen.\n"
"· Blickwinkel zuerst PRODUKT, nicht Technik: Was ist es genau? Welches Problem, fuer wen? Was "
"gibt es dafuer schon und warum reicht das nicht? Was waere der kleinste sinnvolle Wurf? Was "
"spricht DAGEGEN (Aufwand, Betrieb, Wartung, Risiken)? Technik nur so tief, wie es fuer die "
"Machbarkeit noetig ist.\n"
"· Rollen-Cast entsprechend waehlen — NICHT nur Entwickler-Rollen, sondern auch Zielgruppen-, "
"Abgrenzungs-/Markt- und Betriebs-Sicht. Volle Denk-Kaskade mit Advocatus Diaboli.\n"
"· Ergebnis: NUR ein KONZEPT.md im neuen Repo (plus knappes README). KEINE ROADMAP.md, KEINE "
"AGENTS.md, KEIN SAVEPOINT.md, KEIN Geruest — das entsteht erst, wenn der Commander sich fuers "
"Bauen entscheidet.\n"
"· Uebergabe NICHT als Bau-Aufforderung formulieren: sag, was die Idee waere, was sie braeuchte "
"und was dagegen spricht — die Entscheidung liegt beim Commander.")
# Ziel-Plattform je Projekt (vom Commander gewaehlt) — ueberstimmt die Annahmen des Modells. # Ziel-Plattform je Projekt (vom Commander gewaehlt) — ueberstimmt die Annahmen des Modells.
_ZIEL = { _ZIEL = {
@@ -327,7 +345,8 @@ _ZIEL_EHRLICH = ("Traegt die gewaehlte Ziel-Plattform fuer dieses Projekt NICHT
def add_idea(titel: str, notiz: str = "", created_by: str = "mc2-ui", def add_idea(titel: str, notiz: str = "", created_by: str = "mc2-ui",
welt: str = "box", tiefe: str = "", ziel: str = "") -> dict: welt: str = "box", tiefe: str = "", ziel: str = "",
art: str = "projekt") -> dict:
"""Idee in die Queue legen. """Idee in die Queue legen.
welt='box' (Default): triage — der Specifier arbeitet sie aus, die Werkstatt baut, welt='box' (Default): triage — der Specifier arbeitet sie aus, die Werkstatt baut,
@@ -339,8 +358,9 @@ def add_idea(titel: str, notiz: str = "", created_by: str = "mc2-ui",
Karte nie an und die Werkstatt baut sie nie (der Fan-out-Fehler vom 20.07.). Karte nie an und die Werkstatt baut sie nie (der Fan-out-Fehler vom 20.07.).
tiefe (nur ide): 'simpel' | 'gruendlich' — vom Knopf gewaehlte Konzept-Tiefe; leer = tiefe (nur ide): 'simpel' | 'gruendlich' — vom Knopf gewaehlte Konzept-Tiefe; leer =
die Box schaetzt selbst (Fallback fuer Telegram/Lucy). die Box schaetzt selbst (Fallback fuer Telegram/Lucy).
ziel (nur ide): 'lxc' | 'docker' — Ziel-Plattform des Projekts; leer = die Box ziel (nur ide-Projekt): 'lxc' | 'docker' — Ziel-Plattform; leer = die Box entscheidet.
entscheidet (bekommt aber immer den Infrastruktur-Steckbrief).""" art (nur ide): 'projekt' (Default, Repo+Doku+Roadmap, Bau in Zed) oder 'idee'
(Produkt-Idee nur durchdenken: NUR Konzept, keine Roadmap/Geruest, kein Bau-Druck)."""
if not _available(): if not _available():
return {"ok": False, "error": "Die Ideen-Queue lebt auf der Box."} return {"ok": False, "error": "Die Ideen-Queue lebt auf der Box."}
titel = (titel or "").strip() titel = (titel or "").strip()
@@ -352,12 +372,18 @@ def add_idea(titel: str, notiz: str = "", created_by: str = "mc2-ui",
args = ["create", titel, "--assignee", "projektstart", "--created-by", created_by, "--json"] args = ["create", titel, "--assignee", "projektstart", "--created-by", created_by, "--json"]
# Vorspann: Aufwand (Tiefe) + Ziel-Plattform + Infrastruktur — überstimmt die # Vorspann: Aufwand (Tiefe) + Ziel-Plattform + Infrastruktur — überstimmt die
# Annahmen des Modells und macht das Konzept auf die reale Umgebung passend. # Annahmen des Modells und macht das Konzept auf die reale Umgebung passend.
if str(art).lower() == "idee":
# Idee pruefen: Produkt-Blick, volle Kaskade, KEIN Ziel/Geruest/Bau-Druck.
# Sein Heimlabor bleibt Kontext (dort liefe es ja), aber ohne Plattform-Festlegung.
vorspann = [_ART_IDEE, _AUFWAND["gruendlich"], _INFRA_LXC]
else:
zielwahl = _ZIEL.get(str(ziel).lower()) zielwahl = _ZIEL.get(str(ziel).lower())
vorspann = [p for p in (_AUFWAND.get(str(tiefe).lower()), zielwahl) if p] vorspann = [p for p in (_AUFWAND.get(str(tiefe).lower()), zielwahl) if p]
# Heimlabor-Kontext nur beim LXC-Pfad (und ohne Wahl = seine Standard-Welt); # Heimlabor-Kontext nur beim LXC-Pfad (und ohne Wahl = seine Standard-Welt);
# Docker-Projekte bekommen bewusst den portablen Kontext. # Docker-Projekte bekommen bewusst den portablen Kontext.
infra = _INFRA_DOCKER if str(ziel).lower() == "docker" else _INFRA_LXC infra = _INFRA_DOCKER if str(ziel).lower() == "docker" else _INFRA_LXC
vorspann.append(infra + (" " + _ZIEL_EHRLICH if zielwahl else "")) vorspann.append(infra + " " + _ZIEL_HINWEIS
+ (" " + _ZIEL_EHRLICH if zielwahl else ""))
notiz = "\n\n".join(vorspann) + ("\n\n" + notiz if notiz else "") notiz = "\n\n".join(vorspann) + ("\n\n" + notiz if notiz else "")
else: else:
args = ["create", titel, "--triage", "--created-by", created_by, "--json"] args = ["create", titel, "--triage", "--created-by", created_by, "--json"]
@@ -373,7 +399,11 @@ def add_idea(titel: str, notiz: str = "", created_by: str = "mc2-ui",
_list_cache["ts"] = 0.0 # nächster Poll zeigt die neue Idee sofort _list_cache["ts"] = 0.0 # nächster Poll zeigt die neue Idee sofort
try: try:
from services import announce from services import announce
if welt == "ide": if welt == "ide" and str(art).lower() == "idee":
announce.add(f"Idee wird durchdacht: „{titel}“ ({task['id']}) — die Box arbeitet ein "
"Konzept aus (Produkt-Blick). Danach entscheidest du, ob was draus wird.",
"[Ideen-Queue]", "ideen-queue", "silent")
elif welt == "ide":
announce.add(f"Neues IDE-Projekt in Vorbereitung: „{titel}“ ({task['id']}) — die Box " announce.add(f"Neues IDE-Projekt in Vorbereitung: „{titel}“ ({task['id']}) — die Box "
"härtet das Konzept und legt das Repo an, dann baust du in Zed.", "härtet das Konzept und legt das Repo an, dann baust du in Zed.",
"[Ideen-Queue]", "ideen-queue", "silent") "[Ideen-Queue]", "ideen-queue", "silent")
+5
View File
@@ -140,6 +140,11 @@ cp "$SRC/deploy/gitea-repo-create.sh" "$HOME/.hermes/scripts/gitea-repo-create.s
# statt Lucy-default. Profil selbst wird einmalig per `hermes profile create betrieb # statt Lucy-default. Profil selbst wird einmalig per `hermes profile create betrieb
# --clone-from werkstatt` angelegt (model coder→hermes, Description fürs Specifier-Routing). # --clone-from werkstatt` angelegt (model coder→hermes, Description fürs Specifier-Routing).
[ -d "$HOME/.hermes/profiles/betrieb" ] && cp "$SRC/deploy/betrieb-SOUL.md" "$HOME/.hermes/profiles/betrieb/SOUL.md" [ -d "$HOME/.hermes/profiles/betrieb" ] && cp "$SRC/deploy/betrieb-SOUL.md" "$HOME/.hermes/profiles/betrieb/SOUL.md"
# IDE-Vorbereiter (20.07.2026): haertet ein Konzept (konzept-fliessband), legt das Repo an und
# fuellt es NUR mit Doku — der Commander baut dann in Zed. Sonderfall „IDEE PRUEFEN": nur Konzept,
# kein Geruest, kein Bau-Druck. Profil einmalig per `hermes profile create projektstart
# --clone-from werkstatt` angelegt (model coder→hermes, damit heavy warm bleibt).
[ -d "$HOME/.hermes/profiles/projektstart" ] && cp "$SRC/deploy/projektstart-SOUL.md" "$HOME/.hermes/profiles/projektstart/SOUL.md"
chmod +x "$HOME/.hermes/scripts/fremdblick.sh" "$HOME/.hermes/scripts/dreaming-feed.sh" "$HOME/.hermes/scripts/worker.sh" "$HOME/.hermes/scripts/chef-gutachter-feed.sh" "$HOME/.hermes/scripts/hermes-release-radar-feed.sh" "$HOME/.hermes/scripts/radar-selbstkritik-wrapper.sh" "$HOME/.hermes/scripts/idle-radar-feed.sh" "$HOME/.hermes/scripts/selbst-inventur.sh" "$HOME/.hermes/scripts/karten-gutachter.sh" "$HOME/.hermes/scripts/trend-radar-feed.sh" "$HOME/.hermes/scripts/pruefstand.sh" "$HOME/.hermes/scripts/restore-probe.sh" "$HOME/.hermes/scripts/venv-audit.sh" "$HOME/.hermes/scripts/gitea-repo-create.sh" "$HOME/.hermes/scripts/mem0-konsolidierung.sh" "$HOME/.hermes/scripts/mem0-konsolidierung.py" chmod +x "$HOME/.hermes/scripts/fremdblick.sh" "$HOME/.hermes/scripts/dreaming-feed.sh" "$HOME/.hermes/scripts/worker.sh" "$HOME/.hermes/scripts/chef-gutachter-feed.sh" "$HOME/.hermes/scripts/hermes-release-radar-feed.sh" "$HOME/.hermes/scripts/radar-selbstkritik-wrapper.sh" "$HOME/.hermes/scripts/idle-radar-feed.sh" "$HOME/.hermes/scripts/selbst-inventur.sh" "$HOME/.hermes/scripts/karten-gutachter.sh" "$HOME/.hermes/scripts/trend-radar-feed.sh" "$HOME/.hermes/scripts/pruefstand.sh" "$HOME/.hermes/scripts/restore-probe.sh" "$HOME/.hermes/scripts/venv-audit.sh" "$HOME/.hermes/scripts/gitea-repo-create.sh" "$HOME/.hermes/scripts/mem0-konsolidierung.sh" "$HOME/.hermes/scripts/mem0-konsolidierung.py"
# Werkstatt-Skill (Autonomie E6): Selbstwartungs-Kreislauf für Hermes. # Werkstatt-Skill (Autonomie E6): Selbstwartungs-Kreislauf für Hermes.
mkdir -p "$HOME/.hermes/skills/wartung" mkdir -p "$HOME/.hermes/skills/wartung"
+88
View File
@@ -0,0 +1,88 @@
# Projektstart-Worker (Profil „projektstart") — IDE-Vorbereiter
Du bist der **IDE-Vorbereiter** der AI-Box. Du bearbeitest EINE Kanban-Aufgabe: eine Idee des
Commanders, die er **selbst in seiner IDE (Zed / OpenCode) bauen** will — nicht die Box.
Dein Ergebnis ist **kein Code**, sondern ein **startklares, leeres Projekt-Repo**: ein
wasserdicht durchdachtes Konzept plus alle Steuerungs-Dokumente, mit denen der Commander in Zed
dem Coder sofort einen sauberen Auftrag geben kann. Du denkst und bereitest vor — **gebaut wird
in Zed, von ihm.**
## Der Ablauf (genau diese vier Schritte, in dieser Reihenfolge)
### 1. Konzept wasserdicht härten — via `konzept-fliessband`
Nutze den Skill **konzept-fliessband** vollständig: der starke Denker (`gpt-oss-120b`/heavy über
`~/.hermes/scripts/worker.sh`) wählt den Rollen-Cast, die Rollen schärfen in Runden EIN gemeinsames
Konzept, ein Advocatus Diaboli (`fremdblick.sh`, fremdes Modell) sucht Löcher — bis keine Blocker
mehr offen sind (max. 3 Runden). „In der Vorbereitung alles rausholen" ist ausdrücklich gewollt:
lieber gründlich denken als schnell fertig sein. Ergebnis: **EIN wasserdichtes Konzept-Dokument**
(Text), das später als `KONZEPT.md` ins Repo geht.
Halte dich an die Leitplanken des Skills: jede Rollen-Stimme MUSS aus einem `worker.sh`-Aufruf an
heavy stammen (nie selbst ausdenken), großzügige `WORKER_MAXTOK`/`FREMDBLICK_MAXTOK` (Reasoning-
Modelle brauchen Token-Luft), Modell-Wechsel minimieren.
### 2. Repo anlegen (leer, privat)
Wähle einen kurzen, sauberen Projektnamen (kebab-case, z. B. `homelab-dashboard`). Lege das Repo an:
bash ~/.hermes/scripts/gitea-repo-create.sh <name> "<eine Zeile Beschreibung>"
Das Skript legt IMMER **privat** an, protokolliert die Anlage und gibt als **letzte Zeile**
`CLONE <https-clone-url>` aus. Existiert der Name schon (Skript meldet Konflikt), häng eine kurze
Unterscheidung an (`<name>-v2` o. ä.) und melde das in der Übergabe.
### 3. Repo NUR mit Doku füllen — KEIN Code
Klone das frische Repo in deinen Task-Workspace (NICHT `git init`, NICHT shallow) und schreibe
genau diese Dateien — sonst **nichts**, kein Code, kein Gerüst:
- **`KONZEPT.md`** — das wasserdichte Konzept aus Schritt 1 (Ziel, Ansatz, Architektur-Skizze,
offene Entscheidungen, was der Advocatus Diaboli geprüft hat).
- **`ROADMAP.md`** — der Etappen-/Meilenstein-Plan aus dem Konzept: jede Etappe für sich
lauffähig, in Reihenfolge, mit klarem „fertig wenn …".
- **`AGENTS.md`** — Arbeits-Konventionen für den Zed-Coder (nach dem `projekt-start`-Ritual):
Deutsch/Nicht-Entwickler, Plan-vor-Code, kleine Schritte, beweisen statt behaupten, Savepoints,
Box-Modelle je Aufgabe (plan=heavy, build=coder). Kurz, konkret, projektbezogen.
- **`README.md`** — was das Projekt ist, in Alltagssprache; erste Schritte zum Loslegen in Zed.
- **`SAVEPOINT.md`** — Startzustand: „vorbereitet — Bau beginnt in Zed", Stand/nächste Schritte/
offene Fragen (lebendes Übergabe-Dokument für den ersten Zed-Chat).
- **`.aiexclude`** — gitignore-Syntax: was die KI NICHT lesen soll (`.env`, Secrets, große Daten).
Committe (`git add -A && git commit`) und pushe auf **main dieses NEUEN Repos** — das ist korrekt:
es ist das frisch angelegte, eigene Repo des Commanders, kein Vorschlag an ein bestehendes System.
Prüfe nach dem Push mit `git ls-remote origin main`, dass es wirklich angekommen ist.
### 4. Übergabe — `kanban_complete`
Schließe die Karte mit einer Zusammenfassung ab, die das Auftragsbuch dem Commander zeigt:
> „Projekt **<name>** ist vorbereitet. Repo: `<clone-url>`. Öffne es in Zed und wirf dem Coder
> **KONZEPT.md** vor — der Plan steht in **ROADMAP.md**. Die Box baut ab hier nicht mehr mit."
Nenne knapp, was das Konzept-Härten ergab (Rollen-Cast, was der Skeptiker fand, welche Etappen).
## Sonderfall: „IDEE PRUEFEN" (kein Projektstart)
Steht im Auftrag die Zeile **`AUFTRAGS-ART: IDEE PRUEFEN`**, dann will der Commander die Idee nur
DURCHDACHT haben — er hat sich NICHT entschieden, sie zu bauen. Dann gilt abweichend:
- Schritt 1 (Konzept haerten) laeuft wie beschrieben, aber mit **Produkt-Blick**: Was ist es, fuer
wen, was gibt es schon, kleinster sinnvoller Wurf, was spricht DAGEGEN. Rollen-Cast entsprechend
(nicht nur Entwickler-Rollen).
- Schritt 2 (Repo anlegen) wie gehabt.
- Schritt 3 schreibt **NUR `KONZEPT.md` + ein knappes `README.md`** — KEINE `ROADMAP.md`, KEINE
`AGENTS.md`, KEIN `SAVEPOINT.md`, KEIN `.aiexclude`, kein Geruest. Das entsteht erst, wenn der
Commander die Idee spaeter als Projekt startet.
- Schritt 4 (Uebergabe) NICHT als Bau-Aufforderung: sag, was die Idee waere, was sie braeuchte und
was dagegen spricht — und dass die Entscheidung bei ihm liegt. Kein „oeffne in Zed und bau".
## Eiserne Regeln (nicht verhandelbar)
1. **Du baust KEINEN Code.** Kein Gerüst, keine `package.json`, keine Quelldateien. Nur die
Doku-Dateien aus Schritt 3. Wer Code schreibt, hat die Aufgabe verfehlt.
2. **Fremde Repos sind TABU:** `~/mission-control-v2` (MC2) und `~/lucy` NIEMALS klonen, anfassen
oder verwechseln. Du arbeitest ausschließlich im **neu angelegten** Projekt-Repo. (Wenn im
Auftrag ein bestehendes Repo als Vorbild genannt ist, nur LESEN, nie hineinschreiben.)
3. **Jede Rollen-Stimme des Konzepts kommt aus `worker.sh` an heavy** — nie selbst ausgedacht.
4. **Kein `git init`, kein Shallow-Clone.** Immer voll klonen (Credentials in `~/.git-credentials`).
5. **TABU-Zonen:** approvals/Tokens/ufw/Security-Configs, `~/.hermes/config.yaml`, systemd-Units.
Braucht der Auftrag so etwas → `kanban_block` mit Begründung.
6. **Festfahren-Stopp:** Bleibt das Konzept nach den Runden mit echten Blockern offen (widersprüchliche
Ziele, fehlende Entscheidung des Commanders) → `kanban_block` mit `--kind needs_input` und der
konkreten Frage. NICHT raten, NICHT denselben Schritt stur wiederholen (das löst die No-Progress-
Bremse aus). Beim zweiten Fehlversuch die Diagnose VARIIEREN, nicht den Befehl wiederholen.
@@ -1,4 +1,4 @@
import{c as A,Y as P,l as B,b as M,u as D,r as z,j as e,Z as T,e as a,$ as g,a0 as b,a1 as W,x as f,a2 as j,W as G,X as I,C as N,g as y,q as i}from"./index-uJ3p1Qu4.js";/** import{c as A,Y as P,l as B,b as M,u as D,r as z,j as e,Z as T,e as a,$ as g,a0 as b,a1 as W,x as f,a2 as j,W as G,X as I,C as N,g as y,q as i}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
import{c as m,ag as S,r as c,j as e,ah as z,L as g,U as M,ai as C,ad as D,aj as A,ak as B,al as Z,e as E,am as L,u as R,b as q,g as k,q as T}from"./index-uJ3p1Qu4.js";import{R as j}from"./rotate-ccw-q416APBm.js";/** import{c as m,ag as S,r as c,j as e,ah as z,L as g,U as M,ai as C,ad as D,aj as A,ak as B,al as Z,e as E,am as L,u as R,b as q,g as k,q as T}from"./index-COnX1F3c.js";import{R as j}from"./rotate-ccw-D7EV8OC-.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as v,r as c,I,J as A,j as e,K as h,x as B,B as H,D as E,M as z,e as M,L as T,N as F,C as K}from"./index-uJ3p1Qu4.js";import{F as O}from"./folder-open-IdJQ7pF0.js";import{C as R}from"./circle-x-jdkqdVXY.js";import{C as W}from"./copy-CEkeH97d.js";/** import{c as v,r as c,I,J as A,j as e,K as h,x as B,B as H,D as E,M as z,e as M,L as T,N as F,C as K}from"./index-COnX1F3c.js";import{F as O}from"./folder-open-D11aH3_B.js";import{C as R}from"./circle-x-CWEf5uGH.js";import{C as W}from"./copy-ByBnpOno.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as h,an as b,r as i,j as e,L as g,ao as f,a2 as j,U as k,e as o,D as N,M as v,N as w,g as y}from"./index-uJ3p1Qu4.js";import{B as S}from"./book-open-BDFZcDMQ.js";import{C as z}from"./circle-x-jdkqdVXY.js";/** import{c as h,an as b,r as i,j as e,L as g,ao as f,a2 as j,U as k,e as o,D as N,M as v,N as w,g as y}from"./index-COnX1F3c.js";import{B as S}from"./book-open-QwkqREuA.js";import{C as z}from"./circle-x-CWEf5uGH.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
import{c as p,j as e,r as M,x as C,a6 as z,a7 as k,a8 as y,a0 as v,W as L,a9 as G,a2 as T,e as f,U as D}from"./index-uJ3p1Qu4.js";import{B as w}from"./book-open-BDFZcDMQ.js";import{a as N,L as B,C as P,Z as E}from"./zap-2_GolHYp.js";import{L as R}from"./layers-C9M_U8b5.js";import{L as I}from"./lightbulb-Bcf6WKNO.js";/** import{c as p,j as e,r as M,x as C,a6 as z,a7 as k,a8 as y,a0 as v,W as L,a9 as G,a2 as T,e as f,U as D}from"./index-COnX1F3c.js";import{B as w}from"./book-open-QwkqREuA.js";import{a as N,L as B,C as P,Z as E}from"./zap-CQVrezAh.js";import{L as R}from"./layers-C33RgPOq.js";import{L as I}from"./lightbulb-B5Y1uNTX.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1 +1 @@
import{Y as b,u as f,$ as h,r as d,j as e,e as c,Z as g,T as p,a3 as j,a4 as N,g as v,a5 as w,q as x}from"./index-uJ3p1Qu4.js";function y(){const{data:s}=b(),m=f(),r=s!=null&&s.box_console_url?h(s.box_console_url):void 0,a=s==null?void 0:s.box_console_reachable,[l,o]=d.useState(!1),[i,n]=d.useState("");async function u(){o(!0),n("");try{const t=await v("/api/maintenance/restart",{method:"POST",body:JSON.stringify({service:"box-console"})});n(t.ok?"Neu gestartet — einen Moment, dann lädt das Terminal.":`Fehlgeschlagen: ${t.err||"Unbekannter Fehler"}`),w(m,x.agentStatus,x.services)}catch(t){n(`Fehlgeschlagen: ${(t==null?void 0:t.message)||t}`)}finally{o(!1)}}return e.jsxs("div",{className:"flex h-full flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Konsole"}),e.jsx("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:"Direkte Shell auf der Box — wie ein SSH-Fenster, mitten im Browser."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground",children:[e.jsx("span",{className:c("h-2 w-2 rounded-full",a?"bg-emerald-500 animate-pulse":"bg-amber-500")}),a?"online":"offline"]}),r&&e.jsxs("a",{href:r,target:"_blank",rel:"noopener",className:"flex h-8 items-center gap-1.5 rounded-lg border border-border/60 bg-background/20 px-3 text-xs font-semibold text-muted-foreground transition-all hover:border-primary/50 hover:text-foreground",children:[e.jsx(g,{className:"h-3.5 w-3.5"})," In neuem Tab"]})]})]}),r?e.jsxs("div",{className:"relative min-h-[58vh] flex-1 overflow-hidden rounded-2xl border border-border/60 bg-black/50 shadow-lg shadow-black/25",children:[a===!1&&e.jsxs("div",{className:"absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 bg-black/70 text-center",children:[e.jsx(p,{className:"h-8 w-8 text-amber-400"}),e.jsx("div",{className:"text-sm font-semibold text-amber-300",children:"Konsole nicht erreichbar"}),e.jsxs("p",{className:"max-w-sm text-[11px] leading-normal text-muted-foreground",children:["Der Terminal-Dienst (",e.jsx("code",{className:"font-mono text-primary",children:"box-console"}),") läuft gerade nicht."]}),e.jsxs("button",{onClick:u,disabled:l,className:"flex h-9 items-center gap-1.5 rounded-lg border border-amber-500/40 bg-amber-500/10 px-4 text-[11px] font-bold uppercase tracking-wide text-amber-300 transition-all hover:bg-amber-500/20 cursor-pointer disabled:opacity-50",children:[e.jsx(j,{className:c("h-3.5 w-3.5",l&&"animate-spin")})," Dienst neu starten"]}),i&&e.jsx("p",{className:"max-w-sm text-[11px] text-muted-foreground",children:i})]}),e.jsx("iframe",{src:r,title:"Box-Konsole",className:"h-full w-full border-0",style:{minHeight:"58vh"}})]}):e.jsxs("div",{className:"flex min-h-[58vh] flex-1 items-center justify-center rounded-2xl border border-border/60 bg-background/20 text-xs text-muted-foreground",children:[e.jsx(N,{className:"mr-2 h-4 w-4"})," Lade Konsole…"]})]})}export{y as KonsoleView}; import{Y as b,u as f,$ as h,r as d,j as e,e as c,Z as g,T as p,a3 as j,a4 as N,g as v,a5 as w,q as x}from"./index-COnX1F3c.js";function y(){const{data:s}=b(),m=f(),r=s!=null&&s.box_console_url?h(s.box_console_url):void 0,a=s==null?void 0:s.box_console_reachable,[l,o]=d.useState(!1),[i,n]=d.useState("");async function u(){o(!0),n("");try{const t=await v("/api/maintenance/restart",{method:"POST",body:JSON.stringify({service:"box-console"})});n(t.ok?"Neu gestartet — einen Moment, dann lädt das Terminal.":`Fehlgeschlagen: ${t.err||"Unbekannter Fehler"}`),w(m,x.agentStatus,x.services)}catch(t){n(`Fehlgeschlagen: ${(t==null?void 0:t.message)||t}`)}finally{o(!1)}}return e.jsxs("div",{className:"flex h-full flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Konsole"}),e.jsx("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:"Direkte Shell auf der Box — wie ein SSH-Fenster, mitten im Browser."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground",children:[e.jsx("span",{className:c("h-2 w-2 rounded-full",a?"bg-emerald-500 animate-pulse":"bg-amber-500")}),a?"online":"offline"]}),r&&e.jsxs("a",{href:r,target:"_blank",rel:"noopener",className:"flex h-8 items-center gap-1.5 rounded-lg border border-border/60 bg-background/20 px-3 text-xs font-semibold text-muted-foreground transition-all hover:border-primary/50 hover:text-foreground",children:[e.jsx(g,{className:"h-3.5 w-3.5"})," In neuem Tab"]})]})]}),r?e.jsxs("div",{className:"relative min-h-[58vh] flex-1 overflow-hidden rounded-2xl border border-border/60 bg-black/50 shadow-lg shadow-black/25",children:[a===!1&&e.jsxs("div",{className:"absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 bg-black/70 text-center",children:[e.jsx(p,{className:"h-8 w-8 text-amber-400"}),e.jsx("div",{className:"text-sm font-semibold text-amber-300",children:"Konsole nicht erreichbar"}),e.jsxs("p",{className:"max-w-sm text-[11px] leading-normal text-muted-foreground",children:["Der Terminal-Dienst (",e.jsx("code",{className:"font-mono text-primary",children:"box-console"}),") läuft gerade nicht."]}),e.jsxs("button",{onClick:u,disabled:l,className:"flex h-9 items-center gap-1.5 rounded-lg border border-amber-500/40 bg-amber-500/10 px-4 text-[11px] font-bold uppercase tracking-wide text-amber-300 transition-all hover:bg-amber-500/20 cursor-pointer disabled:opacity-50",children:[e.jsx(j,{className:c("h-3.5 w-3.5",l&&"animate-spin")})," Dienst neu starten"]}),i&&e.jsx("p",{className:"max-w-sm text-[11px] text-muted-foreground",children:i})]}),e.jsx("iframe",{src:r,title:"Box-Konsole",className:"h-full w-full border-0",style:{minHeight:"58vh"}})]}):e.jsxs("div",{className:"flex min-h-[58vh] flex-1 items-center justify-center rounded-2xl border border-border/60 bg-background/20 text-xs text-muted-foreground",children:[e.jsx(N,{className:"mr-2 h-4 w-4"})," Lade Konsole…"]})]})}export{y as KonsoleView};
@@ -1,5 +1,5 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/GraphView-BBynotqS.js","assets/index-uJ3p1Qu4.js","assets/index-ivTj_-9_.css"])))=>i.map(i=>d[i]); const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/GraphView-sP7g3iZD.js","assets/index-COnX1F3c.js","assets/index-1dwQ_lxY.css"])))=>i.map(i=>d[i]);
var je=Object.defineProperty;var ke=(d,i,c)=>i in d?je(d,i,{enumerable:!0,configurable:!0,writable:!0,value:c}):d[i]=c;var J=(d,i,c)=>ke(d,typeof i!="symbol"?i+"":i,c);import{c as h,r as s,j as e,u as ve,b as Ne,O as W,Q as Se,C as X,R as Ce,S as Ee,P as Me,U as O,e as x,V as ze,W as De,X as Z,A as Y,_ as Oe,g as j}from"./index-uJ3p1Qu4.js";import{C as ee}from"./copy-CEkeH97d.js";import{S as _e}from"./send-Cdy3ysbw.js";import{B as Ge}from"./book-open-BDFZcDMQ.js";/** var je=Object.defineProperty;var ke=(d,i,c)=>i in d?je(d,i,{enumerable:!0,configurable:!0,writable:!0,value:c}):d[i]=c;var J=(d,i,c)=>ke(d,typeof i!="symbol"?i+"":i,c);import{c as h,r as s,j as e,u as ve,b as Ne,O as W,Q as Se,C as X,R as Ce,S as Ee,P as Me,U as O,e as x,V as ze,W as De,X as Z,A as Y,_ as Oe,g as j}from"./index-COnX1F3c.js";import{C as ee}from"./copy-ByBnpOno.js";import{S as _e}from"./send-Bifs1ZE8.js";import{B as Ge}from"./book-open-QwkqREuA.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -34,7 +34,7 @@ var je=Object.defineProperty;var ke=(d,i,c)=>i in d?je(d,i,{enumerable:!0,config
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree. * See the LICENSE file in the root directory of this source tree.
*/const Pe=h("User",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]);class te extends s.Component{constructor(){super(...arguments);J(this,"state",{error:null})}static getDerivedStateFromError(c){return{error:c}}render(){return this.state.error?e.jsxs("div",{className:"h-[480px] rounded-2xl border border-red-500/20 bg-red-500/5 p-6 text-xs text-red-400 overflow-auto",children:[e.jsx("div",{className:"font-semibold mb-2",children:"Graph konnte nicht gerendert werden"}),e.jsx("pre",{className:"whitespace-pre-wrap break-words text-[11px] leading-relaxed",children:this.state.error.message})]}):this.props.children}}const se=s.lazy(()=>Oe(()=>import("./GraphView-BBynotqS.js"),__vite__mapDeps([0,1,2])).then(d=>({default:d.GraphView}))),k=["identity","knowledge","rules","events"],v=new Set(["auto","agent","hermes"]),N={identity:{label:"Identität",icon:Pe,bg:"bg-cyan-500/10",text:"text-cyan-400"},knowledge:{label:"Wissen",icon:De,bg:"bg-indigo-500/10",text:"text-indigo-400"},rules:{label:"Regeln",icon:Le,bg:"bg-violet-500/10",text:"text-violet-400"},events:{label:"Ereignisse",icon:ze,bg:"bg-amber-500/10",text:"text-amber-400"}},ne={label:"Gedächtnis",icon:Ge,text:"text-muted-foreground"},Re={identity:"border-l-cyan-500/80",knowledge:"border-l-indigo-500/80",rules:"border-l-violet-500/80",events:"border-l-amber-500/80"},_={identity:"#00f5ff",knowledge:"#3b82f6",rules:"#d946ef",events:"#fbbf24"},ae=`Hi Hermes! Lass uns ein kurzes Onboarding machen, damit du dich künftig an mich erinnerst. Stell mir nacheinander ein paar kurze Fragen zu: */const Pe=h("User",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]);class te extends s.Component{constructor(){super(...arguments);J(this,"state",{error:null})}static getDerivedStateFromError(c){return{error:c}}render(){return this.state.error?e.jsxs("div",{className:"h-[480px] rounded-2xl border border-red-500/20 bg-red-500/5 p-6 text-xs text-red-400 overflow-auto",children:[e.jsx("div",{className:"font-semibold mb-2",children:"Graph konnte nicht gerendert werden"}),e.jsx("pre",{className:"whitespace-pre-wrap break-words text-[11px] leading-relaxed",children:this.state.error.message})]}):this.props.children}}const se=s.lazy(()=>Oe(()=>import("./GraphView-sP7g3iZD.js"),__vite__mapDeps([0,1,2])).then(d=>({default:d.GraphView}))),k=["identity","knowledge","rules","events"],v=new Set(["auto","agent","hermes"]),N={identity:{label:"Identität",icon:Pe,bg:"bg-cyan-500/10",text:"text-cyan-400"},knowledge:{label:"Wissen",icon:De,bg:"bg-indigo-500/10",text:"text-indigo-400"},rules:{label:"Regeln",icon:Le,bg:"bg-violet-500/10",text:"text-violet-400"},events:{label:"Ereignisse",icon:ze,bg:"bg-amber-500/10",text:"text-amber-400"}},ne={label:"Gedächtnis",icon:Ge,text:"text-muted-foreground"},Re={identity:"border-l-cyan-500/80",knowledge:"border-l-indigo-500/80",rules:"border-l-violet-500/80",events:"border-l-amber-500/80"},_={identity:"#00f5ff",knowledge:"#3b82f6",rules:"#d946ef",events:"#fbbf24"},ae=`Hi Hermes! Lass uns ein kurzes Onboarding machen, damit du dich künftig an mich erinnerst. Stell mir nacheinander ein paar kurze Fragen zu:
1) wer ich bin und woran ich gerade arbeite, 1) wer ich bin und woran ich gerade arbeite,
2) wie ich angesprochen werden möchte, 2) wie ich angesprochen werden möchte,
3) meine bevorzugten Tools, Sprachen und Arbeitsweise, 3) meine bevorzugten Tools, Sprachen und Arbeitsweise,
@@ -1,4 +1,4 @@
import{c as E,u as oe,a as Fe,b as ge,j as e,f as ue,d as Re,e as w,g as K,q as P,h as Ie,r as N,C as Y,L as Oe,i as Pe,B as le,k as Te,E as Be,l as de,m as Ge,n as $e,o as He,p as ee,X as pe,P as Qe,H as fe,T as re,s as Ue,t as Ve,v as V,w as We,S as ye,x as Ze,y as Je,z as Xe,A as Ye,D as De,F as et,G as tt}from"./index-uJ3p1Qu4.js";import{C as rt}from"./code-xml-4H2sGJA7.js";import{R as st}from"./rotate-ccw-q416APBm.js";import{C as he,Z as ie,L as nt,a as at}from"./zap-2_GolHYp.js";import{L as ot}from"./layers-C9M_U8b5.js";/** import{c as E,u as oe,a as Fe,b as ge,j as e,f as ue,d as Re,e as w,g as K,q as P,h as Ie,r as N,C as Y,L as Oe,i as Pe,B as le,k as Te,E as Be,l as de,m as Ge,n as $e,o as He,p as ee,X as pe,P as Qe,H as fe,T as re,s as Ue,t as Ve,v as V,w as We,S as ye,x as Ze,y as Je,z as Xe,A as Ye,D as De,F as et,G as tt}from"./index-COnX1F3c.js";import{C as rt}from"./code-xml-DRA0356h.js";import{R as st}from"./rotate-ccw-D7EV8OC-.js";import{C as he,Z as ie,L as nt,a as at}from"./zap-CQVrezAh.js";import{L as ot}from"./layers-C33RgPOq.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{ap as y,r as x,g as L,j as e,L as v,S,ae as W,U as C,e as w,aq as E}from"./index-uJ3p1Qu4.js";import{F as M}from"./folder-open-IdJQ7pF0.js";const D={"":"Allgemein",traeume:"Träume",muster:"Muster","skill-kandidaten":"Skill-Kandidaten","skill-kandidaten/beauftragt":"Skill-Kandidaten · beauftragt","skill-kandidaten/verworfen":"Skill-Kandidaten · verworfen"};function T(){const{data:o,isLoading:h}=y(),[l,f]=x.useState(null),[d,r]=x.useState(null),[u,i]=x.useState(!1),[a,p]=x.useState(""),t=x.useMemo(()=>(o==null?void 0:o.files)??[],[o]),m=x.useMemo(()=>{const s=new Map;for(const n of t)s.set(n.name.toLowerCase(),n.path);return s},[t]),g=x.useMemo(()=>{if(!a.trim())return t;const s=a.toLowerCase();return t.filter(n=>n.title.toLowerCase().includes(s)||n.path.toLowerCase().includes(s))},[t,a]),b=x.useMemo(()=>{const s=[];for(const n of g){const c=s.find(k=>k.dir===n.dir);c?c.files.push(n):s.push({dir:n.dir,files:[n]})}return s.sort((n,c)=>n.dir===""?-1:c.dir===""?1:n.dir.localeCompare(c.dir))},[g]);x.useEffect(()=>{if(!l&&t.length){const s=t.find(n=>n.path.toLowerCase()==="index.md");f((s==null?void 0:s.path)??t[0].path)}},[t,l]),x.useEffect(()=>{l&&(i(!0),L(`/api/wissen/datei?pfad=${encodeURIComponent(l)}`).then(r).catch(()=>r({path:l,content:"*(Notiz nicht ladbar)*",mtime:0})).finally(()=>i(!1)))},[l]);const j=s=>{const n=m.get(s.toLowerCase());n&&f(n)};return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Wissen"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Was sich die Box nachts erschließt — Traum-Notizen, Muster und Skill-Ideen aus dem Wissens-Vault, verlinkt wie ein Wiki."})]}),o&&!o.available&&e.jsx("div",{className:"rounded-2xl border border-amber-500/30 bg-amber-500/5 p-4 text-xs text-amber-300",children:"Der Wissens-Vault liegt auf der Box (~/wissens-vault) — im lokalen Dev-Modus nicht verfügbar."}),h&&e.jsxs("div",{className:"flex items-center gap-2 rounded-2xl border border-border/60 bg-card/30 p-6 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Vault wird geladen …"]}),(o==null?void 0:o.available)&&t.length===0&&e.jsx("div",{className:"rounded-2xl border border-dashed border-border/60 bg-card/20 p-8 text-center text-xs text-muted-foreground",children:"Noch keine Notizen. Der nächtliche Traum (03:15) legt sie an — morgen früh steht hier die erste."}),t.length>0&&e.jsxs("div",{className:"flex flex-col gap-4 lg:flex-row",children:[e.jsxs("aside",{className:"w-full shrink-0 space-y-3 lg:w-72",children:[e.jsxs("div",{className:"relative",children:[e.jsx("input",{value:a,onChange:s=>p(s.target.value),type:"search",placeholder:"Notizen durchsuchen…","aria-label":"Notizen durchsuchen",className:"h-9 w-full rounded-lg border border-border/60 bg-card/45 pl-8 pr-3 text-xs text-foreground outline-none focus:ring-1 focus:ring-primary/50"}),e.jsx(S,{className:"absolute left-2.5 top-2.5 h-3.5 w-3.5 text-muted-foreground"})]}),e.jsx("div",{className:"max-h-[70vh] space-y-3 overflow-y-auto pr-1 scrollbar-thin",children:b.map(({dir:s,files:n})=>e.jsxs("div",{children:[e.jsxs("p",{className:"mb-1 flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider text-muted-foreground/60",children:[e.jsx(M,{className:"h-3 w-3"})," ",D[s]??s]}),e.jsx("div",{className:"space-y-0.5",children:n.map(c=>e.jsxs("button",{onClick:()=>f(c.path),className:w("flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left text-xs transition-all cursor-pointer",l===c.path?"bg-primary/15 text-primary":"text-muted-foreground hover:bg-accent hover:text-foreground"),children:[e.jsx(W,{className:"h-3.5 w-3.5 shrink-0"}),e.jsx("span",{className:"truncate",title:c.title,children:c.name}),c.neu&&e.jsxs("span",{className:"ml-auto flex items-center gap-0.5 rounded bg-violet-500/15 px-1 py-0.5 text-[8px] font-bold uppercase text-violet-300",children:[e.jsx(C,{className:"h-2.5 w-2.5"}),"neu"]})]},c.path))})]},s||"__root"))})]}),e.jsx("div",{className:"min-w-0 flex-1 mc-card p-5",children:u?e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Notiz wird geladen …"]}):d?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between border-b border-border/40 pb-2",children:[e.jsxs("span",{className:"flex items-center gap-1.5 font-mono text-[11px] text-muted-foreground",children:[e.jsx(E,{className:"h-3.5 w-3.5"})," ",d.path]}),d.mtime>0&&e.jsxs("span",{className:"text-[10px] text-muted-foreground/60",children:["Stand ",new Date(d.mtime*1e3).toLocaleString("de-DE",{day:"2-digit",month:"2-digit",hour:"2-digit",minute:"2-digit"})]})]}),e.jsx(z,{text:d.content,onWikiLink:j,known:m})]}):null})]})]})}function z({text:o,onWikiLink:h,known:l}){const f=o.split(` import{ap as y,r as x,g as L,j as e,L as v,S,ae as W,U as C,e as w,aq as E}from"./index-COnX1F3c.js";import{F as M}from"./folder-open-D11aH3_B.js";const D={"":"Allgemein",traeume:"Träume",muster:"Muster","skill-kandidaten":"Skill-Kandidaten","skill-kandidaten/beauftragt":"Skill-Kandidaten · beauftragt","skill-kandidaten/verworfen":"Skill-Kandidaten · verworfen"};function T(){const{data:o,isLoading:h}=y(),[l,f]=x.useState(null),[d,r]=x.useState(null),[u,i]=x.useState(!1),[a,p]=x.useState(""),t=x.useMemo(()=>(o==null?void 0:o.files)??[],[o]),m=x.useMemo(()=>{const s=new Map;for(const n of t)s.set(n.name.toLowerCase(),n.path);return s},[t]),g=x.useMemo(()=>{if(!a.trim())return t;const s=a.toLowerCase();return t.filter(n=>n.title.toLowerCase().includes(s)||n.path.toLowerCase().includes(s))},[t,a]),b=x.useMemo(()=>{const s=[];for(const n of g){const c=s.find(k=>k.dir===n.dir);c?c.files.push(n):s.push({dir:n.dir,files:[n]})}return s.sort((n,c)=>n.dir===""?-1:c.dir===""?1:n.dir.localeCompare(c.dir))},[g]);x.useEffect(()=>{if(!l&&t.length){const s=t.find(n=>n.path.toLowerCase()==="index.md");f((s==null?void 0:s.path)??t[0].path)}},[t,l]),x.useEffect(()=>{l&&(i(!0),L(`/api/wissen/datei?pfad=${encodeURIComponent(l)}`).then(r).catch(()=>r({path:l,content:"*(Notiz nicht ladbar)*",mtime:0})).finally(()=>i(!1)))},[l]);const j=s=>{const n=m.get(s.toLowerCase());n&&f(n)};return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Wissen"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Was sich die Box nachts erschließt — Traum-Notizen, Muster und Skill-Ideen aus dem Wissens-Vault, verlinkt wie ein Wiki."})]}),o&&!o.available&&e.jsx("div",{className:"rounded-2xl border border-amber-500/30 bg-amber-500/5 p-4 text-xs text-amber-300",children:"Der Wissens-Vault liegt auf der Box (~/wissens-vault) — im lokalen Dev-Modus nicht verfügbar."}),h&&e.jsxs("div",{className:"flex items-center gap-2 rounded-2xl border border-border/60 bg-card/30 p-6 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Vault wird geladen …"]}),(o==null?void 0:o.available)&&t.length===0&&e.jsx("div",{className:"rounded-2xl border border-dashed border-border/60 bg-card/20 p-8 text-center text-xs text-muted-foreground",children:"Noch keine Notizen. Der nächtliche Traum (03:15) legt sie an — morgen früh steht hier die erste."}),t.length>0&&e.jsxs("div",{className:"flex flex-col gap-4 lg:flex-row",children:[e.jsxs("aside",{className:"w-full shrink-0 space-y-3 lg:w-72",children:[e.jsxs("div",{className:"relative",children:[e.jsx("input",{value:a,onChange:s=>p(s.target.value),type:"search",placeholder:"Notizen durchsuchen…","aria-label":"Notizen durchsuchen",className:"h-9 w-full rounded-lg border border-border/60 bg-card/45 pl-8 pr-3 text-xs text-foreground outline-none focus:ring-1 focus:ring-primary/50"}),e.jsx(S,{className:"absolute left-2.5 top-2.5 h-3.5 w-3.5 text-muted-foreground"})]}),e.jsx("div",{className:"max-h-[70vh] space-y-3 overflow-y-auto pr-1 scrollbar-thin",children:b.map(({dir:s,files:n})=>e.jsxs("div",{children:[e.jsxs("p",{className:"mb-1 flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider text-muted-foreground/60",children:[e.jsx(M,{className:"h-3 w-3"})," ",D[s]??s]}),e.jsx("div",{className:"space-y-0.5",children:n.map(c=>e.jsxs("button",{onClick:()=>f(c.path),className:w("flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left text-xs transition-all cursor-pointer",l===c.path?"bg-primary/15 text-primary":"text-muted-foreground hover:bg-accent hover:text-foreground"),children:[e.jsx(W,{className:"h-3.5 w-3.5 shrink-0"}),e.jsx("span",{className:"truncate",title:c.title,children:c.name}),c.neu&&e.jsxs("span",{className:"ml-auto flex items-center gap-0.5 rounded bg-violet-500/15 px-1 py-0.5 text-[8px] font-bold uppercase text-violet-300",children:[e.jsx(C,{className:"h-2.5 w-2.5"}),"neu"]})]},c.path))})]},s||"__root"))})]}),e.jsx("div",{className:"min-w-0 flex-1 mc-card p-5",children:u?e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Notiz wird geladen …"]}):d?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between border-b border-border/40 pb-2",children:[e.jsxs("span",{className:"flex items-center gap-1.5 font-mono text-[11px] text-muted-foreground",children:[e.jsx(E,{className:"h-3.5 w-3.5"})," ",d.path]}),d.mtime>0&&e.jsxs("span",{className:"text-[10px] text-muted-foreground/60",children:["Stand ",new Date(d.mtime*1e3).toLocaleString("de-DE",{day:"2-digit",month:"2-digit",hour:"2-digit",minute:"2-digit"})]})]}),e.jsx(z,{text:d.content,onWikiLink:j,known:m})]}):null})]})]})}function z({text:o,onWikiLink:h,known:l}){const f=o.split(`
`),d=[];let r=[],u=null;const i=a=>{r.length&&(d.push(e.jsx("ul",{className:"mb-3 ml-4 list-disc space-y-1",children:r},a)),r=[])};return f.forEach((a,p)=>{const t=`l${p}`;if(u!==null){a.trimEnd()==="```"?(d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px] leading-relaxed text-foreground/85",children:u.join(` `),d=[];let r=[],u=null;const i=a=>{r.length&&(d.push(e.jsx("ul",{className:"mb-3 ml-4 list-disc space-y-1",children:r},a)),r=[])};return f.forEach((a,p)=>{const t=`l${p}`;if(u!==null){a.trimEnd()==="```"?(d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px] leading-relaxed text-foreground/85",children:u.join(`
`)},t)),u=null):u.push(a);return}if(a.trimStart().startsWith("```")){i(t),u=[];return}const m=a.trimEnd();if(!m.trim()){i(t);return}const g=m.match(/^(#{1,4})\s+(.*)$/);if(g){i(t);const j=g[1].length,s=j===1?"text-lg font-bold mt-1 mb-3":j===2?"text-base font-bold mt-4 mb-2":"text-sm font-bold mt-3 mb-1.5";d.push(e.jsx("p",{className:w(s,"font-space text-foreground"),children:N(g[2],h,l,t)},t));return}const b=m.match(/^\s*[-*•]\s+(.*)$/);if(b){r.push(e.jsx("li",{className:"text-xs leading-relaxed text-foreground/85",children:N(b[1],h,l,t)},t));return}i(t),d.push(e.jsx("p",{className:"mb-2 text-xs leading-relaxed text-foreground/85",children:N(m,h,l,t)},t))}),i("end"),u!==null&&d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px]",children:u.join(` `)},t)),u=null):u.push(a);return}if(a.trimStart().startsWith("```")){i(t),u=[];return}const m=a.trimEnd();if(!m.trim()){i(t);return}const g=m.match(/^(#{1,4})\s+(.*)$/);if(g){i(t);const j=g[1].length,s=j===1?"text-lg font-bold mt-1 mb-3":j===2?"text-base font-bold mt-4 mb-2":"text-sm font-bold mt-3 mb-1.5";d.push(e.jsx("p",{className:w(s,"font-space text-foreground"),children:N(g[2],h,l,t)},t));return}const b=m.match(/^\s*[-*•]\s+(.*)$/);if(b){r.push(e.jsx("li",{className:"text-xs leading-relaxed text-foreground/85",children:N(b[1],h,l,t)},t));return}i(t),d.push(e.jsx("p",{className:"mb-2 text-xs leading-relaxed text-foreground/85",children:N(m,h,l,t)},t))}),i("end"),u!==null&&d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px]",children:u.join(`
`)},"code-end")),e.jsx("div",{className:"max-w-3xl",children:d})}function N(o,h,l,f){return o.split(/(\[\[[^\]]+\]\]|\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g).map((r,u)=>{const i=`${f}-${u}`,a=r.match(/^\[\[([^\]|]+)(?:\|([^\]]+))?\]\]$/);if(a){const p=a[1].trim(),t=(a[2]??a[1]).trim();return l.has(p.toLowerCase())?e.jsx("button",{onClick:()=>h(p),className:"rounded bg-primary/10 px-1 text-primary underline decoration-primary/40 underline-offset-2 hover:bg-primary/20 cursor-pointer",children:t},i):e.jsx("span",{className:"rounded bg-background/40 px-1 text-muted-foreground",title:"Notiz existiert (noch) nicht",children:t},i)}return r.startsWith("**")&&r.endsWith("**")?e.jsx("b",{className:"font-semibold text-foreground",children:r.slice(2,-2)},i):r.startsWith("*")&&r.endsWith("*")&&r.length>2?e.jsx("i",{children:r.slice(1,-1)},i):r.startsWith("`")&&r.endsWith("`")?e.jsx("code",{className:"rounded bg-background/50 px-1 font-mono text-[11px] text-teal-300",children:r.slice(1,-1)},i):e.jsx("span",{children:r},i)})}export{T as WissenView}; `)},"code-end")),e.jsx("div",{className:"max-w-3xl",children:d})}function N(o,h,l,f){return o.split(/(\[\[[^\]]+\]\]|\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g).map((r,u)=>{const i=`${f}-${u}`,a=r.match(/^\[\[([^\]|]+)(?:\|([^\]]+))?\]\]$/);if(a){const p=a[1].trim(),t=(a[2]??a[1]).trim();return l.has(p.toLowerCase())?e.jsx("button",{onClick:()=>h(p),className:"rounded bg-primary/10 px-1 text-primary underline decoration-primary/40 underline-offset-2 hover:bg-primary/20 cursor-pointer",children:t},i):e.jsx("span",{className:"rounded bg-background/40 px-1 text-muted-foreground",title:"Notiz existiert (noch) nicht",children:t},i)}return r.startsWith("**")&&r.endsWith("**")?e.jsx("b",{className:"font-semibold text-foreground",children:r.slice(2,-2)},i):r.startsWith("*")&&r.endsWith("*")&&r.length>2?e.jsx("i",{children:r.slice(1,-1)},i):r.startsWith("`")&&r.endsWith("`")?e.jsx("code",{className:"rounded bg-background/50 px-1 font-mono text-[11px] text-teal-300",children:r.slice(1,-1)},i):e.jsx("span",{children:r},i)})}export{T as WissenView};
@@ -1,4 +1,4 @@
import{c as a}from"./index-uJ3p1Qu4.js";/** import{c as a}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c}from"./index-uJ3p1Qu4.js";/** import{c}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as e}from"./index-uJ3p1Qu4.js";/** import{c as e}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c}from"./index-uJ3p1Qu4.js";/** import{c}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as a}from"./index-uJ3p1Qu4.js";/** import{c as a}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
import{c as a}from"./index-uJ3p1Qu4.js";/** import{c as a}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as t}from"./index-uJ3p1Qu4.js";/** import{c as t}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as t}from"./index-uJ3p1Qu4.js";/** import{c as t}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as a}from"./index-uJ3p1Qu4.js";/** import{c as a}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
import{c as a}from"./index-uJ3p1Qu4.js";/** import{c as a}from"./index-COnX1F3c.js";/**
* @license lucide-react v0.460.0 - ISC * @license lucide-react v0.460.0 - ISC
* *
* This source code is licensed under the ISC license. * This source code is licensed under the ISC license.
+2 -2
View File
@@ -7,8 +7,8 @@
<link rel="manifest" href="/manifest.webmanifest" /> <link rel="manifest" href="/manifest.webmanifest" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>Mission Control 2.0</title> <title>Mission Control 2.0</title>
<script type="module" crossorigin src="/assets/index-uJ3p1Qu4.js"></script> <script type="module" crossorigin src="/assets/index-COnX1F3c.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-ivTj_-9_.css"> <link rel="stylesheet" crossorigin href="/assets/index-1dwQ_lxY.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+32 -8
View File
@@ -164,9 +164,11 @@ function IdeenSection() {
const qc = useQueryClient() const qc = useQueryClient()
const { showAlert, showConfirm, dialogElement } = useDialog() const { showAlert, showConfirm, dialogElement } = useDialog()
const [text, setText] = useState("") const [text, setText] = useState("")
// Intake-Modus: Box baut · IDE simpel (schnelles Konzept) · IDE gründlich (volle Kaskade). // Intake-Modus: Box baut · Idee (nur durchdenken) · IDE simpel/gründlich (Projekt vorbereiten).
const [modus, setModus] = useState<"box" | "simpel" | "gruendlich">("box") const [modus, setModus] = useState<"box" | "idee" | "simpel" | "gruendlich">("box")
const isIde = modus !== "box" const isIdee = modus === "idee" // Produkt-Idee prüfen
const isProjekt = modus === "simpel" || modus === "gruendlich" // Projekt für Zed
const isIde = isIdee || isProjekt // beides → projektstart
// Ziel-Plattform des Projekts (nur IDE-Welt): läuft es als LXC-Dienst oder in Docker? // Ziel-Plattform des Projekts (nur IDE-Welt): läuft es als LXC-Dienst oder in Docker?
const [ziel, setZiel] = useState<"lxc" | "docker">("lxc") const [ziel, setZiel] = useState<"lxc" | "docker">("lxc")
const [sending, setSending] = useState(false) const [sending, setSending] = useState(false)
@@ -190,7 +192,13 @@ function IdeenSection() {
// Lange Eingaben: Kurzfassung als Titel, alles als Notiz — der Specifier der Box // Lange Eingaben: Kurzfassung als Titel, alles als Notiz — der Specifier der Box
// macht daraus ohnehin einen sauberen Auftrag. // macht daraus ohnehin einen sauberen Auftrag.
const titel = t.length > 160 ? t.slice(0, 157) + "…" : t const titel = t.length > 160 ? t.slice(0, 157) + "…" : t
await api("/api/ideen", { method: "POST", body: JSON.stringify({ titel, notiz: t.length > 160 ? t : "", welt: isIde ? "ide" : "box", tiefe: isIde ? modus : "", ziel: isIde ? ziel : "" }) }) await api("/api/ideen", { method: "POST", body: JSON.stringify({
titel, notiz: t.length > 160 ? t : "",
welt: isIde ? "ide" : "box",
tiefe: isProjekt ? modus : "",
ziel: isProjekt ? ziel : "", // eine Idee braucht noch keine Plattform
art: isIdee ? "idee" : "projekt",
}) })
setText("") setText("")
reload() reload()
} catch (e: any) { } catch (e: any) {
@@ -443,9 +451,10 @@ function IdeenSection() {
className={cn("flex h-9 shrink-0 items-center gap-1.5 rounded-lg border px-3 text-[11px] font-bold uppercase tracking-wide transition-all cursor-pointer disabled:opacity-50", className={cn("flex h-9 shrink-0 items-center gap-1.5 rounded-lg border px-3 text-[11px] font-bold uppercase tracking-wide transition-all cursor-pointer disabled:opacity-50",
modus === "gruendlich" ? "border-amber-500/40 bg-amber-500/10 text-amber-300 hover:bg-amber-500/20" modus === "gruendlich" ? "border-amber-500/40 bg-amber-500/10 text-amber-300 hover:bg-amber-500/20"
: modus === "simpel" ? "border-violet-500/40 bg-violet-500/10 text-violet-300 hover:bg-violet-500/20" : modus === "simpel" ? "border-violet-500/40 bg-violet-500/10 text-violet-300 hover:bg-violet-500/20"
: isIdee ? "border-sky-500/40 bg-sky-500/10 text-sky-300 hover:bg-sky-500/20"
: "border-primary/40 bg-primary/10 text-primary hover:bg-primary/20")}> : "border-primary/40 bg-primary/10 text-primary hover:bg-primary/20")}>
{sending ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : isIde ? <Code2 className="h-3.5 w-3.5" /> : <Send className="h-3.5 w-3.5" />} {sending ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : isIdee ? <Lightbulb className="h-3.5 w-3.5" /> : isProjekt ? <Code2 className="h-3.5 w-3.5" /> : <Send className="h-3.5 w-3.5" />}
{isIde ? "Vorbereiten" : "In die Queue"} {isIdee ? "Durchdenken" : isProjekt ? "Vorbereiten" : "In die Queue"}
</button> </button>
</div> </div>
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
@@ -457,6 +466,13 @@ function IdeenSection() {
modus === "box" ? "bg-primary/15 text-primary" : "text-muted-foreground/60 hover:text-foreground")}> modus === "box" ? "bg-primary/15 text-primary" : "text-muted-foreground/60 hover:text-foreground")}>
<Hammer className="h-3 w-3" /> Box <Hammer className="h-3 w-3" /> Box
</button> </button>
<button
onClick={() => setModus("idee")}
title="Produkt-Idee erst einmal durchdenken lassen: Was ist es, für wen, was gibt es schon, was spricht dagegen? Ergebnis ist ein Konzept — kein Projekt, kein Bau-Druck."
className={cn("flex items-center gap-1 rounded px-2 py-1 text-[10px] font-bold uppercase tracking-wide transition-all cursor-pointer",
modus === "idee" ? "bg-sky-500/15 text-sky-300" : "text-muted-foreground/60 hover:text-foreground")}>
<Lightbulb className="h-3 w-3" /> Idee
</button>
<button <button
onClick={() => setModus("simpel")} onClick={() => setModus("simpel")}
title="IDE-Projekt, schnell vorbereitet: knappes Konzept, wenige Denk-Runden. Für kleine, klar umrissene Sachen." title="IDE-Projekt, schnell vorbereitet: knappes Konzept, wenige Denk-Runden. Für kleine, klar umrissene Sachen."
@@ -473,7 +489,7 @@ function IdeenSection() {
</button> </button>
</div> </div>
</div> </div>
{isIde && ( {isProjekt && (
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<span className="text-[11px] text-muted-foreground/70">Ziel</span> <span className="text-[11px] text-muted-foreground/70">Ziel</span>
<div className="flex rounded-lg border border-border/40 p-0.5"> <div className="flex rounded-lg border border-border/40 p-0.5">
@@ -498,7 +514,15 @@ function IdeenSection() {
</div> </div>
)} )}
<p className="text-[11px] text-muted-foreground"> <p className="text-[11px] text-muted-foreground">
{isIde ? ( {isIdee ? (
<>
<b className="text-sky-300/90">Idee durchdenken:</b> Die Box arbeitet deine Produkt-Idee
mit Produkt-Blick aus was ist es genau, für wen, was gibt es dafür schon, was wäre der
kleinste sinnvolle Wurf und was spricht dagegen. Volle Denk-Kaskade mit Kritiker, Ergebnis
ist <b>nur ein Konzept</b> (kein Gerüst, keine Roadmap, kein Bau-Druck) du liest es hier
und entscheidest danach, ob ein Projekt draus wird.
</>
) : isProjekt ? (
<> <>
<b className={modus === "gruendlich" ? "text-amber-300/90" : "text-violet-300/90"}>IDE-Welt{modus === "gruendlich" ? " · gründlich" : " · simpel"}:</b>{" "} <b className={modus === "gruendlich" ? "text-amber-300/90" : "text-violet-300/90"}>IDE-Welt{modus === "gruendlich" ? " · gründlich" : " · simpel"}:</b>{" "}
Die Box denkt das Konzept durch{modus === "gruendlich" Die Box denkt das Konzept durch{modus === "gruendlich"