{markdown_inline(stream["title"])}
{markdown_inline(stream["claim"])}
{markdown_inline(stream["meaning"])}#!/usr/bin/env python3
import json
import re
from datetime import datetime
from html import escape
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
WORKSPACE = ROOT.parent
OUT = ROOT / "understanding_site"
DATA_JS = OUT / "site-data.js"
INDEX = OUT / "index.html"
PORTFOLIO_HTML = OUT / "portfolio-map.html"
RESULT = OUT / "result.json"
TEXT_EXTENSIONS = {
".md",
".json",
".jsonl",
".yaml",
".yml",
".html",
".txt",
".sh",
".py",
}
RECOMMENDED_READING = [
"ProjectIntakeTower/PROJECT_PORTFOLIO_MAP_V1.md",
"ProjectIntakeTower/visual_summary/project_learning_graphic.html",
"ProjectIntakeTower/OWNER_DIGEST.md",
"ProjectIntakeTower/triage/TOP_10_NEXT_ACTIONS.md",
"ProjectIntakeTower/NIGHT_STOP.md",
]
STOP_LAYER_PATHS = [
"ProjectIntakeTower/PANIC_QUOTA_STOPLOSS.md",
"CONTROL_ROOM.md",
"ProjectIntakeTower/NIGHT_STOP.md",
"ProjectIntakeTower/jobs/running/STOP_NOW.md",
"ProjectIntakeTower/MORNING_RESUME.md",
]
CORE_ANCHOR_PATHS = [
"ProjectIntakeTower/PROJECT_PORTFOLIO_MAP_V1.md",
"ProjectIntakeTower/visual_summary/project_learning_graphic.html",
"ProjectIntakeTower/OWNER_DIGEST.md",
"ProjectIntakeTower/triage/TOP_10_NEXT_ACTIONS.md",
"ProjectIntakeTower/jobs/pending/",
"ProjectIntakeTower/verifier/",
"ProjectIntakeTower/visual_summary/",
"ProjectIntakeTower/inventory/projects.jsonl",
"ProjectIntakeTower/inventory/project_cards/",
]
RAW_MASS_PATHS = [
"ProjectIntakeTower/triage/HUMAN_DECISION_REQUIRED.md",
"ProjectIntakeTower/triage/BACKLOG.md",
"ProjectIntakeTower/inventory/evidence/",
"ProjectIntakeTower/inventory/raw_scan.jsonl",
]
def rel_workspace(path):
return path.resolve().relative_to(WORKSPACE.resolve()).as_posix()
def load_json(path, fallback):
try:
return json.loads(path.read_text(encoding="utf-8"))
except Exception:
return fallback
def is_probably_text(path):
if path.suffix.lower() in TEXT_EXTENSIONS:
return True
try:
chunk = path.read_bytes()[:4096]
except OSError:
return False
if b"\x00" in chunk:
return False
try:
chunk.decode("utf-8")
except UnicodeDecodeError:
return False
return True
def title_from_content(path, content):
if path.endswith(".md"):
match = re.search(r"^#\s+(.+)$", content, re.M)
if match:
return match.group(1).strip()
name = Path(path).name
return name.replace("_", " ").replace("-", " ")
def kind_for(path):
suffix = Path(path).suffix.lower().lstrip(".")
return suffix or "text"
def group_for(path):
if path == "CONTROL_ROOM.md":
return "Control Layer"
if path.startswith("__generated__/"):
return "Guide"
if "PANIC" in path or "NIGHT_STOP" in path or "MORNING_RESUME" in path or "STOP_NOW" in path:
return "Control Layer"
if "/triage/" in path:
return "Triage"
if "/jobs/" in path:
return "Jobs"
if "/inventory/" in path:
return "Inventory"
if "/github/" in path:
return "GitHub Drafts"
if "/verifier/" in path or "/scripts/" in path:
return "Pipeline"
if "/visual_summary/" in path or "/explainers/" in path:
return "Visual Explainability"
if "/consolidation_decision/" in path or "CONSOLIDATION" in path:
return "Consolidation"
if "/archive_plan/" in path:
return "Archive"
if "/small_fix/" in path or "/test_generation/" in path or "/verifier_creation/" in path or "/doc_reality_sync/" in path:
return "Generated Work"
return "Root"
def workstream_for(path):
if path.startswith("__generated__/"):
return "Guide"
if path in RAW_MASS_PATHS or any(path.startswith(prefix) for prefix in RAW_MASS_PATHS if prefix.endswith("/")):
return "Raw"
if path in STOP_LAYER_PATHS:
return "Safety"
if path == "CONTROL_ROOM.md":
return "Safety"
if "PANIC" in path or "NIGHT_STOP" in path or "MORNING_RESUME" in path or "STOP_NOW" in path:
return "Safety"
if "/consolidation_decision/" in path or "CONSOLIDATION_DECISION" in path:
return "Safety"
if "/doc_reality_sync/" in path or "/small_fix/" in path or "/test_generation/" in path or "/verifier_creation/" in path:
return "Raw"
if path in CORE_ANCHOR_PATHS or any(path.startswith(prefix) for prefix in CORE_ANCHOR_PATHS if prefix.endswith("/")):
return "Core"
if "/triage/" in path or "/jobs/" in path or "/verifier/" in path or "/scripts/" in path or "/github/issue_drafts/" in path:
return "Core"
if "/inventory/projects.jsonl" in path or "/inventory/project_cards/" in path:
return "Core"
if "/visual_summary/" in path:
return "Core"
return "Raw"
def priority_for(path):
if path.startswith("__generated__/"):
return 1000
if path in RECOMMENDED_READING:
return 980 - (RECOMMENDED_READING.index(path) * 10)
if path in STOP_LAYER_PATHS:
return 900
if workstream_for(path) == "Core":
return 760
if workstream_for(path) == "Safety":
return 740
if "/triage/" in path:
return 680
if "/jobs/running/" in path or "/jobs/done/" in path:
return 660
if "/consolidation_decision/" in path or "CONSOLIDATION" in path:
return 640
if "/inventory/project_cards/" in path:
return 420
if "/inventory/evidence/" in path:
return 360
return 300
def original_href(path):
if path.startswith("__generated__/"):
return ""
if path == "CONTROL_ROOM.md":
return "../../CONTROL_ROOM.md"
prefix = "ProjectIntakeTower/"
if path.startswith(prefix):
return "../" + path[len(prefix) :]
return ""
def collect_documents():
files = [WORKSPACE / "CONTROL_ROOM.md"]
for path in ROOT.rglob("*"):
if not path.is_file():
continue
rel = rel_workspace(path)
if rel.startswith("ProjectIntakeTower/understanding_site/"):
continue
if path.suffix.lower() in {".png", ".mp4", ".pyc"}:
continue
files.append(path)
docs = []
seen = set()
for path in files:
if not path.exists() or not is_probably_text(path):
continue
rel = rel_workspace(path)
if rel in seen:
continue
seen.add(rel)
try:
content = path.read_text(encoding="utf-8", errors="replace")
except OSError:
continue
stat = path.stat()
docs.append(
{
"path": rel,
"title": title_from_content(rel, content),
"kind": kind_for(rel),
"group": group_for(rel),
"workstream": workstream_for(rel),
"size": stat.st_size,
"mtime": datetime.fromtimestamp(stat.st_mtime).astimezone().isoformat(timespec="seconds"),
"priority": priority_for(rel),
"href": original_href(rel),
"content": content,
}
)
docs.extend(generated_documents())
docs.sort(key=lambda d: (-d["priority"], d["group"], d["path"]))
return docs
def generated_documents():
gains_md = """# Safety-Pattern und drei verwertbare Gewinne
Diese Gewinne gehoeren nicht zur normalen Produktarbeit von ProjectIntakeTower/Core. Sie gehoeren zur Safety-Seite: Kaskadenbewaeltigung, Stop-Loss, Containment und Wiederaufnahme.
## 1. Technischer Gewinn
Der Lauf war ein echter Agentic-Stress-Test. Der Owner-Befund lautet: ca. 45 Mio. Codex-Token, plus Hermes/OpenCode/Codex-Prozessspuren. Das ist Trainingsmaterial fuer Agent Engineering, weil der Stress nicht abstrakt war: er hat konkrete Artefakte, Jobs, Triage-Listen und Kontrollreaktionen erzeugt.
Evidenz: `CONTROL_ROOM.md`, `ProjectIntakeTower/PANIC_QUOTA_STOPLOSS.md`, `ProjectIntakeTower/NIGHT_STOP.md`.
## 2. System-Gewinn
Das System hat eigene Stop-Layer produziert: `PANIC_QUOTA_STOPLOSS.md`, `CONTROL_ROOM.md`, `NIGHT_STOP.md`, `STOP_NOW.md`. Das ist wertvoller als viele gebaute Features, weil es zeigt, dass der Stack Kontrollmechanismen entwickeln kann, sobald die Orchestrierung zu breit wird.
## 3. Produkt-Gewinn
Daraus wird ein wiederverwendbares Pattern: `Chaos Power Mode -> Stop-Loss -> Containment -> Morning Resume`. Das kann als Skill, Artikel, Vortrag, Blogpost oder Agent-Operating-Manual wiederverwendet werden.
"""
reading_md = """# Gefuehrte Lesereihenfolge
Nicht `triage/HUMAN_DECISION_REQUIRED.md` zuerst lesen. Das ist Rohmasse.
1. `PROJECT_PORTFOLIO_MAP_V1.md`: Verwertbare Ernte und Arbeitsrahmen.
2. `visual_summary/project_learning_graphic.html`: Visuelle Karte.
3. `OWNER_DIGEST.md`: Komprimierter Owner-Blick.
4. `triage/TOP_10_NEXT_ACTIONS.md`: Priorisierte naechste Handlungen.
5. `NIGHT_STOP.md`: Safety-Grenze und Restart-Regeln.
Danach mental trennen:
- `ProjectIntakeTower/Core` = echte Projektlandkarte.
- `ProjectIntakeTower/Safety` = Kaskadenkontrolle.
"""
now_md = """# Was jetzt zu tun ist
Der naechste Anker ist `ProjectIntakeTower/Core`, nicht ein neues Source-Projekt und nicht die gesamte Rohmasse.
Arbeitsregel: erst die vier empfohlenen Dokumente lesen, dann Core und Safety bewusst getrennt halten.
Default naechster Arbeitsblock: Core-Karte verstehen, Safety-Pattern als eigenes Betriebswissen markieren, dann maximal einen bounded Job aus `jobs/pending/` auswaehlen.
"""
now = datetime.now().astimezone().isoformat(timespec="seconds")
generated = []
for rel, title, content in [
("__generated__/DREI_GEWINNE.md", "Drei verwertbare Gewinne", gains_md),
("__generated__/LESEPFAD.md", "Gefuehrte Lesereihenfolge", reading_md),
("__generated__/JETZT_TUN.md", "Was jetzt zu tun ist", now_md),
]:
generated.append(
{
"path": rel,
"title": title,
"kind": "generated",
"group": "Guide",
"workstream": "Guide",
"size": len(content.encode("utf-8")),
"mtime": now,
"priority": priority_for(rel),
"href": "",
"content": content,
}
)
return generated
def summarize_jobs():
jobs_root = ROOT / "jobs"
out = {}
for state in ["pending", "done", "running", "failed"]:
folder = jobs_root / state
entries = []
if folder.exists():
for path in sorted(folder.rglob("*")):
if not path.is_file():
continue
rel = rel_workspace(path)
item = {"path": rel, "name": path.name, "size": path.stat().st_size}
if path.suffix == ".json":
data = load_json(path, {})
item["job_id"] = data.get("job_id") or data.get("id")
item["mode"] = data.get("mode") or data.get("job_mode")
item["project_path"] = data.get("project_path")
item["labels"] = data.get("labels") or data.get("tags") or []
entries.append(item)
out[state] = entries
return out
def load_all_projects():
pri = load_json(ROOT / "triage" / "PROJECT_PRIORITIZATION.json", {})
projects = pri.get("projects")
if not isinstance(projects, list):
by_path = {}
for rows in pri.get("categories", {}).values():
if not isinstance(rows, list):
continue
for row in rows:
path = row.get("path")
if path and path not in by_path:
by_path[path] = row
projects = list(by_path.values())
projects.sort(key=lambda p: p.get("score", 0), reverse=True)
return projects
def load_projects():
return load_all_projects()[:120]
def gain_cards():
return [
{
"title": "Technischer Gewinn",
"claim": "Echter Agentic-Stress-Test: ca. 45 Mio. Codex-Token als Owner-/Usage-Befund, plus belegte Hermes/OpenCode/Codex-Spuren.",
"why": "Das ist Trainingsmaterial fuer Agent Engineering: nicht als Theorie, sondern als reale Ueberlastung mit Artefakten, Verifiern und Jobs.",
"evidencePaths": [
"CONTROL_ROOM.md",
"ProjectIntakeTower/PANIC_QUOTA_STOPLOSS.md",
"ProjectIntakeTower/NIGHT_STOP.md",
],
"reuseIdeas": ["Agent Engineering Case Study", "Stress-Test Fixture", "Token-Burn Postmortem"],
},
{
"title": "System-Gewinn",
"claim": "Der Stack hat selbst Stop-Layer produziert: Panic Stop-Loss, Control Room, Night Stop und STOP_NOW.",
"why": "Das ist ein Kontrollmechanismus, nicht nur Output. Das System konnte seine eigene Expansion begrenzen.",
"evidencePaths": STOP_LAYER_PATHS,
"reuseIdeas": ["Stop-Loss Skill", "Operator Policy", "Containment Checklist"],
},
{
"title": "Produkt-Gewinn",
"claim": "Das wiederverwendbare Pattern lautet: Chaos Power Mode -> Stop-Loss -> Containment -> Morning Resume.",
"why": "Aus dem Chaos wird ein Produktbaustein: Skill, Artikel, Vortrag, Blogpost oder Agent-Operating-Manual.",
"evidencePaths": [
"ProjectIntakeTower/PANIC_QUOTA_STOPLOSS.md",
"CONTROL_ROOM.md",
"ProjectIntakeTower/NIGHT_STOP.md",
"ProjectIntakeTower/MORNING_RESUME.md",
],
"reuseIdeas": ["Operating Manual", "Talk Outline", "Blogpost Series"],
},
]
def workstream_cards():
return [
{
"id": "Core",
"title": "ProjectIntakeTower/Core",
"claim": "Echte Arbeit: Projektinventar, Triage, Top-10-Actions, Job-Contracts, Verifier, Visual Summary und Owner Digest.",
"meaning": "Das ist der 'Was habe ich eigentlich auf meinem System?'-Teil.",
},
{
"id": "Safety",
"title": "ProjectIntakeTower/Safety",
"claim": "Kaskadenkontrolle: Panic Stop-Loss, Control Room, Night Stop, STOP_NOW, Morning Resume und Safety-nahe Consolidator-Artefakte.",
"meaning": "Das ist Betriebsunfall-Management. Wertvoll, aber anders wertvoll als Produktarbeit.",
},
{
"id": "Raw",
"title": "Rohmasse",
"claim": "Vollstaendige, lange Artefakte wie HUMAN_DECISION_REQUIRED, Backlog, Evidence-JSONs und Generated Reports.",
"meaning": "Durchsuchbar, aber nicht zuerst lesen.",
},
]
def top_paths(docs, workstream, limit=12):
return [doc["path"] for doc in docs if doc["workstream"] == workstream and not doc["path"].startswith("__generated__/")][:limit]
def project_reasons(project):
return project.get("reasons") or project.get("score_reasons") or []
def compact_project(project):
return {
"name": project.get("name") or Path(project.get("path", "")).name,
"path": project.get("path", ""),
"score": project.get("score", 0),
"dirty_count": project.get("dirty_count", 0),
"branch_count": project.get("branch_count", 0),
"todo_fixme_count": project.get("todo_fixme_count", 0),
"plan_hit_count": project.get("plan_hit_count", 0),
"agent_artifact_count": project.get("agent_artifact_count", 0),
"duplicate_cluster": project.get("duplicate_cluster"),
"themes": project.get("themes", []),
"categories": project.get("categories", []),
"tech": project.get("tech"),
"reasons": project_reasons(project)[:4],
}
def next_agent_run_label(project):
categories = set(project.get("categories", []))
if "MERGE" in categories:
return "bounded consolidation review, not feature work"
if project.get("dirty_count", 0) >= 10:
return "dirty-state stabilization audit before any build"
if project.get("todo_fixme_count", 0) >= 20:
return "focused verifier/test pass"
if project.get("agent_artifact_count", 0):
return "artifact verification and closure"
return "small read-only audit, then decide"
def build_condensation(projects):
active = [
p for p in projects
if "KEEP" in p.get("categories", []) and "ARCHIVE" not in p.get("categories", []) and "PAUSE" not in p.get("categories", [])
][:14]
old_energy = sorted(
[
p for p in projects
if "PAUSE" in p.get("categories", []) or "ARCHIVE" in p.get("categories", []) or (
"TOKEN_BURN_CANDIDATE" in p.get("categories", []) and "KEEP" not in p.get("categories", [])
)
],
key=lambda p: (p.get("score", 0), p.get("plan_hit_count", 0), p.get("todo_fixme_count", 0)),
reverse=True,
)[:14]
dirty_danger = sorted(
[p for p in projects if p.get("dirty_count", 0) > 0],
key=lambda p: (p.get("dirty_count", 0), p.get("score", 0)),
reverse=True,
)[:14]
cluster_map = {}
for p in projects:
duplicate = p.get("duplicate_cluster")
if duplicate:
cluster_map.setdefault(f"duplicate:{duplicate}", []).append(p)
for theme in p.get("themes", []) or []:
cluster_map.setdefault(f"theme:{theme}", []).append(p)
clusters = []
for key, members in cluster_map.items():
if len(members) < 2:
continue
members = sorted(members, key=lambda p: p.get("score", 0), reverse=True)
clusters.append(
{
"name": key,
"count": len(members),
"top_score": members[0].get("score", 0),
"members": [compact_project(p) for p in members[:8]],
}
)
clusters.sort(key=lambda c: (c["count"], c["top_score"]), reverse=True)
next_agent = []
for p in projects:
categories = set(p.get("categories", []))
if "ARCHIVE" in categories or "PAUSE" in categories:
continue
if "KEEP" not in categories and "URGENT" not in categories:
continue
if p.get("score", 0) < 45 and p.get("dirty_count", 0) < 10:
continue
item = compact_project(p)
item["suggested_run"] = next_agent_run_label(p)
item["human_gate"] = "HUMAN_DECISION_REQUIRED" in categories or p.get("dirty_count", 0) > 0
next_agent.append(item)
next_agent = next_agent[:12]
return {
"questions": [
"Welche Projekte sind wirklich aktiv?",
"Welche sind nur alte Energie?",
"Welche haben gefaehrliche dirty states?",
"Welche gehoeren zusammen?",
"Wo lohnt sich ein echter naechster Agentenlauf?",
],
"activeProjects": [compact_project(p) for p in active],
"oldEnergy": [compact_project(p) for p in old_energy],
"dirtyDanger": [compact_project(p) for p in dirty_danger],
"clusters": clusters[:10],
"nextAgentRuns": next_agent,
}
def markdown_inline(text):
return re.sub(
r"\*\*([^*]+)\*\*",
r"\1",
re.sub(r"`([^`]+)`", r"\1", escape(str(text), quote=True)),
)
def render_markdown_fragment(content):
lines = str(content or "").splitlines()
html = []
list_type = None
in_code = False
code_lines = []
def flush_list():
nonlocal list_type
if list_type:
html.append(f"{list_type}>")
list_type = None
def open_list(tag):
nonlocal list_type
if list_type == tag:
return
flush_list()
html.append(f"<{tag}>")
list_type = tag
def flush_code():
nonlocal in_code, code_lines
if in_code:
html.append("
" + escape("\n".join(code_lines), quote=True) + "")
code_lines = []
in_code = False
for line in lines:
if line.startswith("```"):
if in_code:
flush_code()
else:
flush_list()
in_code = True
code_lines = []
continue
if in_code:
code_lines.append(line)
continue
if re.match(r"^\s*---+\s*$", line):
flush_list()
html.append("" + markdown_inline(line) + "
") flush_code() flush_list() return "\n".join(html) def extract_h2_section(content, heading): pattern = rf"^##\s+{re.escape(heading)}\s*\n(.*?)(?=^##\s+|\Z)" match = re.search(pattern, content, re.M | re.S) return match.group(1).strip() if match else "" def extract_h2_from_prefix(content, prefix): match = re.search(rf"^##\s+{re.escape(prefix)}.*$", content, re.M) return content[match.start():].strip() if match else "" def extract_h3_sections(content): matches = list(re.finditer(r"^###\s+(.+)$", content, re.M)) sections = [] for index, match in enumerate(matches): start = match.end() end = matches[index + 1].start() if index + 1 < len(matches) else len(content) sections.append({"title": match.group(1).strip(), "body": content[start:end].strip()}) return sections def extract_status(content): match = re.search(r"Status:\s*\n\s*([A-Z_]+)\.?", content) return match.group(1) if match else "" def status_class(status): lower = status.lower() if "stabilize" in lower: return "stabilize" if "human" in lower: return "human" if "archive" in lower: return "archive" if "merge" in lower: return "merge" return "secondary" def portfolio_metrics(assumptions, counts): metrics = [] for line in assumptions.splitlines(): match = re.match(r"^-\s+([^:]+):\s+(.+)$", line.strip()) if match: metrics.append({"label": match.group(1), "value": match.group(2)}) if metrics: return metrics[:8] return [ {"label": "Projekt-/Artefaktcluster", "value": counts.get("total_projects", "-")}, {"label": "Core-Dokumente", "value": counts.get("coreDocuments", "-")}, {"label": "Safety-Dokumente", "value": counts.get("safetyDocuments", "-")}, {"label": "Rohdokumente", "value": counts.get("rawDocuments", "-")}, ] def build_portfolio_model(data): doc = next((item for item in data["documents"] if item["path"] == data["portfolioMap"]), None) content = doc["content"] if doc else "" purpose = extract_h2_section(content, "Zweck") assumptions = extract_h2_section(content, "Was ich jetzt als wahr annehme") families = extract_h3_sections(extract_h2_section(content, "Meine wichtigsten Projektfamilien")) decisions = extract_h3_sections(extract_h2_section(content, "Meine Top-Entscheidungen, aber nicht alle heute")) ignore_today = extract_h2_section(content, "Was ich ab jetzt ignoriere") next_action = extract_h2_section(content, "Nächste konkrete Aktion") verifier = extract_h2_from_prefix(content, "Verifier-Ergebnis") return { "doc": doc, "content": content, "purpose": purpose, "assumptions": assumptions, "families": families, "decisions": decisions, "ignore_today": ignore_today, "next_action": next_action, "verifier": verifier, "metrics": portfolio_metrics(assumptions, data["counts"]), } def build_data(): summary = load_json(ROOT / "triage" / "PROJECT_PRIORITIZATION_SUMMARY.json", {}) docs = collect_documents() projects = load_all_projects() workstream_counts = {} for doc in docs: workstream_counts[doc["workstream"]] = workstream_counts.get(doc["workstream"], 0) + 1 return { "generatedAt": datetime.now().astimezone().isoformat(timespec="seconds"), "title": "ProjectIntakeTower Understanding Site", "counts": { **summary, "documents": len(docs), "textBytes": sum(d["size"] for d in docs if not d["path"].startswith("__generated__/")), "coreDocuments": workstream_counts.get("Core", 0), "safetyDocuments": workstream_counts.get("Safety", 0), "rawDocuments": workstream_counts.get("Raw", 0), }, "pattern": "Core = echte Projektlandkarte | Safety = Kaskadenkontrolle | Raw = nicht zuerst lesen", "safetyPattern": "Chaos Power Mode -> Stop-Loss -> Containment -> Morning Resume", "gains": gain_cards(), "workstreams": workstream_cards(), "portfolioMap": "ProjectIntakeTower/PROJECT_PORTFOLIO_MAP_V1.md", "portfolioMapHtml": "portfolio-map.html", "recommendedReading": RECOMMENDED_READING, "readingPath": RECOMMENDED_READING, "coreDocuments": top_paths(docs, "Core"), "safetyDocuments": top_paths(docs, "Safety"), "rawDocuments": top_paths(docs, "Raw"), "stopLayers": STOP_LAYER_PATHS, "projects": projects[:120], "condensation": build_condensation(projects), "jobs": summarize_jobs(), "documents": docs, "visualAsset": "../visual_summary/project_learning_graphic.png", "narrativeSections": [ { "title": "Was passiert ist", "body": "PROJECT_PORTFOLIO_MAP_V1.md ist jetzt die verwertbare Ernte aus ProjectIntakeTower. Die Website trennt weiterhin echte Projektlandkarte, Safety-Kaskadenkontrolle und Rohmasse.", }, { "title": "Was jetzt wichtig ist", "body": "Der Mehrwert liegt in der Verdichtung: wirklich aktive Projekte, alte Energie, dirty risks, Zusammenhaenge und naechste echte Agentenlaeufe. Lies zuerst die Portfolio-Map und die vier stuetzenden Dokumente.", }, { "title": "Was nicht passieren darf", "body": "Nicht mit HUMAN_DECISION_REQUIRED.md starten. Das Dokument bleibt auffindbar, ist aber Rohmasse und kein guter Einstieg.", }, ], } def write_site_data(data): OUT.mkdir(parents=True, exist_ok=True) payload = json.dumps(data, ensure_ascii=False, separators=(",", ":")) DATA_JS.write_text("window.PROJECT_UNDERSTANDING_DATA = " + payload + ";\n", encoding="utf-8") def write_portfolio_map(data): model = build_portfolio_model(data) doc = model["doc"] or {} metrics_html = "\n".join( f'{markdown_inline(stream["claim"])}
{markdown_inline(stream["meaning"])}Die Markdown-Datei bleibt die Quelle. Diese Seite macht daraus eine greifbare Arbeitskarte: Was ist Core-Arbeit, was ist Safety, welche Projektfamilien gibt es, und welche Entscheidung kommt als naechstes.
Das ist der Teil, der wirklich Wert erzeugt hat: Inventar, Triage, Top-10-Actions, Job-Contracts, Verifier, Visual Summary und Owner Digest.
Nicht die einzelnen jobs/pending/*.json sind der Hauptwert, sondern diese zusammengezogene Projektkarte.
Das ist nicht normale Produktarbeit, sondern Betriebsunfall-Management. Es bleibt wertvoll, aber es gehoert in eine andere mentale Schublade.
Nicht mit triage/HUMAN_DECISION_REQUIRED.md starten. Lies zuerst die Portfolio-Map, dann die vier Dokumente, die sie tragen.
Die Tabelle zeigt die wichtigsten Projektknoten aus der vorhandenen Priorisierung. Externe Projektdateien werden hier nur referenziert.
| Projekt | Score | Status | Warum |
|---|