Zum Inhalt

portfolio

Fasst mehrere bereits konfigurierte ARTs zu einem kombinierten Large-Solution- oder Portfolio-Report zusammen — als Pooled (die Solution als ein System betrachtet) oder als Vergleich (Einheiten nebeneinander). Nutzt die Metriken aus build_reports; die einzelnen ART-Reports werden nur referenziert, nicht verändert.

Status: verfügbar (Alpha)

Handbücher

Sprache Download
Deutsch (DE) Benutzerhandbuch
English (EN) User Manual
Română (RO) Manual de Utilizator
Português (PT) Manual do Utilizador
Français (FR) Manuel d'utilisation

Grundbegriffe

Begriff Bedeutung
ART Agile Release Train / Teamgruppe — die Ebene, auf der du in build_reports bereits berichtest.
Solution Eine Gruppierung mehrerer ARTs (referenziert deren Projekt-Templates).
Portfolio Eine Gruppierung mehrerer Solutions (Portfolio > Solutions > ARTs).
Pooled Modus: Alle Issues werden zu einem Datensatz zusammengeführt — die Solution als ein System.
Vergleich Modus: Jede Einheit (ART oder Solution) wird separat nebeneinander dargestellt.

Oberfläche

Screenshot der Portfolio-GUI

Start

GUI

python -m portfolio

Oder auf die Kachel Solutions & Portfolios links im SituationReport-Launcher klicken.

Kommandozeile

python -m portfolio solution.json --mode pooled --output report.html
# Vergleichsmodus / PDF-Ausgabe:
python -m portfolio solution.json --mode comparison --pdf report.pdf

Die Konfigurationsdatei (solution.json) listet die Mitglieder auf (ARTs bei einer Solution, Solutions bei einem Portfolio) und wird in der GUI erstellt bzw. bearbeitet.

Report-Inhalte

Jeder Report beginnt mit der Management-Summary — eine Zeile je Einheit (Pooled: die ganze Solution/das Portfolio): Items, abgeschlossen, offen (WIP), Durchlaufzeit-Perzentile (Median/85./95.), der Ziel-CT-Anteil und die End-to-End-Lead-Time (Created → Closed, Median/85.; im Pooled-Modus die Solution-Lead-Time über alle ARTs).

Darunter zeigt die Tabelle Data Quality per Source je Quelle: Record-Zahl, ihren Anteil am Gesamtvolumen, den Anteil ohne First Date, den offenen Anteil, ob CFD-Daten geliefert wurden, den Datenstand — und eine Ampel-Konfidenz (high/medium/low, Schwellen in summary.py dokumentiert). Der Titel trägt den Abdeckungsgrad („x/y sources delivered data"). Im PDF ist die Tabelle Seite 2.

Im Comparison-Modus werden Median-CT- und 95.-Perzentil-Zellen rot hervorgehoben, wenn sie das 1,5-fache des Spalten-Medians übersteigen (ab drei Zeilen) — die Frage „welche Einheit ist der Ausreißer?" beantwortet sich selbst.

Capability-Map & -Health (optional)

Eine Solution-Config kann über "capabilities": "pfad/zu/capabilities.json" auf eine Capability-Map verweisen; der Report rendert dann unter der Qualitätstabelle eine Capability Map & Health-Tabelle (PDF: eigene Seite). Ein Portfolio aggregiert die Maps aller Member-Solutions und ergänzt eine Solution-Spalte. Die Map:

{
  "capabilities": [
    {
      "id": "C-1",
      "title": "Data Insights & Reporting",
      "health": "critical",
      "arts": ["ART Beta-3"],
      "owner": "ART Beta-3",
      "assessed_on": "2026-08-26",
      "notes": "optional"
    }
  ]
}

health ist einer von healthy / at_risk / critical — von Menschen bewertet im PI-Planning/-Review (assessed_on hält fest, wann). arts benennt die beitragenden Member-ARTs; eine Capability ohne beitragenden ART wird als uncovered markiert (Geschäftswert, den niemand liefert), und ein ART-Name, der nicht unter den Members der Solution ist, erzeugt eine Drift-Warnung im Log. Kritische Capabilities sortieren nach oben, Health-Zellen sind farbig; der Titel zählt critical/at risk/uncovered. owner benennt ein Team, keine Person. Die Capability-Map (Geschäftsfähigkeiten) ist bewusst nicht die stage_map (Workflow-Status) — andere Dimension, andere Quelle. Fehlende oder defekte Dateien werden geloggt und übersprungen.

ROAM-Risk-Board (optional)

Eine Solution-Config kann über "risks": "pfad/zu/risks.json" auf ein Risiko-Register verweisen; der Report rendert dann unter Qualitätstabelle und Capability-Map ein ROAM-Board (PDF: eigene Seite). Ein Portfolio aggregiert die Register aller Member-Solutions und ergänzt eine Solution-Spalte. Das Register:

{
  "risks": [
    {
      "id": "R-1",
      "title": "Testumgebung noch nicht bestellt",
      "roam": "owned",
      "owner": "System Team",
      "impact": "high",
      "status_since": "2026-07-15",
      "notes": "optional"
    }
  ]
}

roam ist eine der Kategorien resolved / owned / accepted / mitigated, impact eine von high / medium / low. Die Zeilen sind in R-O-A-M-Reihenfolge gruppiert, Kategorie- und Impact-Zellen farbig. status_since (wann das Risiko in seine aktuelle Kategorie kam) treibt das Aging: ein Owned-Risiko, das älter als 30 Tage ist, bekommt eine rote „Since"-Zelle — Ownership ohne Bewegung ist genau das, was das Board sichtbar machen soll. Der Titel zählt Risiken gesamt, Owned und Aging. owner benennt ein Team, keine Person. Eine fehlende oder defekte risks-Datei wird geloggt und übersprungen — Governance-Daten brechen den Flow-Report nie.

NFR-/Architecture-Runway-Dashboard (optional)

Eine Solution-Config kann über "nfr": "pfad/zu/nfr.json" auf ein NFR-Register verweisen; der Report rendert dann unter dem ROAM-Board ein NFR & Architecture Runway-Dashboard (PDF: eigene Seite, beide Tabellen gestapelt). Ein Portfolio aggregiert die Register aller Member-Solutions und ergänzt eine Solution-Spalte. Das Register:

{
  "nfrs": [
    {
      "id": "N-1",
      "title": "API-Antwortzeit",
      "target": "p95 < 200 ms",
      "actual": "p95 = 340 ms",
      "status": "violated",
      "owner": "ART Beta-1"
    }
  ],
  "runway": [
    {
      "id": "RW-1",
      "title": "Automatisches Failover",
      "status": "gap",
      "needed_by": "2026-08-13",
      "owner": "ART Beta-2"
    }
  ]
}

Der NFR-status ist einer von met / at_risk / violated, der Runway-status einer von in_place / building / gap — von Menschen bewertet im PI-Planning/-Review; das Werkzeug rechnet Ziel gegen Ist bewusst nicht selbst („das LLM textet, es rechnet nicht" gilt sinngemäß auch fürs Werkzeug). Verletzte NFRs und Runway-Lücken sortieren nach oben, Status-Zellen sind farbig; ein Runway-Element, dessen needed_by verstrichen ist, ohne dass es in_place ist, erscheint als überfällig (rote Datumszelle). Der Titel zählt NFRs (verletzt/at risk) und Runway-Elemente (Lücken/überfällig). owner benennt ein Team, keine Person. Fehlende oder defekte Dateien werden geloggt und übersprungen.

Dependency-/Integrations-Heatmap (optional)

Eine Solution-Config kann über "dependencies": "pfad/zu/dependencies.json" auf ein Dependency-Register verweisen; der Report rendert dann unter dem NFR-Dashboard eine Dependency & Integration Heatmap (PDF: eigene Seite). Ein Portfolio aggregiert die Register aller Member-Solutions und ergänzt in der Detail-Tabelle eine Solution-Spalte. Das Register:

{
  "dependencies": [
    {
      "id": "D-1",
      "title": "Billing-API-Contract",
      "from": "ART Alpha-1",
      "to": "ART Alpha-3",
      "status": "blocked",
      "due": "2026-08-18",
      "notes": "optional"
    }
  ]
}

from braucht etwas, das to liefert; status ist einer von blocked / at_risk / on_track / done. Die Heatmap zählt offene Abhängigkeiten (Status ≠ done) je from/to-Paar — jede Zelle trägt die Farbe ihres dringlichsten Status. Darunter listet die Detail-Tabelle jede Abhängigkeit (blocked zuerst); eine Abhängigkeit mit verstrichenem due, die nicht done ist, erscheint überfällig (rote Datumszelle). Der Titel zählt blocked/at risk/überfällig. to wird bewusst nicht gegen die Member-Liste validiert — Integrationspunkte dürfen auf den ART einer anderen Solution, einen Lieferanten oder ein Fremdsystem zeigen (Cross-Solution-Abhängigkeiten werden im Portfolio-Report sichtbar). Fehlende oder defekte Dateien werden geloggt und übersprungen.

Decision-/Assumption-Log (optional)

Eine Solution-Config kann über "decisions": "pfad/zu/decisions.json" auf ein Entscheidungs-Log verweisen; der Report rendert dann unter der Dependency-Heatmap eine Decision & Assumption Log-Tabelle (PDF: eigene Seite). Ein Portfolio aggregiert die Logs aller Member-Solutions und ergänzt eine Solution-Spalte. Das Log — leichtgewichtig, ADR-artig:

{
  "entries": [
    {
      "id": "ADR-1",
      "kind": "decision",
      "title": "Vendor-Sync-Service kaufen statt bauen",
      "status": "accepted",
      "owner": "ART Beta-1",
      "logged_on": "2026-04-05",
      "supersedes": "ADR-0",
      "notes": "optional"
    },
    {
      "id": "AS-1",
      "kind": "assumption",
      "title": "Datenqualität bessert sich mit dem nächsten Rollout",
      "status": "open",
      "review_by": "2026-08-23"
    }
  ]
}

kind ist decision (Status proposed / accepted / superseded) oder assumption (Status open / confirmed / invalidated) — der Parser erzwingt das passende Status-Set. supersedes muss einen Eintrag desselben Logs benennen; so bleibt die Trade-off-Spur intakt. review_by gibt einer Annahme ihr Verfallsdatum: eine offene Annahme mit überschrittenem Prüfdatum sortiert nach oben und bekommt eine rote „review due"-Zelle — der Anschlusspunkt für Red-Team-/Premortem-Sitzungen. owner benennt ein Team, keine Person. Fehlende oder defekte Dateien werden geloggt und übersprungen.

Delta-Briefing (D2, deterministischer Kern)

Zwei Befehle machen aus Report-Ständen ein „Was hat sich geändert?"-Briefing:

python -m portfolio portfolio.json --snapshot stand_jetzt.json
python -m portfolio --delta stand_vorher.json stand_jetzt.json --output delta.html

--snapshot friert den berechneten Report-Zustand (Kennzahlen je Einheit und gepoolt, Quell-Qualität inkl. Konfidenz, alle sieben Governance-Register — seit 0.37.1 auch Flussprobleme mit Konferenzen-Zähler und SLOs) als kleines Schema-v1-JSON ein; --as-of YYYY-MM-DD setzt das Beobachtungsdatum (Standard: heute). Ohne --output/--pdf wird nur der Snapshot geschrieben.

--delta PREV NOW braucht keine Config: Es vergleicht zwei Snapshots und liefert das Briefing — Kennzahl-Deltas auf Anzeigegenauigkeit (unsichtbare Float-Änderungen entfallen), Durchsatz im Zeitraum, Konfidenz-Wechsel je Quelle und je Governance-Register neue/entfallene Einträge, Statusübergänge (Verschlechterungen zuerst, rot; Verbesserungen grün) sowie frisch überfällige Einträge (gegen das as-of-Datum beider Snapshots beurteilt — nur echte Kipp-Punkte zählen). --output *.md schreibt Markdown, jede andere Endung die eigenständige HTML-Seite, ohne --output geht Markdown nach stdout. Ein Delta ohne Änderungen sagt das ausdrücklich — Stille ist Information.

Das Markdown ist bewusst der Eingabe-Contract der optionalen LLM-Narration (D2 Teil 2, noch nicht gebaut): Das LLM darf umformulieren, nie Zahlen hinzufügen — die Zahlen entstehen hier, deterministisch.

In der GUI: Das Manager-Fenster trägt zwei passende Knöpfe — Snapshot speichern … friert die aktuell konfigurierte Solution/das Portfolio in eine JSON-Datei ein (Namensvorschlag mit Tagesdatum), und Delta-Briefing … fragt nach Vorher- und Nachher-Snapshot und öffnet das Briefing im Browser. Der Demo-Weg ist noch kürzer: Der Demo-Portfolio-Bereich des Testdaten-Generators bekommt Delta-Briefing öffnen und rendert direkt das mitgelieferte Paar snapshot_prev/now.json.

Flussproblem-Backlog & Konferenzmappe (optional, B6)

"flow_problems": "flow_problems.json" rendert den Flussproblem- Backlog — den wichtigsten Input der Value-Stream-Konferenz. Jedes Problem trägt id, Titel, Status (open/committed/resolved/ dropped), die betroffenen value_streams (Cross-VS wird abgeleitet: mehr als ein Stream), Einbringer, Owner-Team, raised_on, einen conferences-Zähler (in wie vielen Konferenzen es auf dem Tisch war — von Menschen gepflegt), resolution_commitment und follow_up_pi. Das Workshop-Muster „geloggt, nie mitigiert, taucht nächstes PI wieder auf" wird messbar: Ein ungelöstes Problem mit ≥ 3 Konferenzen sortiert nach oben und trägt einen roten Zähler.

Die Konferenzmappe bündelt die Sitzungs-Inputs zu einer leichten, druckbaren Seite:

python -m portfolio portfolio.json --conference mappe.html --conference-date 2026-09-10

Input 1 · Aktuelle Daten (Summary + Quell-Qualität), Input 2 · Impediment-Backlog & Governance (Flussprobleme zuerst, dann ROAM und Dependencies), Input 3 · Business Objectives (Capability-Map + SLOs), Input 4 · Integrierte Roadmap & Strategic Themes (B7). Seit 0.36.0 ergänzt eine Solution, die in "harmonisation" den Ordner eines Harmonisierungs-Arbeitsbereichs nennt, die Entscheider-Matrix des Moduls harmonisation als Anhang nach Input 4 — eine Board-Sicht, bewusst kein fünfter Konferenz-Input.

KI-Entwürfe für die Mappe (D8, seit 0.37.0). --conference zusammen mit --narrate [PROVIDER] entwirft fünf gekennzeichnete Teile — eine Einleitung über alle vier Inputs und je Input einen Absatz — in die Entwurfsdatei <DATEI>.narration.md; die Mappe selbst bleibt deterministisch. Mit --conference-draft inline stehen die Entwürfe zusätzlich in der Mappe (Einleitung vor Input 1, jeder Absatz unter seiner Überschrift). Jeder Teil hat seinen eigenen deterministischen Contract aus denselben Registern, die die Mappe zeigt — Einheiten, Teams und Register, nie Personen; Zahlen-Wächter, Art.-50-Banner und Betreiber-Nachweis (Zweck d8_conference) gelten unverändert. Ein Teil, dessen Entwurf scheitert, wird in der Datei genannt und fehlt; die Mappe wird trotzdem geschrieben. In der Oberfläche gilt der KI-Haken jetzt auch für „Konferenzmappe …“; die neue Auswahl „Mappen-Entwurf: nur Datei | in der Mappe“ bestimmt den Ort. Der vollständige interaktive Report bleibt die Detailquelle. In der GUI: Der Knopf Konferenzmappe … im Manager-Fenster schreibt dieselbe Seite für die aktuell konfigurierte Solution und öffnet sie im Browser — von dort als PDF drucken; im Demo-Portfolio-Bereich des Testdaten-Generators öffnet Konferenzmappe öffnen die Demo-Mappe mit einem Klick.

Der Konferenztermin (seit 0.31.0). Die Mappe ist für einen geplanten Termin geschrieben, nicht für den Tag ihrer Erzeugung. Das Feld „Konferenz am" im Manager-Fenster hinterlegt ihn als report.conference_date in der Konfiguration; --conference-date sticht ihn für einen einzelnen Lauf. Der Kopf der Mappe nennt dann den Termin samt Vorlaufzeit („noch 19 Tage"), und der Dateiname schlägt den Konferenztermin vor. Ohne Termin steht im Kopf „Konferenztermin nicht gesetzt" — nicht das heutige Datum, das eine Konferenz von heute behaupten würde. Das Feld ist optional; Konfigurationen ohne den Schlüssel laden unverändert.

Reportsprache (seit 0.32.0). Die Beschriftungen und Texte der Reports folgen der Sprache des Fensters — wer die Oberfläche auf Französisch stellt, bekommt den Report auf Französisch. Wer eine Sprache festnageln will, wählt sie im Feld Reportsprache; die Vorgabe „—" heißt „wie Oberfläche" und speichert nichts. Rangfolge: --lang (Kommandozeile) sticht report.language (Konfiguration) sticht die Fenstersprache; ohne alles drei Englisch. Das Datumsformat folgt mit (de/ro 19.09.2026, pt/fr 19/09/2026, en 2026-09-19) — bis 0.31.0 stand in jedem Report das deutsche Format, auch im englischen. Seit 0.33.0 folgen auch die Beschriftungen innerhalb der Diagramme — Achsen, Diagrammtitel, Kurvennamen und die Monatsabkürzungen der Zeitachsen. Nicht übersetzt werden die Metriknamen (die regelt weiter die SAFe/Global-Umschaltung), alles, was aus den Daten kommt — Stage-Namen, Vorgangsarten, Projektkürzel —, und die Markdown-Fassung des Delta-Briefings (sie ist der Eingabe-Contract der LLM-Narration, deren Sprache --llm-lang regelt).

Farblegende (seit 0.31.0). Alle eingefärbten Zellen ziehen aus denselben fünf Hintergründen. Am Kopf jeder Seite steht deshalb ein Farbschlüssel (grün · blau · gelb · rot · grau) und unter jeder eingefärbten Tabelle eine Zeile mit deren eigenen Statuswörtern — nötig, weil dieselbe Farbe je nach Register etwas anderes bedeutet: Grau heißt bei einer Abhängigkeit done, bei einem ROAM-Risiko accepted. Statusskalen werden vollständig gezeigt, Einzelmarkierungen (überfällig, überaltert, unabgedeckt) nur, wenn sie auf der Seite vorkommen. Dasselbe gilt für den vollen Report und das Delta-Briefing.

Lagevortrag-Einseiter (P6, seit 0.43.0)

„Eine fokussierte Folie, die jeder sofort lesen kann.“ --onepager seite.html rendert die ganze Lage auf eine A4-Seite: vier Dimensionen (Flow, Qualität, Wert, Abhängigkeiten) × drei Fragen (Wo stehen wir? Was hat sich geändert? Was folgt daraus?), BLUF oben, ein Konfidenz-Badge je Zelle. Alles deterministisch aus den Registern, die der Report schon kennt; keine neue Rechnung, kein Urteil.

python -m portfolio portfolio.json --onepager seite.html --since-snapshot snapshots/snapshot_prev.json
python -m portfolio portfolio.json --onepager kata.html --kata
  • Spalte 1 — gepoolte Kennzahlen und Flussprobleme; DORA-Stufen, SLO- und NFR-Status; Capability-Health, Themes und Epics; Cross-VS-Druck, Abhängigkeiten und ROAM-Risiken.
  • Spalte 2 — nur mit --since-snapshot: Durchsatz, Cycle-Time-Verschiebung und Register-Übergänge aus dem Delta-Briefing. Ohne Vergleichsstand sagt die Spalte das.
  • Spalte 3 — nur Entscheidungsbedarf, nie eine Empfehlung: Flussprobleme ab der dritten Konferenz, verletzte SLOs, verletzte NFRs, überfällige Runway-Lücken, kritische Capabilities, Themes ohne Epic, Epics ohne Theme, Annahmen über dem Prüfdatum, der Wecker über seiner Schwelle, überfällige Abhängigkeiten — plus eine leere Zeile für das Urteil des Vortragenden.
  • BLUF — ein Vorlagensatz aus den Daten: die größte Abweichung zuerst (Schwelle gerissen, Überlebende, Verletzungen), sonst „Lage im Rahmen der vereinbarten Schwellen“.
  • Konfidenz — Flow folgt der Quell-Qualität (A1); Register gelten als hoch, wenn datiert innerhalb von 30 Tagen, mittel, wenn vorhanden, aber undatiert oder älter, fehlt, wenn nicht verbunden.
  • Kata (--kata, GUI-Haken Kata) — dieselbe Seite mit leeren Zellen und den Fragen als Platzhalter: das Übungsblatt des Curriculums („eine Lageanalyse in 30 Minuten“); die gefüllte Seite ist die Lösung.

GUI: Knopf Einseiter … im Manager-Fenster; Spalte 2 nutzt den zuletzt in dieser Sitzung geschriebenen Snapshot.

Lagevortrag-Entwurf — die KI-Lesart des Einseiters (M6, seit 0.50.0)

--onepager seite.html --narrate PROVIDER schreibt zusätzlich einen Sprechzettel seite.html.vortrag.md (Englisch: .briefing.md): den KI-formulierten Entwurf des gesprochenen Lagevortrags von rund 90 Sekunden, 8 bis 12 Sätze in fester Reihenfolge — zuerst der BLUF, dann die vier Dimensionen (wo stehen wir, was hat sich geändert), dann der Entscheidungsbedarf nur genannt, zuletzt das Datenvertrauen (Zellen mit Konfidenz niedrig oder fehlt). Der Contract des Modells ist der Einseiter selbst als zitierbare Fakten (E/bluf, E/meta, E/flow.q1 … E/dependencies.q3, E/<dimension>.decide) plus der Fakten-Index des Stands (S1/S0/D). Es gelten dieselben Wächter wie bei D3/D4 über llm.narrate: Zahlen-Wächter, Zitat-Wächter je Aussage, Banner, Betreiber-Nachweis mit Zweck m6_briefing; Provider frei, auch export. Ein verworfener Entwurf bricht nichts ab — der Einseiter steht, die Datei nennt den Grund.

Die Einseiter-Seite selbst bleibt byte-gleich und KI-frei; ihr Footer bleibt wahr. Leitplanke des Musters M6, als erste Zeile der Datei: Entwurf, nicht der Vortrag — der Vortragende prüft, kürzt, trägt vor und zeichnet verantwortlich. Bewusst nicht: keine Übersetzung des Sprechzettels, kein Noise-Audit über Entwürfe, keine Empfehlung oder Option im Entwurf.

python -m portfolio portfolio.json --onepager seite.html --since-snapshot snapshots/snapshot_prev.json --narrate ollama
python -m portfolio portfolio.json --onepager seite.html --narrate export      # Prompt-Bündel, zurück über llm check

GUI: der Haken KI-Narration (Entwurf) wirkt auch beim Knopf Einseiter … (nie beim Kata).

Das Lagebild befragen (D3, seit 0.46.0)

Schritt-für-Schritt-Einführung mit Bildschirmfotos, echten Ausgaben und Fehlerbildern: Tutorial „Das Lagebild befragen" (PDF: DE / EN).

--ask "Frage" stellt eine Frage an einen Stand. Der Stand (live aus der Config oder ein gespeicherter Snapshot über --ask-snapshot) wird zum Fakten-Index abgeflacht: jede Zahl und jeder Registereintrag bekommt einen Pfad wie S1/total.median_ct, S1/units(ART Alpha-2).open oder S1/governance.dependencies(D-7).status; mit --since-snapshot kommen der Vorstand (S0/…) und die Veränderungen (D/…) dazu, ein angebundener Harmonisierungs-Arbeitsbereich liefert H/…. Der Index ist der einzige Kontext des Modells — kein Vektorspeicher, kein Retriever, keine Fremdquellen — und der Zitat-Wächter verwirft jede Antwort, in der eine Aussage ohne Pfad-Zitat steht, ein nicht existierender Pfad zitiert wird oder eine Zahl nicht aus den zitierten Fakten stammt. „Dazu liegt im Lagebild keine Angabe vor." ist der einzige erlaubte Satz ohne Zitat. Owner- und andere Personenfelder kommen nie in den Index (per Test erzwungen); Freitexte aus Registern sind als Daten gekennzeichnet und gekürzt.

Entscheidungshygiene (Prinzip 7): --own-view "…" hält deine eigene Einschätzung vor der Antwort fest; sie steht in <config>_<datum>.ask.md neben der Antwort und geht nie ans Modell. Der GUI-Knopf Lagebild befragen … öffnet einen Dialog mit Frage, Einschätzungsfeld (standardmäßig an, eine Präferenz dieses Rechners) und Antwort. Provider wie überall (--narrate; export schreibt das Prompt-Bündel, llm check prüft dann auch die Zitate); Nachweis-Zweck d3_question; Rückgabewert 3, wenn die Antwort verworfen wird. Die Antwort erklärt, sie empfiehlt nie.

Noise-Audit — wie laut ist das Modell? (D7, seit 0.47.0)

--ask "Frage" --noise 5 stellt dieselbe Frage fünfmal in variierter Formulierung (Lauf 1 die unveränderte Frage, dann eigene Varianten aus --noise-variants, dann feste Rahmen wie „Kurz gefasst: …") gegen denselben Stand. Weil jede D3-Antwort ihre Pfade zitieren muss, wird die Streuung deterministisch gemessen, ohne zweites Modell: Zitier-Konsistenz (mittlere paarweise Jaccard-Ähnlichkeit der zitierten Pfadmengen, 0–100), der Kern (Pfade, die die Mehrheit zitiert), die Streuung (Pfade, die nur eine Antwort zitiert, mit markierten Aussagen), Zahlen-Abweichungen je Pfad sowie die Quoten „keine Angabe" und „verworfen". Eine verworfene Antwort wird nicht wiederholt — sie zählt als Streuung. --views DATEI listet Einschätzungen des Stabs (eine je Absatz) neben dem KI-Kern, ohne Bewertung. Das Protokoll geht nach <config>_<datum>.noise.md; der GUI-Dialog Lagebild befragen … hat ein Feld Wiederholungen (> 1 startet das Audit). Die Streuung ist ein Befund über Modell und Frage, kein Urteil über die Lage.

Entscheidungspunkte — das Wecker-Register (D4, seit 0.48.0)

"decision_points": "decision_points.json" rendert das Wecker-Register (Muster M4: Frühindikator + Schwelle + vereinbarte Reaktion). Jeder Wecker nennt eine Kennzahl als Fakten-Pfad des Frage-Index (S1/units(ART Alpha-3).p85_ct, D/total.open mit "unit": "%" für die relative Veränderung zum Vorstand, S1/governance.dependencies.count(blocked), S1/pressure.cross_vs für den P4-Druck), einen Vergleich (>=, <=, >, <), die vereinbarte threshold, die question, die der Wecker auf die Tagesordnung bringt, die vereinbarte reaction und das team. Der Report prüft jeden Wecker gegen den Stand und zeigt alle vier Zustände: ausgelöst (hervorgehoben), unterschwellig, nicht vereinbart (keine Schwelle — weckt nie), nicht berechenbar (Pfad fehlt, z. B. D/… ohne Vorstand). Das Werkzeug erfindet keine Schwelle, rechnet keine Priorität und spricht keine Empfehlung aus — die Regeln von P4. Die ausgewerteten Wecker stehen im Snapshot (neuntes Governance-Register) und im Delta-Briefing („neu ausgelöst"); --alarms DATEI schreibt ein Protokoll, mit --since-snapshot werden die D/…-Wecker berechenbar. Wecker lassen sich in D3 erfragen (S1/governance.decision_points(DP-1).status).

{"schema": 1, "points": [
  {"id": "DP-1", "title": "P85 von Alpha-3 über den vereinbarten 30 Tagen",
   "metric": "S1/units(ART Alpha-3).p85_ct", "op": ">=", "threshold": 30,
   "question": "Scope von Alpha-3 im nächsten PI kürzen?",
   "reaction": "Lead-Team bringt Vorschlag in die nächste VSC", "team": "ART Alpha-3",
   "agreed_on": "2026-09-30"}
]}

Schritt 2 (seit 0.49.0). --alarms … --history ORDNER liest einen Ordner gespeicherter Snapshots (mindestens vier Stände) und listet Auffälligkeits-Hinweise: Kennzahlen, deren jüngster Wert mehr als 3 MAD vom Median der eigenen Historie abweicht (robuste Statistik, Standardbibliothek). Hinweise sind Kandidaten für Wecker, nie Alarme — ob daraus ein Wecker wird, vereinbart der Stab; höchstens zehn werden gezeigt, der Rest gezählt. --alarms … --narrate PROVIDER ergänzt je ausgelöstem Wecker eine KI-Erklärung: das Modell sieht den Wecker und nur die Fakten, die sein Pfad berührt, muss jede Aussage zitieren (Zitat-Wächter wie D3), darf keine Ursache über die Fakten hinaus nennen und empfiehlt nichts; eine verworfene Erklärung lässt den Wecker stehen. Ausgelöste Wecker erscheinen außerdem als Entscheidungspunkte in den Zeilen des Einseiters und führen dessen BLUF an.

Solution Areas & Rekurrenz je Naht (optional, P5)

"solution_areas": "solution_areas.json" rendert das Solution-Area-Register: dynamische Solution Areas — befristete Zusammenarbeit über Teams oder Value Streams hinweg — mit id, title, einem kurzen Schlüssel topic, mindestens zwei participants, opened_on und closed_on (leer = noch aktiv). Der Report gruppiert sie je Naht (dieselben Beteiligten) und zählt, wie oft derselbe Anlass dort wiederkam: zweimal wird hervorgehoben, ab dreimal ist es das EA-Signal — dynamische Areas sollten selten sein, und dieselbe an derselben Stelle zeigt auf den Value-Stream-Schnitt oder die Architektur, nicht auf die Teams. Die Nähte stehen in Input 2 der Konferenzmappe, im Snapshot und Delta-Briefing, im Einseiter (Zeile Abhängigkeiten, Entscheidungspunkt „Naht prüfen“) und im Exec-Summary-Contract.

{"schema": 1, "areas": [
  {"id": "SA-1", "title": "Shared test environment", "topic": "test environment",
   "participants": ["ART Alpha-1", "ART Alpha-3"], "opened_on": "2026-03-01", "closed_on": "2026-03-28"}
]}

Strategic Themes & integrierte Roadmap (optional, B7)

"themes": "themes.json" gibt strategischen Themen ein strukturiertes Zuhause und der Solution-Ebene ihre integrierte Roadmap:

{
  "themes": [{"id": "T-1", "title": "Digital ordering end-to-end"}],
  "epics": [
    {"id": "EP-1", "title": "Self-service portal", "train": "ART A",
     "horizon": "P1", "theme": "T-1", "status": "in_progress"},
    {"id": "EP-9", "title": "Legacy rewrite", "train": "ART C",
     "horizon": "Y1"}
  ]
}

Horizonte folgen nah granular, fern grob: P1 · P2 · Y1 · Y2 · Y3. Orphan-Detection wirkt in beide Richtungen: Ein Theme, auf das kein Epic einzahlt, wird rot als declared & forgotten markiert (portfolioweit beurteilt — ein Epic einer anderen Solution zählt), und ein Epic mit leerem theme ist eine Zombie-Initiative (ein Tippfehler in der Referenz ist ein Validierungsfehler, kein Zombie). Der Report rendert Theme-Tabelle, Roadmap-Matrix (Zeilen = Trains, Spalten = Horizonte, Zombies rot) und Zombie-Liste; die Konferenzmappe trägt sie als Input 4. Roadmap-Epics fließen außerdem in D2-Snapshots — das Delta-Briefing dokumentiert so die updated roadmaps je Konferenz (Horizont- Verschiebungen, Statuswechsel; ein verlorenes Theme liest sich als → zombie).

SLO- & DORA-Register (optional, C1/C2)

Eine Solution-Config kann zwei weitere Register referenzieren, beide vom steckbaren sources-Framework erzeugt (Provider und das 30-Zeilen-Rezept für neue Quellen: siehe dessen Modulseite):

  • "slo": "slo.json" rendert Service Levels & Error Budgets: je SLO Ziel, aktueller SLI, Rest-Error-Budget (zentrale Regel: verbraucht = (100−SLI)/(100−Ziel)) und Status — met / at risk (< 25 % Restbudget) / breached / unknown, breached zuerst. Jede Datenquelle wird nach derselben Regel beurteilt.
  • "dora": "dora.json" rendert Delivery Performance (DORA) & Code Quality: die vier DORA-Kennzahlen je Einheit, jede Zelle an den veröffentlichten Schwellen eingestuft (elite/high/medium/low), Gesamt-Tier = schwächste Kennzahl; darunter die Qualitätstabelle (Coverage, Maintainability-Rating, kritische Verstöße).

Jede Zeile behält ihre Datenquelle (kombinierbare Quellen); ein Portfolio aggregiert Member-Register mit Solution-Spalte; defekte Dateien werden geloggt und übersprungen.

Eigene Stage-Map (optional, Config-Schema 2)

Standardmäßig poolen unterschiedliche ART-Workflows in die drei kanonischen Gruppen To Do / In Progress / Done. Eine Solution-Config kann stattdessen eigene kanonische Stages definieren:

"stage_map": {
  "stages": {
    "Backlog":   ["Funnel", "Analysis"],
    "In Arbeit": ["Implementing", "Review"],
    "Fertig":    ["Done", "Released"]
  },
  "first_stage": "In Arbeit",
  "closed_stage": "Fertig"
}

first_stage/closed_stage markieren die CFD-Grenzen. Nicht zugeordnete Stages fallen mit protokollierter Warnung in first_stage. Configs ohne den Block verhalten sich unverändert (v1-Dateien laden wie bisher).

Architektur

portfolio/
├── __main__.py        Dispatcher: GUI ohne Argumente, CLI mit Argumenten
├── cli.py             run_solution_report() + argparse-CLI
├── solution_config.py Solution-/Portfolio-Konfiguration (Mitglieder, Modus, Terminologie)
├── risks_config.py    ROAM-Risiko-Register (B3): Schema, parse/load/save
├── nfr_config.py      NFR-/Runway-Register (B2): Schema, parse/load/save
├── capability_config.py Capability-Map (B1): Schema, parse/load/save
├── dependency_config.py Dependency-Register (B5): Schema, parse/load/save
├── decision_config.py Decision-/Assumption-Log (B4): Schema, parse/load/save
├── flow_problems_config.py Flussproblem-Backlog (B6): Schema, Survivor-Regel
├── themes_config.py   Strategic Themes/Roadmap (B7): Orphan-/Zombie-Regeln
├── slo_config.py      SLO-Register (C1): zentrale Budget-/Status-Regel
├── dora_config.py     Delivery-Register (C2): DORA-Tiers + Qualität
├── solution_areas_config.py Solution-Area-Register (P5): Nähte, Rekurrenz-Schwellen
├── decision_point.py  Cross-Value-Stream-Druck + Entscheidungspunkt-Wecker (P4)
├── snapshot.py        Report-Snapshot (D2): Kennzahlen/Qualität/Governance einfrieren (acht Register)
├── delta.py           Delta-Briefing (D2): zwei Snapshots vergleichen, HTML/Markdown
├── exec_summary.py    Exec-Summary-Contract für die KI (D1): Zahlen nur aus dem Snapshot
├── red_team.py        Red-Team-Fragen (D5) gegen den Contract
├── conference_draft.py KI-Entwurf für die Konferenzmappe (D8): Datei oder inline
├── onepager.py        Lagevortrag-Einseiter (P6): 4 × 3, BLUF, Kata-Modus
├── briefing.py        Lagevortrag-Entwurf (M6): Einseiter-Zellen als Fakten E/…, zitiert, bewacht
├── report_texts.py    Report-Texte in fünf Sprachen (t(key, lang))
├── gui.py             Solutions-&-Portfolios-GUI (Datenquellen-Dialog mit elf Registern)
├── aggregator.py      Zusammenführung auf Datensatz-Ebene + Rendering (HTML/PDF/Konferenzmappe)
└── summary.py         Management-Summary + Datenqualität (A1/A2), Ausreißer (A3), Register-Blöcke (ROAM, NFR, Abhängigkeiten, Entscheidungen, Flussprobleme, Solution Areas, Themes, SLO, DORA)

Nutzt build_reports (Loader, Metriken, Export) wieder. Die Aggregation erfolgt per Record-Pooling — die ART-Issues werden auf Datensatz-Ebene zusammengeführt und die bestehenden Metriken laufen unverändert darüber (ein gepoolter Median ≠ der Mittelwert der Mediane).

Tests

python -m pytest tests/portfolio/