Karten-Titel: kurz und an der Wortgrenze statt abgeschnittener Textwueste
Der Commander schreibt seine Ideen roh — ein ganzer Absatz wurde 1:1 zum
Kartentitel und war danach ueberall abgeschnitten ("... und lass uns ueberlegen
wie"). Drei Stellen:
- add_idea(): Zurufe ueber 90 Zeichen bekommen einen kurzen Anzeige-Titel
(erster Satz, sonst Schnitt an der Wortgrenze). Der VOLLE Wortlaut wandert in
den Auftrag, mit Kopfzeile "der Kartentitel ist nur eine Kurzfassung" — sonst
arbeitet der Worker am abgeschnittenen Satz.
- _projekt_titel(): der Gruppenname nahm stur die aelteste Karte und schnitt sie
bei 80 Zeichen mitten im Wort ab. Jetzt gewinnt bei fehlendem gemeinsamen
Praefix der kuerzeste Mitglieds-Titel (die aus einem Konzept abgeleiteten
Karten sind die gepflegten) — Praefixe wie "Idee:" fallen weg, Schnitt an der
Wortgrenze. Aus der ARM-Kette wird so "ARM-UI — Modernes Dashboard fuer
Automatic Ripping Machine" statt des halben Zurufs.
- UI: Tooltip der Zeile zeigt den vollen TITEL statt des Auftragstexts (der
beginnt mit Vorspann-Bausteinen und half beim Lesen nie).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -99,9 +99,27 @@ def _blocker_frage(task_id: str) -> dict | None:
|
||||
return {"frage": frage[:800], "kind": kind}
|
||||
|
||||
|
||||
def _kurz(text: str, max_len: int = 80) -> str:
|
||||
"""Auf max_len kürzen — aber an der WORTGRENZE, nicht mitten im Wort (User 21.07.:
|
||||
„Idee: Recherchiere zu ARM … und lass uns überlegen wie")."""
|
||||
t = " ".join((text or "").split())
|
||||
if len(t) <= max_len:
|
||||
return t
|
||||
schnitt = t[:max_len].rsplit(" ", 1)[0].rstrip(" ,;:–-")
|
||||
return (schnitt or t[:max_len]) + "…"
|
||||
|
||||
|
||||
_TITEL_PRAEFIX_RX = re.compile(r"^\s*(idee|projekt|bitte)\s*[:\-–]?\s*", re.I)
|
||||
|
||||
|
||||
def _projekt_titel(titles: list[str]) -> str:
|
||||
"""Anzeigename einer Karten-Familie: gemeinsamer Titel-Präfix (z. B. „Homelab-Dashboard 2.0"),
|
||||
sonst der Titel der ältesten Karte. Reine Anzeige-Heuristik, nichts hängt davon ab."""
|
||||
sonst der AUFGERÄUMTESTE Mitglieds-Titel. Reine Anzeige-Heuristik, nichts hängt davon ab.
|
||||
|
||||
Der kürzeste Titel gewinnt, weil die gepflegten Karten (aus einem Konzept abgeleitet)
|
||||
kurz sind und der rohe Zuruf des Commanders lang — vorher nahm die Gruppe stur die
|
||||
älteste Karte und schnitt deren Textwüste bei 80 Zeichen mitten im Wort ab.
|
||||
"""
|
||||
if not titles:
|
||||
return "Projekt"
|
||||
prefix = titles[0]
|
||||
@@ -109,7 +127,9 @@ def _projekt_titel(titles: list[str]) -> str:
|
||||
while prefix and not t.startswith(prefix):
|
||||
prefix = prefix[:-1]
|
||||
prefix = prefix.strip(" –-:·")
|
||||
return prefix if len(prefix) >= 10 else titles[0][:80]
|
||||
if len(prefix) >= 10:
|
||||
return _kurz(prefix)
|
||||
return _kurz(_TITEL_PRAEFIX_RX.sub("", min(titles, key=len)))
|
||||
|
||||
|
||||
def _ketten_anreichern(items: list[dict]) -> list[dict]:
|
||||
@@ -319,6 +339,12 @@ _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.
|
||||
# Langer Zuruf → kurzer Kartentitel; der volle Wortlaut steht dann hier im Auftrag.
|
||||
# Der Worker MUSS wissen, dass der Titel nur eine Kurzfassung ist, sonst arbeitet er
|
||||
# am abgeschnittenen Satz statt an der ganzen Idee.
|
||||
_WORTLAUT_KOPF = ("DIE IDEE IM WORTLAUT (der Kartentitel ist nur eine Kurzfassung fuer die "
|
||||
"Anzeige — DAS hier ist der Auftrag):\n")
|
||||
|
||||
# Die erste Zeile ist zugleich der MARKER, an dem die Queue-Sicht die Art wiedererkennt
|
||||
# (das Kanban kennt kein eigenes Feld dafuer) — beim Aendern _ART_MARKER mitziehen.
|
||||
_ART_MARKER = "AUFTRAGS-ART: IDEE PRUEFEN"
|
||||
@@ -377,6 +403,15 @@ def add_idea(titel: str, notiz: str = "", created_by: str = "mc2-ui",
|
||||
return {"ok": False, "error": "Titel bitte zwischen 3 und 200 Zeichen."}
|
||||
welt = "ide" if str(welt).lower() == "ide" else "box"
|
||||
notiz = (notiz or "").strip()
|
||||
# Der Commander schreibt roh — sein Zuruf ist oft ein ganzer Absatz und wurde bisher
|
||||
# komplett zum Kartentitel (in jeder Liste abgeschnitten, unlesbar). Also: kurzer
|
||||
# Titel für die Anzeige, der WORTLAUT wandert vollständig in den Auftrag, damit der
|
||||
# Worker nichts verliert.
|
||||
wortlaut = ""
|
||||
if len(titel) > 90:
|
||||
satz = re.split(r"(?<=[.!?])\s", titel)[0].strip()
|
||||
wortlaut = titel
|
||||
titel = satz if 10 <= len(satz) <= 90 else _kurz(titel, 80)
|
||||
if welt == "ide":
|
||||
args = ["create", titel, "--assignee", "projektstart", "--created-by", created_by, "--json"]
|
||||
# Vorspann: Aufwand (Tiefe) + Ziel-Plattform + Infrastruktur — überstimmt die
|
||||
@@ -393,9 +428,13 @@ def add_idea(titel: str, notiz: str = "", created_by: str = "mc2-ui",
|
||||
infra = _INFRA_DOCKER if str(ziel).lower() == "docker" else _INFRA_LXC
|
||||
vorspann.append(infra + " " + _ZIEL_HINWEIS
|
||||
+ (" " + _ZIEL_EHRLICH if zielwahl else ""))
|
||||
if wortlaut:
|
||||
vorspann.insert(0, _WORTLAUT_KOPF + wortlaut)
|
||||
notiz = "\n\n".join(vorspann) + ("\n\n" + notiz if notiz else "")
|
||||
else:
|
||||
args = ["create", titel, "--triage", "--created-by", created_by, "--json"]
|
||||
if wortlaut:
|
||||
notiz = _WORTLAUT_KOPF + wortlaut + ("\n\n" + notiz if notiz else "")
|
||||
if notiz:
|
||||
args[2:2] = ["--body", notiz[:4000]]
|
||||
try:
|
||||
@@ -916,7 +955,7 @@ def projekt_aus_idee(task_id: str, ziel: str = "", tiefe: str = "") -> dict:
|
||||
_list_cache["ts"] = 0.0
|
||||
try:
|
||||
from services import announce
|
||||
announce.add(f"Aus der Idee „{quell_titel}“ wird ein Projekt: {task['id']} — die Box "
|
||||
announce.add(f"Aus der Idee „{_kurz(quell_titel, 60)}“ wird ein Projekt: {task['id']} — die Box "
|
||||
"bereitet das Repo vor, gebaut wird in Zed.",
|
||||
"[Ideen-Queue]", "ideen-queue", "silent")
|
||||
except Exception:
|
||||
|
||||
Reference in New Issue
Block a user