update
This commit is contained in:
@@ -19,9 +19,9 @@ ALLOWED_FORMATS = [
|
|||||||
FORMAT_META = {
|
FORMAT_META = {
|
||||||
"OnePager": {"pages": "1 Seite", "time": "~5 Min"},
|
"OnePager": {"pages": "1 Seite", "time": "~5 Min"},
|
||||||
"Cheatsheet": {"pages": "1 Seite", "time": "~10 Min"},
|
"Cheatsheet": {"pages": "1 Seite", "time": "~10 Min"},
|
||||||
"MiniGuide": {"pages": "3-4 Seiten", "time": "~15 Min"},
|
"MiniGuide": {"pages": "3-5 Seiten", "time": "~15-25 Min"},
|
||||||
"Guide": {"pages": "15-250 Seiten", "time": "variabel"},
|
"Guide": {"pages": "10-30 Seiten", "time": "variabel"},
|
||||||
"EndGuide": {"pages": "120-150 Seiten", "time": "~6h"},
|
"EndGuide": {"pages": "50-250 Seiten", "time": "variabel"},
|
||||||
}
|
}
|
||||||
|
|
||||||
AGENT_TIMEOUT = 3600
|
AGENT_TIMEOUT = 3600
|
||||||
|
|||||||
@@ -79,34 +79,57 @@ SCHRITT 3: Schreibe eine vollständige Wissensdatei nach {cache_path}.
|
|||||||
Die Datei muss als alleinige Faktenbasis für einen Lern-Guide ausreichen. Erfasse: Zweck, Architektur, Abläufe, wichtige Dateien, Konfiguration, Befehle, Datenstrukturen, Besonderheiten. Lass nichts Wichtiges aus. Schreibe NUR diese eine Datei."""
|
Die Datei muss als alleinige Faktenbasis für einen Lern-Guide ausreichen. Erfasse: Zweck, Architektur, Abläufe, wichtige Dateien, Konfiguration, Befehle, Datenstrukturen, Besonderheiten. Lass nichts Wichtiges aus. Schreibe NUR diese eine Datei."""
|
||||||
|
|
||||||
|
|
||||||
def _build_generator_prompt(topic: str, format_name: str, html_path: Path, instructions: str = "", project_content: str | None = None) -> str:
|
def _research_line(topic: str, project_content: str | None) -> str:
|
||||||
spec = (TEMPLATES_DIR / "Format" / f"{format_name}.md").read_text(encoding="utf-8")
|
|
||||||
reference = (TEMPLATES_DIR / "Referenz" / f"{format_name}.md").read_text(encoding="utf-8")
|
|
||||||
|
|
||||||
extra = f"\n\nZUSÄTZLICHE ANWEISUNGEN VOM NUTZER:\n{instructions}\n" if instructions else ""
|
|
||||||
|
|
||||||
if project_content:
|
if project_content:
|
||||||
research_line = (
|
return (
|
||||||
f'Die folgenden PROJEKT-INHALTE sind die Quelle der Wahrheit für "{topic}". '
|
f'Die folgenden PROJEKT-INHALTE sind die Quelle der Wahrheit für "{topic}". '
|
||||||
"Nutze sie als primäre Faktenbasis. Recherchiere per Websuche nur ergänzend, "
|
"Nutze sie als primäre Faktenbasis. Recherchiere per Websuche nur ergänzend, "
|
||||||
"um fehlende oder sich ändernde Fakten (z. B. aktuelle Versionsnummern externer Tools) zu prüfen.\n\n"
|
"um fehlende oder sich ändernde Fakten (z. B. aktuelle Versionsnummern externer Tools) zu prüfen.\n\n"
|
||||||
f"PROJEKT-INHALTE (Quelle der Wahrheit):\n{project_content}"
|
f"PROJEKT-INHALTE (Quelle der Wahrheit):\n{project_content}"
|
||||||
)
|
)
|
||||||
else:
|
return f'Recherchiere zuerst die aktuelle Version und aktuelle Fakten zu "{topic}" per Websuche, damit Versionsnummern und Angaben stimmen.'
|
||||||
research_line = f'Recherchiere zuerst die aktuelle Version und aktuelle Fakten zu "{topic}" per Websuche, damit Versionsnummern und Angaben stimmen.'
|
|
||||||
|
|
||||||
|
def _build_inventory_prompt(topic: str, format_name: str, inventory_path: Path, instructions: str = "", project_content: str | None = None) -> str:
|
||||||
|
spec = (TEMPLATES_DIR / "Format" / f"{format_name}.md").read_text(encoding="utf-8")
|
||||||
|
extra = f"\n\nZUSÄTZLICHE ANWEISUNGEN VOM NUTZER:\n{instructions}\n" if instructions else ""
|
||||||
|
|
||||||
|
return f"""Erstelle das Themeninventar für einen Lern-Guide zum Thema "{topic}" im Format "{format_name}".
|
||||||
|
|
||||||
|
{_research_line(topic, project_content)}
|
||||||
|
|
||||||
|
Das Inventar ist eine durchnummerierte Liste der Bausteine (Konzepte/Funktionen/Features), die der Guide abdecken muss — bereits in sinnvolle Teile/Sektionen gruppiert. Die ABDECKUNGS-Regel der Format-Spezifikation bestimmt die Auswahl; wie viele Punkte das sind, hängt vom Thema ab. Ein anderer Agent schreibt den Guide später strikt nach diesem Inventar — jeder Punkt wird eine Sektion.
|
||||||
|
|
||||||
|
Schreibe NUR die Inventar-Datei nach: {inventory_path}
|
||||||
|
Kein HTML, kein weasyprint.
|
||||||
|
|
||||||
|
FORMAT-SPEZIFIKATION (relevant sind ABDECKUNG und Seitenrahmen):
|
||||||
|
{spec}
|
||||||
|
{extra}"""
|
||||||
|
|
||||||
|
|
||||||
|
def _build_generator_prompt(topic: str, format_name: str, html_path: Path, inventory: str, instructions: str = "", project_content: str | None = None) -> str:
|
||||||
|
spec = (TEMPLATES_DIR / "Format" / f"{format_name}.md").read_text(encoding="utf-8")
|
||||||
|
reference = (TEMPLATES_DIR / "Referenz" / f"{format_name}.md").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
extra = f"\n\nZUSÄTZLICHE ANWEISUNGEN VOM NUTZER:\n{instructions}\n" if instructions else ""
|
||||||
|
|
||||||
return f"""Erstelle einen Lern-Guide zum Thema "{topic}" im Format "{format_name}".
|
return f"""Erstelle einen Lern-Guide zum Thema "{topic}" im Format "{format_name}".
|
||||||
|
|
||||||
{research_line}
|
{_research_line(topic, project_content)}
|
||||||
|
|
||||||
Schreibe die HTML-Datei nach: {html_path}
|
Schreibe die HTML-Datei nach: {html_path}
|
||||||
|
|
||||||
Schreibe NUR die HTML-Datei. Führe KEIN weasyprint aus, erzeuge KEINE PDF. Das übernimmt ein anderer Prozess.
|
Schreibe NUR die HTML-Datei. Führe KEIN weasyprint aus, erzeuge KEINE PDF. Das übernimmt ein anderer Prozess.
|
||||||
|
|
||||||
|
THEMENINVENTAR (verbindlich — von einem Recherche-Agenten erstellt):
|
||||||
|
Jeder Inventar-Punkt muss im Guide als eigene Sektion umgesetzt werden. Nicht zusammenfassen, nicht kürzen, nichts weglassen. Der Umfang des Guides folgt aus diesem Inventar innerhalb des Seitenrahmens der Spezifikation.
|
||||||
|
{inventory}
|
||||||
|
|
||||||
FORMAT-SPEZIFIKATION:
|
FORMAT-SPEZIFIKATION:
|
||||||
{spec}
|
{spec}
|
||||||
|
|
||||||
REFERENZ-IMPLEMENTIERUNG (Stil-Vorlage, adaptiere für "{topic}"):
|
REFERENZ-IMPLEMENTIERUNG (NUR Stil-Vorlage: Bausteine, CSS, Tonalität. Umfang und Struktur kommen aus dem INVENTAR, nicht aus der Referenz):
|
||||||
{reference}
|
{reference}
|
||||||
{extra}"""
|
{extra}"""
|
||||||
|
|
||||||
@@ -222,9 +245,27 @@ async def generate_guide(guide_id: str, topic: str, format_name: str, instructio
|
|||||||
return
|
return
|
||||||
project_content = cache_path.read_text(encoding="utf-8")
|
project_content = cache_path.read_text(encoding="utf-8")
|
||||||
|
|
||||||
# Step 1: Generator-Agent erstellt HTML
|
# Step 1: Inventar-Agent recherchiert die Bausteine des Themas
|
||||||
|
inventory_path = html_path.with_suffix(".inventar.md")
|
||||||
|
await _set_progress(guide_id, "Erstelle Themeninventar…")
|
||||||
|
current_step = "Inventar"
|
||||||
|
inv_prompt = _build_inventory_prompt(topic, format_name, inventory_path, instructions, project_content)
|
||||||
|
returncode, inv_out, inv_err = await run_agent(guide_id, inv_prompt, AGENT_TIMEOUT, provider=provider, role="fast", capabilities="full")
|
||||||
|
|
||||||
|
if guide_id in _cancelled:
|
||||||
|
return
|
||||||
|
if returncode != 0:
|
||||||
|
await _fail(guide_id, _claude_error("Inventar-Fehler", returncode, inv_out, inv_err))
|
||||||
|
return
|
||||||
|
if not inventory_path.exists():
|
||||||
|
await _fail(guide_id, "Themeninventar wurde nicht erstellt")
|
||||||
|
return
|
||||||
|
inventory = inventory_path.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
# Step 2: Generator-Agent erstellt HTML nach Inventar
|
||||||
await _set_progress(guide_id, "Generiere HTML…")
|
await _set_progress(guide_id, "Generiere HTML…")
|
||||||
gen_prompt = _build_generator_prompt(topic, format_name, html_path, instructions, project_content)
|
current_step = "Generierung"
|
||||||
|
gen_prompt = _build_generator_prompt(topic, format_name, html_path, inventory, instructions, project_content)
|
||||||
returncode, stdout, stderr = await run_agent(guide_id, gen_prompt, AGENT_TIMEOUT, provider=provider, role="guide", capabilities="full")
|
returncode, stdout, stderr = await run_agent(guide_id, gen_prompt, AGENT_TIMEOUT, provider=provider, role="guide", capabilities="full")
|
||||||
|
|
||||||
if guide_id in _cancelled:
|
if guide_id in _cancelled:
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ async def remove(guide_id: str):
|
|||||||
raise HTTPException(404, "Guide nicht gefunden")
|
raise HTTPException(404, "Guide nicht gefunden")
|
||||||
html_path, pdf_path = final_paths(guide["topic"], guide["format"])
|
html_path, pdf_path = final_paths(guide["topic"], guide["format"])
|
||||||
html_path.unlink(missing_ok=True)
|
html_path.unlink(missing_ok=True)
|
||||||
|
html_path.with_suffix(".inventar.md").unlink(missing_ok=True)
|
||||||
pdf_path.unlink(missing_ok=True)
|
pdf_path.unlink(missing_ok=True)
|
||||||
await delete_progress(guide_id)
|
await delete_progress(guide_id)
|
||||||
await delete_guide(guide_id)
|
await delete_guide(guide_id)
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
END-GUIDE-STIL (HTML/CSS → PDF via WeasyPrint)
|
END-GUIDE-STIL (HTML/CSS → PDF via WeasyPrint)
|
||||||
|
|
||||||
FORMAT
|
FORMAT
|
||||||
- A4 Hochformat, ~120–150 Seiten
|
- A4 Hochformat, 50–250 Seiten (themenabhängig — kleines Thema kurz,
|
||||||
|
großes Thema lang; die Seitenzahl folgt aus dem Inventar)
|
||||||
- @page { size: A4; margin: 18mm; }
|
- @page { size: A4; margin: 18mm; }
|
||||||
- Cover-Seite + automatisches Inhaltsverzeichnis
|
- Cover-Seite + automatisches Inhaltsverzeichnis
|
||||||
- Footer: Seitenzahl Mitte, "PHP EndGuide" rechts
|
- Footer: Seitenzahl Mitte, "<Thema> EndGuide" rechts
|
||||||
|
|
||||||
UMFANG (höchste Guide-Stufe)
|
ABDECKUNG (höchste Guide-Stufe)
|
||||||
- 17 Teile, 97 durchnummerierte Kapitel
|
- ALLE Bausteine des Themas — vollständig, "lieber zu viel als zu wenig".
|
||||||
- Anspruch: vollständig, "lieber zu viel als zu wenig"
|
- Von der ersten Zeile bis zu Experten-Themen (Architektur, Interna, Betrieb —
|
||||||
- Von der ersten Zeile bis zu Experten-Themen (Architektur, Async, Betrieb)
|
was immer beim Thema die Expertenstufe ist).
|
||||||
- Zielversion PHP 8.5
|
- Aktuelle Version des Themas als Zielversion nennen.
|
||||||
|
|
||||||
|
THEMENINVENTAR (verbindlich)
|
||||||
|
- Das Inventar wird vorab von einem Recherche-Agenten erstellt und mitgeliefert.
|
||||||
|
Es ist die verbindliche Stoffliste: 1 Inventar-Punkt = 1 EIGENE H2-Sektion
|
||||||
|
nach dem Muster Titel·Erklärung·Beispiel.
|
||||||
|
- Punkte beim Schreiben NICHT zusammenfassen, kürzen oder eindampfen — wirkt
|
||||||
|
das Pensum zu groß, Teil für Teil abarbeiten statt komprimieren.
|
||||||
|
- Teile und Kapitel aus dem Inventar ableiten: verwandte Punkte zu Kapiteln
|
||||||
|
gruppieren, Kapitel zu Teilen. Es gibt KEINE Vorgabe-Zahl für Teile/Kapitel.
|
||||||
|
|
||||||
ZIELGRUPPE — VOM ANFÄNGER ZUM EXPERTEN
|
ZIELGRUPPE — VOM ANFÄNGER ZUM EXPERTEN
|
||||||
- Beginnt bei null, steigert sich progressiv über die Teile
|
- Beginnt bei null, steigert sich progressiv über die Teile
|
||||||
@@ -22,46 +32,46 @@ KERNPRINZIP — TITEL · ERKLÄRUNG · BEISPIEL (das definierende Muster)
|
|||||||
- JEDES Konzept in genau dieser Reihenfolge:
|
- JEDES Konzept in genau dieser Reihenfolge:
|
||||||
1. Titel: reiner Konzept-/Verb-/Typname. Nichts sonst.
|
1. Titel: reiner Konzept-/Verb-/Typname. Nichts sonst.
|
||||||
2. Erklärung: 1–3 Sätze Prosa. Nennt die Funktionen/Bausteine und was sie tun.
|
2. Erklärung: 1–3 Sätze Prosa. Nennt die Funktionen/Bausteine und was sie tun.
|
||||||
3. Beispiel: lauffähiger Code mit sichtbarem Ergebnis als Kommentar.
|
3. Beispiel: lauffähiger Code (bzw. konkretes Beispiel) mit sichtbarem
|
||||||
|
Ergebnis als Kommentar.
|
||||||
- Die Überschrift trägt NIE die Funktionsliste oder die Definition:
|
- Die Überschrift trägt NIE die Funktionsliste oder die Definition:
|
||||||
- schlecht: "Ersetzen: str_replace & substr_replace"
|
- schlecht: "Ersetzen: str_replace & substr_replace"
|
||||||
"object – Instanz einer Klasse"
|
"object – Instanz einer Klasse"
|
||||||
- gut: "Ersetzen" + Erklärung nennt str_replace/substr_replace + Beispiel
|
- gut: "Ersetzen" + Erklärung nennt die Funktionen + Beispiel
|
||||||
"object" + Erklärung "Instanz einer Klasse" + Beispiel
|
"object" + Erklärung "Instanz einer Klasse" + Beispiel
|
||||||
|
|
||||||
INHALTLICHE PRINZIPIEN
|
INHALTLICHE PRINZIPIEN
|
||||||
- Vollständigkeit: aufzählbare Mengen IMMER komplett (alle Operatoren, alle
|
- Vollständigkeit: aufzählbare Mengen IMMER komplett (alle Operatoren, alle
|
||||||
Zuweisungs-Kurzformen, alle Vergleiche, alle Sortiervarianten …). Nur sehr
|
Varianten, alle Modi …). Nur sehr große Mengen (z. B. hunderte
|
||||||
große Mengen (z. B. Datums-Formatzeichen) als Auswahl + Verweis auf die Doku.
|
Formatzeichen) als Auswahl + Verweis auf die Doku.
|
||||||
- Mechanik zeigen: Beispiele sind echte, lauffähige Mini-Demos MIT Ausgabe –
|
- Mechanik zeigen: Beispiele sind echte, lauffähige Mini-Demos MIT Ausgabe –
|
||||||
nicht nur Signaturen oder leere Interfaces. Bei Mustern/Interfaces:
|
nicht nur Signaturen oder leere Interfaces. Bei Mustern/Interfaces:
|
||||||
Vertrag + konkrete Implementierung + Aufruf mit sichtbarem Ergebnis.
|
Vertrag + konkrete Implementierung + Aufruf mit sichtbarem Ergebnis.
|
||||||
- Tiefe vor Aufzählung: erst erklären warum/wann, dann zeigen.
|
- Tiefe vor Aufzählung: erst erklären warum/wann, dann zeigen.
|
||||||
- Keine Performance-Zahlen ohne Quelle.
|
- Keine Performance-Zahlen ohne Quelle.
|
||||||
|
|
||||||
CODE-KONVENTIONEN
|
CODE-KONVENTIONEN (bei technischen Themen)
|
||||||
- Bezeichner englisch: Variablen, Funktionen, Klassen, Methoden, Konstanten,
|
- Bezeichner englisch: Variablen, Funktionen, Klassen, Methoden, Konstanten.
|
||||||
Enum-Fälle.
|
|
||||||
- Deutsch bleibt: Fließtext, Überschriften, Code-Kommentare, Ausgabetexte,
|
- Deutsch bleibt: Fließtext, Überschriften, Code-Kommentare, Ausgabetexte,
|
||||||
Beispieldaten ("Anna", "Köln", "Hallo Welt").
|
Beispieldaten ("Anna", "Köln", "Hallo Welt").
|
||||||
- Unverändert: PHP-eigene Namen (count, $_GET, int …); SQL-Tabellen-/
|
- Unverändert: themen-/spracheigene Namen (Built-ins, Standard-APIs);
|
||||||
Spaltennamen in Strings (= Daten, kein PHP-Bezeichner).
|
Tabellen-/Spaltennamen in Strings (= Daten, keine Bezeichner).
|
||||||
- Ergebnis-Kommentar an jedem Beispiel: // 19.99 €
|
- Ergebnis-Kommentar an jedem Beispiel: // 19.99 €
|
||||||
- Neutrale Daten: Namen Anna/Ben/Tom, Orte Köln/Hamburg, mail@example.com.
|
- Neutrale Daten: Namen Anna/Ben/Tom, Orte Köln/Hamburg, mail@example.com.
|
||||||
Keine personenbezogenen oder echten Daten.
|
Keine personenbezogenen oder echten Daten.
|
||||||
- Moderne Syntax bevorzugen (match, Enums, Constructor Promotion, readonly,
|
- Moderne Syntax der aktuellen Zielversion bevorzugen; Versionsabhängiges
|
||||||
Property Hooks, Pipe |> …). Versionsabhängiges kennzeichnen ("seit 8.4",
|
kennzeichnen ("seit Version X").
|
||||||
"PHP 8.5").
|
|
||||||
|
|
||||||
STRUKTUR
|
STRUKTUR
|
||||||
1. Cover: Logo, Titel "PHP — Der EndGuide", Subtitle, Badge "17 Teile · 97 Kapitel"
|
1. Cover: Logo, Titel "<Thema> — Der EndGuide", Subtitle, Badge
|
||||||
|
"<N> Teile · <M> Kapitel" (Zahlen aus dem Inventar)
|
||||||
2. Inhaltsverzeichnis (automatisch aus der Struktur erzeugt)
|
2. Inhaltsverzeichnis (automatisch aus der Struktur erzeugt)
|
||||||
3. Pro Teil: Trennseite (Teil-Nummer · Titel · Beschreibung · Kapitel-Liste)
|
3. Pro Teil: Trennseite (Teil-Nummer · Titel · Beschreibung · Kapitel-Liste)
|
||||||
4. Pro Kapitel: Kapitel-Nummer + Titel, kurzer Lead-Satz, dann H2-Sektionen
|
4. Pro Kapitel: Kapitel-Nummer + Titel, kurzer Lead-Satz, dann H2-Sektionen
|
||||||
nach dem Muster Titel·Erklärung·Beispiel
|
nach dem Muster Titel·Erklärung·Beispiel
|
||||||
|
|
||||||
NUMMERIERUNG
|
NUMMERIERUNG
|
||||||
- Teile (1–17) und Kapitel (durchlaufend 1–97) sind GETRENNTE Zähler.
|
- Teile und Kapitel sind GETRENNTE Zähler.
|
||||||
- Kapitel laufen über den ganzen Guide durch – sie starten NICHT je Teil neu.
|
- Kapitel laufen über den ganzen Guide durch – sie starten NICHT je Teil neu.
|
||||||
- "Teil 7" ≠ "Kapitel 7".
|
- "Teil 7" ≠ "Kapitel 7".
|
||||||
|
|
||||||
@@ -76,30 +86,38 @@ ELEMENTE
|
|||||||
Erklärung + Beispiel inline.
|
Erklärung + Beispiel inline.
|
||||||
|
|
||||||
TYPOGRAFIE & FARBEN (max 3 + Neutrals)
|
TYPOGRAFIE & FARBEN (max 3 + Neutrals)
|
||||||
- Hauptfarbe: PHP-Violett; dunkle Code-Blöcke (#1e2a3a-Familie).
|
- Hauptfarbe: an offizielle Farbe des Themas anlehnen; dunkle Code-Blöcke
|
||||||
|
(#1e2a3a-Familie).
|
||||||
- Body Serif; Überschriften Sans-Serif bold; Code Monospace.
|
- Body Serif; Überschriften Sans-Serif bold; Code Monospace.
|
||||||
- max. 3 Schriftgrößen pro Sektion.
|
- max. 3 Schriftgrößen pro Sektion.
|
||||||
|
|
||||||
CALLOUT-NUTZUNG
|
CALLOUT-NUTZUNG
|
||||||
- tip (✓): Best Practice / Empfehlung.
|
- tip (✓): Best Practice / Empfehlung.
|
||||||
- warn (!): Sicherheits- oder Stolperfalle (SQL-Injection, Session-Fixation,
|
- warn (!): Sicherheits- oder Stolperfalle.
|
||||||
ungeprüfte Uploads …).
|
- note (i): Hintergrund / Abgrenzung.
|
||||||
- note (i): Hintergrund / Abgrenzung ("ORM oder pures PDO?", "nebenläufig ≠
|
|
||||||
parallel").
|
|
||||||
|
|
||||||
BUILD-ARCHITEKTUR (strukturgetrieben)
|
BUILD-ARCHITEKTUR (strukturgetrieben)
|
||||||
- Eine Quelle der Wahrheit: STRUCTURE in build.py = Liste aus
|
- Eine Quelle der Wahrheit: STRUCTURE in build.py = Liste aus
|
||||||
(Teil-Kicker, Titel, Beschreibung, [Kapiteltitel]). Daraus entstehen
|
(Teil-Kicker, Titel, Beschreibung, [Kapiteltitel]) — direkt aus dem
|
||||||
Reihenfolge, Nummern, Inhaltsverzeichnis und Trennseiten automatisch.
|
Inventar abgeleitet. Daraus entstehen Reihenfolge, Nummern,
|
||||||
|
Inhaltsverzeichnis und Trennseiten automatisch.
|
||||||
- Inhalt in Modulen content_partN.py: CHAPTERS = { "Kapiteltitel": body_html }.
|
- Inhalt in Modulen content_partN.py: CHAPTERS = { "Kapiteltitel": body_html }.
|
||||||
|
Teil für Teil schreiben — nie den ganzen Guide in einem Stück. Nach jedem
|
||||||
|
Teil: H2-Sektionen gegen die Inventar-Punkte des Teils zählen, Fehlendes
|
||||||
|
sofort ergänzen, erst dann den nächsten Teil beginnen.
|
||||||
|
- build.py meldet am Ende die Gesamtzahl der H2-Sektionen; sie muss der
|
||||||
|
Anzahl der Inventar-Punkte entsprechen.
|
||||||
- Highlight-Span-Klassen im Code:
|
- Highlight-Span-Klassen im Code:
|
||||||
c=Kommentar, k=Keyword, s=String/Zahl, f=Funktion,
|
c=Kommentar, k=Keyword, s=String/Zahl, f=Funktion,
|
||||||
t=Typ/Klasse/Konstante/Enum-Fall, v=Variable, a=Attribut.
|
t=Typ/Klasse/Konstante, v=Variable, a=Attribut.
|
||||||
Inline-Code im Text: <code class="inline">.
|
Inline-Code im Text: <code class="inline">.
|
||||||
- Escaping im Code: < > & als < > & (z. B. ->, =>, &&).
|
- Escaping im Code: < > & als < > & (z. B. ->, =>, &&).
|
||||||
- scrub() filtert beim Bauen personenbezogene Reste (Namen/Orte/Mails) heraus.
|
- scrub() filtert beim Bauen personenbezogene Reste (Namen/Orte/Mails) heraus.
|
||||||
|
|
||||||
VERMEIDEN
|
VERMEIDEN
|
||||||
|
- Feste Teile-/Kapitel-/Seitenzahlen als Ziel (der Umfang folgt aus dem
|
||||||
|
Inventar, nicht umgekehrt).
|
||||||
|
- Inventar-Punkte zusammenfassen oder weglassen.
|
||||||
- Funktionsliste oder Definition in der Überschrift (Titel bleibt rein).
|
- Funktionsliste oder Definition in der Überschrift (Titel bleibt rein).
|
||||||
- Übersichts-/Referenztabellen ohne Erklärtext.
|
- Übersichts-/Referenztabellen ohne Erklärtext.
|
||||||
- Deutsche Code-Bezeichner.
|
- Deutsche Code-Bezeichner.
|
||||||
@@ -111,21 +129,20 @@ VERMEIDEN
|
|||||||
(page-break-inside: avoid).
|
(page-break-inside: avoid).
|
||||||
|
|
||||||
GENERIERUNG & PRÜFUNG
|
GENERIERUNG & PRÜFUNG
|
||||||
1. python3 build.py → guide.html (meldet Kapitel/Teile + Fortschritt %)
|
1. Inventar lesen, STRUCTURE daraus ableiten.
|
||||||
2. weasyprint guide.html guide.pdf
|
2. python3 build.py → guide.html (meldet Kapitel/Teile + Sektionen)
|
||||||
3. Auslieferung nach /mnt/user-data/outputs: cp html und cp pdf als GETRENNTE
|
3. weasyprint guide.html guide.pdf
|
||||||
Befehle ausführen – NICHT mit && nach einem grep verketten (grep gibt bei 0
|
4. Verifizieren — die Sollwerte kommen aus dem Inventar:
|
||||||
Treffern Exit 1, bricht die Kette ab → eine Datei würde stillschweigend fehlen).
|
- grep -c 'toc-part' == Anzahl Teile in STRUCTURE
|
||||||
4. In /outputs verifizieren:
|
- grep -c 'chapter-num' == Anzahl Kapitel in STRUCTURE
|
||||||
- pdfinfo PHP-EndGuide-Neu.pdf | grep Pages (Seitenzahl)
|
- grep -c '<h2' == Anzahl Inventar-Punkte (1 Punkt = 1 Sektion;
|
||||||
- grep -c 'toc-part' (= 17 Teile)
|
bei Differenz: fehlende Punkte ausarbeiten — NICHT das Inventar kürzen)
|
||||||
- grep -c 'chapter-num' (= 97 Kapitel)
|
- grep -c '<table>' == 0
|
||||||
- grep -c '<table>' (= 0)
|
- keine echten Namen/Orte/Mails
|
||||||
- grep -coE 'echte Namen/Orte/Mails' (= 0)
|
- Seitenzahl (pdfinfo) im Rahmen 50–250
|
||||||
5. Stichproben rendern (pdftoppm) und ansehen:
|
5. Stichproben rendern (pdftoppm) und ansehen:
|
||||||
- Überschrift = reiner Titel, Erklärung darunter, dann Beispiel?
|
- Überschrift = reiner Titel, Erklärung darunter, dann Beispiel?
|
||||||
- Code englisch, Erklärung und Kommentare deutsch?
|
- Code englisch, Erklärung und Kommentare deutsch?
|
||||||
- SQL-Strings als Daten unverändert?
|
|
||||||
- Codeblöcke/Callouts nicht über Seitenumbruch zerrissen?
|
- Codeblöcke/Callouts nicht über Seitenumbruch zerrissen?
|
||||||
- Cover, Inhaltsverzeichnis und Teil-Trennseiten korrekt?
|
- Cover, Inhaltsverzeichnis und Teil-Trennseiten korrekt?
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,11 @@ A guide is a short book. The structure is always the same three levels:
|
|||||||
- **Chapter** — one focused topic. Chapters flow continuously down the page (they do not force a page break); each is separated from the previous by spacing and its own heading block. **3–10 chapters per part**. Each chapter is numbered sequentially across the whole guide (Chapter 1, 2, 3 … regardless of part).
|
- **Chapter** — one focused topic. Chapters flow continuously down the page (they do not force a page break); each is separated from the previous by spacing and its own heading block. **3–10 chapters per part**. Each chapter is numbered sequentially across the whole guide (Chapter 1, 2, 3 … regardless of part).
|
||||||
- **Section** (`<h2>`) and **sub-section** (`<h3>`) — structure inside a chapter.
|
- **Section** (`<h2>`) and **sub-section** (`<h3>`) — structure inside a chapter.
|
||||||
|
|
||||||
Length scales with ambition: a compact guide is ~15–30 pages, a comprehensive one 80–250 pages. Decide based on the request and tell the reader the scope on the cover.
|
### Scope — coverage-driven (middle tier)
|
||||||
|
|
||||||
|
**10–30 pages, covering all important building blocks of the topic** — everything a practical user needs in real work. More selective than the EndGuide tier ("all building blocks"), far broader than the MiniGuide tier ("core building blocks only"). How much that is depends on the topic.
|
||||||
|
|
||||||
|
A **topic inventory** is produced beforehand by a research agent and supplied to you. It is binding: every inventory item must appear in the guide as its own section — do not merge, trim, or drop items. Derive parts and chapters from the inventory; part/chapter counts follow from it, there is no default number. Page count is an outcome within the 10–30 range, never a target. State the resulting scope on the cover (parts · chapters).
|
||||||
|
|
||||||
### Voice and content rules (apply to every topic)
|
### Voice and content rules (apply to every topic)
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,17 @@
|
|||||||
MINI-GUIDE-STIL (HTML/CSS → PDF via WeasyPrint)
|
MINI-GUIDE-STIL (HTML/CSS → PDF via WeasyPrint)
|
||||||
|
|
||||||
FORMAT
|
FORMAT
|
||||||
- A4 Hochformat, 3-4 Seiten
|
- A4 Hochformat, 3-5 Seiten
|
||||||
- @page { size: A4; margin: 18mm 18mm 16mm 18mm; }
|
- @page { size: A4; margin: 18mm 18mm 16mm 18mm; }
|
||||||
- Footer: Seitenzahl Mitte, Guide-Titel rechts
|
- Footer: Seitenzahl Mitte, Guide-Titel rechts
|
||||||
|
|
||||||
UMFANG (einheitlich mit allen Guide-Stufen)
|
ABDECKUNG (niedrigste Guide-Stufe)
|
||||||
- 1 Kapitel (oder besser: 4-6 Sektionen ohne Kapitel-Struktur)
|
- ALLE Kern-Bausteine des Themas — was man braucht, um anzufangen.
|
||||||
- ~1500 Wörter Fließtext
|
Welche das sind, hängt vom Thema ab.
|
||||||
- 5-7 Code-Beispiele (sehr kurz, 2-7 Zeilen)
|
- Das Themeninventar wird vorab von einem Recherche-Agenten erstellt und
|
||||||
- ~15 Min Lesezeit
|
mitgeliefert. Es ist verbindlich: jeder Punkt bekommt eine Sektion.
|
||||||
- 3-4 Seiten
|
- Sektionen ohne Kapitel-Struktur; Code-Beispiele sehr kurz (2-7 Zeilen)
|
||||||
|
- ~15-25 Min Lesezeit, 3-5 Seiten — diese Obergrenze gilt immer
|
||||||
|
|
||||||
ZIELGRUPPE — KOMPAKTER ANFÄNGER-EINSTIEG
|
ZIELGRUPPE — KOMPAKTER ANFÄNGER-EINSTIEG
|
||||||
- Echte Anfänger ohne Programmier-Vorwissen im Thema
|
- Echte Anfänger ohne Programmier-Vorwissen im Thema
|
||||||
|
|||||||
Reference in New Issue
Block a user