From 68322b13d928f063c44d476f7904dc9046853ea1 Mon Sep 17 00:00:00 2001 From: mhoennig Date: Thu, 23 Jul 2026 07:52:02 +0200 Subject: [PATCH] feat: Add High Risk status [!] for uncertain effort estimation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer Status-Code [!] für Items mit unbekannter Größe/Aufwand: Parser: - STATUS_BY_CODE erweitert: '!' -> {key:'highrisk', name:'High Risk – Aufwand unklar'} Style: - .node.st-highrisk: Pastellorange (#FFE5CC) mit orange Rahmen (#F97316) - .chip.st-highrisk: Gleiche Farben für Agenda-Beispiele i18n (alle 9 Sprachen): - DE: "High Risk" - EN: "high risk" - ES: "alto riesgo" - FR: "risque élevé" - PL: "wysokie ryzyko" - RU: "высокий риск" - HI: "उच्च जोखिम" - ZH: "高风险" - JA: "高リスク" Tests: - parser.test.js aktualisiert: 8 Status-Codes (waren 7) Damit können Items mit ungeklärtem Aufwand im Lean-Pathfinding-Prozess gekennzeichnet werden – wichtig für Risk-Flagging in Phase 1. Co-Authored-By: Claude Haiku 4.5 --- frontend/src/app.js | 18 +++++++++--------- frontend/src/parser.js | 3 ++- frontend/src/style.css | 2 ++ frontend/tests/parser.test.js | 5 +++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/frontend/src/app.js b/frontend/src/app.js index 0cc5a12..21ca376 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -580,7 +580,7 @@ const I18N = { empty:"Noch keine Struktur — einfach lostippen.", ghost:"…", mixedWarn:"Zeile {line}: Unter „{label}“ sind - und | gemischt — dargestellt nach dem ersten Kind.", st_idee:"Idee", st_geplant:"geplant", st_arbeit:"in Arbeit", st_durchstich:"Durchstich", - st_fertig:"fertig", st_prod:"in Produktion", st_verworfen:"verworfen", + st_fertig:"fertig", st_prod:"in Produktion", st_highrisk:"High Risk", st_verworfen:"verworfen", unknownStatusWarn:"Zeile {line}: unbekanntes Statuszeichen „{code}“ — als neutral dargestellt.", a11yStatus:"Status: {status}", a11ySize:"Aufwand: {size}", a11ySizeImplicit:"Aufwand: M (angenommen)", a11yTags:"Zuständig: {names}", a11yLink:"verlinkt", hint_indent:"Einrückung (2 Leerzeichen oder Tab) definiert die Hierarchie.", @@ -620,7 +620,7 @@ const I18N = { empty:"No structure yet — just start typing.", ghost:"…", mixedWarn:"Line {line}: under “{label}”, - and | are mixed — rendered by the first child.", st_idee:"idea", st_geplant:"planned", st_arbeit:"in progress", st_durchstich:"walking skeleton", - st_fertig:"done", st_prod:"in production", st_verworfen:"discarded", + st_fertig:"done", st_prod:"in production", st_highrisk:"high risk", st_verworfen:"discarded", unknownStatusWarn:"Line {line}: unknown status code “{code}” — shown as neutral.", a11yStatus:"Status: {status}", a11ySize:"Effort: {size}", a11ySizeImplicit:"Effort: M (assumed)", a11yTags:"Assigned: {names}", a11yLink:"has link", hint_indent:"Indentation (2 spaces or a tab) defines the hierarchy.", @@ -660,7 +660,7 @@ const I18N = { empty:"Aún no hay estructura — simplemente empieza a escribir.", ghost:"…", mixedWarn:"Línea {line}: bajo «{label}» se mezclan - y | — se representa según el primer hijo.", st_idee:"idea", st_geplant:"planificado", st_arbeit:"en curso", st_durchstich:"prototipo funcional", - st_fertig:"terminado", st_prod:"en producción", st_verworfen:"descartado", + st_fertig:"terminado", st_prod:"en producción", st_highrisk:"alto riesgo", st_verworfen:"descartado", unknownStatusWarn:"Línea {line}: código de estado desconocido «{code}» — mostrado como neutral.", a11yStatus:"Estado: {status}", a11ySize:"Esfuerzo: {size}", a11ySizeImplicit:"Esfuerzo: M (asumido)", a11yTags:"Responsable: {names}", a11yLink:"con enlace", hint_indent:"La sangría (2 espacios o un tabulador) define la jerarquía.", @@ -700,7 +700,7 @@ const I18N = { empty:"Pas encore de structure — commencez à taper.", ghost:"…", mixedWarn:"Ligne {line} : sous « {label} », - et | sont mélangés — rendu selon le premier enfant.", st_idee:"idée", st_geplant:"planifié", st_arbeit:"en cours", st_durchstich:"squelette fonctionnel", - st_fertig:"terminé", st_prod:"en production", st_verworfen:"abandonné", + st_fertig:"terminé", st_prod:"en production", st_highrisk:"risque élevé", st_verworfen:"abandonné", unknownStatusWarn:"Ligne {line} : code de statut inconnu « {code} » — affiché comme neutre.", a11yStatus:"Statut : {status}", a11ySize:"Effort : {size}", a11ySizeImplicit:"Effort : M (supposé)", a11yTags:"Responsable : {names}", a11yLink:"avec lien", hint_indent:"L'indentation (2 espaces ou une tabulation) définit la hiérarchie.", @@ -740,7 +740,7 @@ const I18N = { empty:"Brak struktury — zacznij pisać.", ghost:"…", mixedWarn:"Wiersz {line}: pod „{label}” mieszają się - i | — renderowane według pierwszego dziecka.", st_idee:"pomysł", st_geplant:"zaplanowane", st_arbeit:"w toku", st_durchstich:"działający szkielet", - st_fertig:"gotowe", st_prod:"w produkcji", st_verworfen:"odrzucone", + st_fertig:"gotowe", st_prod:"w produkcji", st_highrisk:"wysokie ryzyko", st_verworfen:"odrzucone", unknownStatusWarn:"Wiersz {line}: nieznany znak statusu „{code}” — pokazany jako neutralny.", a11yStatus:"Status: {status}", a11ySize:"Nakład: {size}", a11ySizeImplicit:"Nakład: M (założony)", a11yTags:"Przypisano: {names}", a11yLink:"z linkiem", hint_indent:"Wcięcie (2 spacje lub tabulator) definiuje hierarchię.", @@ -780,7 +780,7 @@ const I18N = { empty:"Пока нет структуры — просто начните печатать.", ghost:"…", mixedWarn:"Строка {line}: под «{label}» смешаны - и | — отображается по первому потомку.", st_idee:"идея", st_geplant:"запланировано", st_arbeit:"в работе", st_durchstich:"сквозной прототип", - st_fertig:"готово", st_prod:"в эксплуатации", st_verworfen:"отклонено", + st_fertig:"готово", st_prod:"в эксплуатации", st_highrisk:"высокий риск", st_verworfen:"отклонено", unknownStatusWarn:"Строка {line}: неизвестный код статуса «{code}» — показан как нейтральный.", a11yStatus:"Статус: {status}", a11ySize:"Оценка: {size}", a11ySizeImplicit:"Оценка: M (предполагается)", a11yTags:"Ответственные: {names}", a11yLink:"со ссылкой", hint_indent:"Отступ (2 пробела или табуляция) задаёт иерархию.", @@ -820,7 +820,7 @@ const I18N = { empty:"अभी कोई संरचना नहीं — बस टाइप करना शुरू करें।", ghost:"…", mixedWarn:"पंक्ति {line}: „{label}“ के अंतर्गत - और | मिश्रित हैं — पहले चाइल्ड के अनुसार दिखाया गया।", st_idee:"विचार", st_geplant:"नियोजित", st_arbeit:"प्रगति पर", st_durchstich:"कार्यशील ढाँचा", - st_fertig:"पूर्ण", st_prod:"उत्पादन में", st_verworfen:"अस्वीकृत", + st_fertig:"पूर्ण", st_prod:"उत्पादन में", st_highrisk:"उच्च जोखिम", st_verworfen:"अस्वीकृत", unknownStatusWarn:"पंक्ति {line}: अज्ञात स्थिति कोड „{code}“ — तटस्थ रूप में दिखाया गया।", a11yStatus:"स्थिति: {status}", a11ySize:"आकार: {size}", a11ySizeImplicit:"आकार: M (अनुमानित)", a11yTags:"जिम्मेदार: {names}", a11yLink:"लिंक सहित", hint_indent:"इंडेंट (2 स्पेस या टैब) पदानुक्रम तय करता है।", @@ -860,7 +860,7 @@ const I18N = { empty:"还没有结构——直接开始输入吧。", ghost:"…", mixedWarn:"第 {line} 行:在「{label}」下 - 与 | 混用——按第一个子项渲染。", st_idee:"想法", st_geplant:"已计划", st_arbeit:"进行中", st_durchstich:"可运行骨架", - st_fertig:"已完成", st_prod:"已上线", st_verworfen:"已放弃", + st_fertig:"已完成", st_prod:"已上线", st_highrisk:"高风险", st_verworfen:"已放弃", unknownStatusWarn:"第 {line} 行:未知状态代码“{code}”——显示为中性。", a11yStatus:"状态:{status}", a11ySize:"工作量:{size}", a11ySizeImplicit:"工作量:M(假定)", a11yTags:"负责人:{names}", a11yLink:"含链接", hint_indent:"缩进(2 个空格或制表符)定义层级。", @@ -900,7 +900,7 @@ const I18N = { empty:"まだ構造がありません — 入力を始めてください。", ghost:"…", mixedWarn:"{line} 行目:「{label}」の下で - と | が混在 — 最初の子に従って表示。", st_idee:"アイデア", st_geplant:"計画済み", st_arbeit:"作業中", st_durchstich:"ウォーキングスケルトン", - st_fertig:"完了", st_prod:"本番稼働", st_verworfen:"破棄", + st_fertig:"完了", st_prod:"本番稼働", st_highrisk:"高リスク", st_verworfen:"破棄", unknownStatusWarn:"{line} 行目: 不明なステータス記号「{code}」— 中立として表示。", a11yStatus:"ステータス: {status}", a11ySize:"規模: {size}", a11ySizeImplicit:"規模: M(想定)", a11yTags:"担当: {names}", a11yLink:"リンクあり", hint_indent:"インデント(スペース2つまたはタブ)で階層を定義します。", diff --git a/frontend/src/parser.js b/frontend/src/parser.js index 6680ad3..cad691e 100644 --- a/frontend/src/parser.js +++ b/frontend/src/parser.js @@ -15,7 +15,8 @@ export const STATUS_BY_CODE = { '/': {key:'durchstich', name:'Durchstich – funktionsbereit, Feinarbeiten offen'}, 'x': {key:'fertig', name:'fertig'}, '^': {key:'prod', name:'in Produktion'}, - '-': {key:'verworfen', name:'verworfen'} + '-': {key:'verworfen', name:'verworfen'}, + '!': {key:'highrisk', name:'High Risk – Aufwand unklar'} }; /* Parst den Notationstext zu { roots, warnings }. diff --git a/frontend/src/style.css b/frontend/src/style.css index 560b73b..f870a9e 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -512,6 +512,7 @@ .node.st-durchstich{background:#FBF2CE;border-color:#D9BE63;color:var(--ink)} .node.st-fertig {background:#DCF1DE;border-color:#86C293;color:var(--ink)} .node.st-prod {background:#DBEAF8;border-color:#85ACD7;color:var(--ink)} + .node.st-highrisk {background:#FFE5CC;border-color:#F97316;color:var(--ink)} .node.st-verworfen{ background:#F1F2F4;border-color:#B3BAC2;border-style:dashed; color:var(--muted);text-decoration:line-through;box-shadow:none; @@ -529,6 +530,7 @@ .chip.st-durchstich{background:#FBF2CE;border-color:#D9BE63} .chip.st-fertig {background:#DCF1DE;border-color:#86C293} .chip.st-prod {background:#DBEAF8;border-color:#85ACD7} + .chip.st-highrisk {background:#FFE5CC;border-color:#F97316} .chip.st-verworfen{background:#F1F2F4;border-color:#B3BAC2;border-style:dashed;color:var(--muted);text-decoration:line-through} /* ---------- Transponierte Modi (vertikal + kompakt) ---------- */ diff --git a/frontend/tests/parser.test.js b/frontend/tests/parser.test.js index 8dd266b..efec8c0 100644 --- a/frontend/tests/parser.test.js +++ b/frontend/tests/parser.test.js @@ -182,9 +182,10 @@ describe('Vokabular-Exporte', () => { expect(SIZE_RANK).toEqual({ XS: 0, S: 1, M: 2, L: 3, XL: 4, XXL: 5 }); }); - it('STATUS_BY_CODE deckt alle sieben Codes ab (SPEC §4)', () => { + it('STATUS_BY_CODE deckt alle acht Codes ab (SPEC §4)', () => { expect(Object.keys(STATUS_BY_CODE).sort()) - .toEqual([' ', '-', '/', '?', '^', 'x', '~'].sort()); + .toEqual([' ', '!', '-', '/', '?', '^', 'x', '~'].sort()); expect(STATUS_BY_CODE['-'].key).toBe('verworfen'); + expect(STATUS_BY_CODE['!'].key).toBe('highrisk'); }); });