\section{OLLM}
\label{sec:ollm}

\ldeen{OLLM ist die ausführbare Buildschnittstelle des Bundles. Es liest das
Manifest, entdeckt Units, normalisiert Target und Sprache, erzeugt einen
isolierten Buildauftrag und lässt ihn von \code{latexmk} mit Lua\LaTeX\
ausführen. Dadurch müssen Quelldateien weder Jobnamen zerlegen noch den
Projektzustand erraten. Die allgemeine Befehlsform lautet}{OLLM is the
executable build interface of the bundle. It reads the manifest, discovers
units, normalizes the target and language, creates an isolated build request,
and runs it through \code{latexmk} with Lua\LaTeX. Source files therefore do
not need to parse job names or infer project state. The general command form is}:

\begin{verbatim}
ollm [globale Optionen] [Aktion] [Target] [Aktionsoptionen]
\end{verbatim}

\ldeen{Ohne Aktion wird \code{build} angenommen. Die mitgelieferten Targets
\code{slides}, \code{handout}, \code{screen} und \code{script} dürfen als
nacktes Wort stehen; projektdefinierte Targets werden eindeutig mit
\keyis*{--target}{NAME} gewählt}{If no action is given, \code{build} is
assumed. The supplied targets \code{slides}, \code{handout}, \code{screen},
and \code{script} may be written as bare words; project-defined targets are
selected unambiguously with \keyis*{--target}{NAME}}:

\begin{verbatim}
ollm slides --language=de
ollm build --target=script --language=en
\end{verbatim}

\subsection{\ldeen{Bauen: von einer Instanz bis zur Serie}{Building: From One Instance to a Series}}

\ldeen{Für die tägliche Arbeit in einer Unit genügt meist ein einzelner
Build. Ohne \option{--language} verwendet OLLM die Projektsprache, sofern das
Target sie unterstützt, sonst dessen erste konfigurierte Sprache.
\option{--source} ist standardmäßig \File{main.tex}}{For day-to-day work in
a unit, a single build is usually sufficient. Without \option{--language},
OLLM uses the project default language if supported by the target, otherwise
the target's first configured language. \option{--source} defaults to
\File{main.tex}}:

\begin{verbatim}
ollm build script --language=en
ollm build --target=slides --source=main.tex
\end{verbatim}

\ldeen{Der Scope bestimmt, wie weit die Auswahl reicht. \code{current} baut
eine Dokumentinstanz der aktuellen Unit. \code{unit} baut deren zulässige
Target-/Sprachmatrix. \code{series} baut eine Dokumentinstanz aller passenden
normalen Units, während \code{collection} die eindeutig passende
Integrationsunit des Dokumenttyps baut. Die letzten beiden Scopes funktionieren
auch aus der Projektwurzel}{The scope determines how far the selection reaches.
\code{current} builds one document instance of the current unit. \code{unit}
builds its permitted target/language matrix. \code{series} builds one
document instance of every applicable regular unit, whereas \code{collection}
builds the uniquely matching integration unit for the document type. The last
two scopes also work from the project root}:

\begin{verbatim}
ollm build --all --scope=unit
ollm handout --language=de --scope=series
ollm script --language=de --scope=collection
\end{verbatim}

\ldeen{\option{--all} erweitert die Matrix nur innerhalb des gewählten
Scopes; es bedeutet nicht automatisch "`das ganze Projekt"'.
\option{--rebuild} erzwingt einen vollständigen \code{latexmk}-Neubau.
\option{--dry-run} zeigt die normalisierte Auswahl, ohne \LaTeX\ zu starten,
und eignet sich zusammen mit \keyis*{--format}{json} für Werkzeuge und CI.}{
\option{--all} expands the matrix only within the selected scope; it does not
automatically mean "`the entire project"'. \option{--rebuild} forces a full
\code{latexmk} rebuild. \option{--dry-run} displays the normalized selection
without starting \LaTeX\ and, together with \keyis*{--format}{json}, is useful
for tools and CI.}

\ldeen{Serieninterne Referenzen und Integrationen bilden Abhängigkeiten.
\option{--resolve} baut veraltete Produzenten und Konsumenten in mehreren
Runden bis zu einem Fixpunkt. Eine logische Unit, die noch nie direkt gebaut
wurde, muss zunächst einmal in der benötigten Dokumentinstanz gebaut werden, damit
OLLM ihre ID dem Verzeichnis zuordnen kann.}{Cross-unit references and
integrations form dependencies. \option{--resolve} rebuilds stale producers
and consumers in several rounds until a fixed point is reached. A logical unit
that has never been built directly must first be built once in the required
document instance so that OLLM can associate its ID with its directory.}

\begin{verbatim}
ollm build script --language=de --resolve
\end{verbatim}

\subsection{\ldeen{Prüfen und Diagnostizieren}{Inspecting and Diagnosing}}

\ldeen{\code{report}, \code{check} und \code{doctor} beantworten drei
verschiedene Fragen. \code{report} beschreibt den bekannten Zustand:
Units, Dokumentinstanzen, Fassungen, Ausgabedateien und Abhängigkeiten. Befunde ändern
seinen Exitstatus nicht, solange der Zustand lesbar ist. \code{check} liest
dieselben Daten, bewertet Inkonsistenzen aber als Fehler und eignet sich daher
für eine Freigabeprüfung. Beide Befehle bauen nichts.}{\code{report},
\code{check}, and \code{doctor} answer three different questions.
\code{report} describes the known state: units, document instances, versions,
output files, and dependencies. Findings do not change its exit status as long as
the state is readable. \code{check} reads the same data but treats
inconsistencies as errors and is therefore suitable for a release check. Neither
command builds anything.}

\ldeen{Ein typischer Fehler macht den Unterschied greifbar: Fehlt auf einem
neuen Rechner das Paket \pkg{tagpax}, hilft \code{doctor}, weil die
Werkzeugkette unvollständig ist. Wurde dagegen \code{020-processes} nach einem
erfolgreichen Build verändert und das Gesamtskript verwendet noch dessen alten
Buildstand, meldet \code{check} den veralteten Projektzustand. \code{report}
eignet sich zuvor zur Ursachenforschung, weil es die beteiligten Buildstände
und Abhängigkeiten zeigt, ohne den Befund als Freigabefehler zu werten.}{A
typical failure makes the distinction concrete: if the \pkg{tagpax} package is
missing on a new machine, \code{doctor} helps because the toolchain is
incomplete. If, on the other hand, \code{020-processes} was changed after a
successful build and the combined notes still use its old build,
\code{check} reports stale project state. \code{report} is useful for
investigating the cause first because it shows the builds and dependencies
involved without treating the finding as a release failure.}

\begin{verbatim}
ollm report --scope=series
ollm check --scope=current --target=script --language=de
ollm check --format=json
\end{verbatim}

\ldeen{\code{doctor} prüft dagegen die Werkzeugkette: Perl,
\code{latexmk}, Lua\LaTeX, \code{kpsewhich}, den TOML-Parser und die
benötigten TeX-Pakete. In einem Projekt kommen Manifest, Definitionen,
Schreibbarkeit, Zustand und Shell-Escape-Policy hinzu. Verwenden Sie
\code{doctor}, wenn bereits die Umgebung fraglich ist, und \code{check},
wenn ein vorhandener Projektzustand widersprüchlich erscheint.}{
\code{doctor}, by contrast, checks the toolchain: Perl, \code{latexmk},
Lua\LaTeX, \code{kpsewhich}, the TOML parser, and required TeX packages.
Inside a project it also checks the manifest, definitions, writability, state,
and shell-escape policy. Use \code{doctor} when the environment itself is in
doubt, and \code{check} when an existing project state appears inconsistent.}

\begin{verbatim}
ollm doctor
ollm doctor --project-root=/path/to/project --format=json
\end{verbatim}

\subsection{\ldeen{Aufräumen und Zustände pflegen}{Cleaning and Maintaining State}}

\ldeen{OLLM trennt Buildverzeichnisse von den in die Serie übernommenen Dokumentinstanzen.
\code{clean --level=aux} entfernt Hilfsdateien, behält aber das lokale PDF;
\code{build} entfernt das isolierte Buildverzeichnis; \code{state}
entfernt diese Dokumentinstanzen; \code{all} kombiniert die letzten beiden.
Mit \option{--dry-run} sehen Sie zuerst den Löschplan. Scopes sind hier
\code{current}, \code{unit} und \code{series}.}{OLLM separates build
directories from document instances retained for the series. \code{clean --level=aux} removes
auxiliary files but retains the local PDF; \code{build} removes the isolated
build directory; \code{state} removes these document instances; and
\code{all} combines the last two. Use \option{--dry-run} to inspect the
deletion plan first. The available scopes here are \code{current},
\code{unit}, and \code{series}.}

\begin{verbatim}
ollm clean --level=aux
ollm clean --level=build --scope=unit --dry-run
ollm clean --level=state --scope=series
\end{verbatim}

\ldeen{\code{prune} beseitigt aufgegebene temporäre Zustände und ersetzte
ältere Buildstände. Zustände physisch entfernter Units werden nur mit
\option{--stale-units} einbezogen. Das ist absichtlich vorsichtiger als ein
pauschales Löschen von \code{.osglecture}, bei dem auch die bekannten
Zuordnungen logischer Unit-IDs verloren gehen.}{\code{prune} removes
abandoned temporary states and older, replaced build results. State belonging to
physically removed units is included only with \option{--stale-units}. This is
deliberately more cautious than deleting \code{.osglecture} wholesale,
which also loses known mappings of logical unit IDs.}

\begin{verbatim}
ollm prune --dry-run
ollm prune --stale-units
\end{verbatim}

\subsection{\ldeen{Bereitstellen}{Deployment}}

\ldeen{\code{deploy} kopiert bereits erfolgreich gebaute PDFs an die im
Manifest konfigurierten Zielorte. Es startet keinen Build und legt keine
Zielverzeichnisse an. Verwenden Sie daher zuerst \code{build} oder
\code{build --resolve} und danach \code{deploy}. In der Projektwurzel gilt
standardmäßig Scope \code{series}, in einer Unit \code{current}.}{
\code{deploy} copies already successfully built PDFs to destinations
configured in the manifest. It neither starts a build nor creates destination
directories. Therefore run \code{build} or \code{build --resolve} first,
then \code{deploy}. The default scope is \code{series} at the project root
and \code{current} inside a unit.}

\begin{verbatim}
ollm deploy handout --language=de --scope=series
ollm deploy --target=script --scope=collection
ollm deploy --all --overwrite
\end{verbatim}

\ldeen{Dateinamenschablonen können unter anderem Serien-ID, Unit-ID,
Ordnungskennung, Kapitel, Dokumenttyp, Sprache und Rolle verwenden. Eine
vorhandene identische Datei bleibt unverändert. Ob eine abweichende Datei
\option{--overwrite} verlangt, bestimmt
\option{security.overwrite}.}{File-name templates can use, among
other values, the series ID, unit ID, ordinal, chapter, document type,
language, and role. An existing identical file remains untouched. Whether a
different existing file requires \option{--overwrite} is controlled by
\option{security.overwrite}.}

\ldeen{Die bereitgestellten Kopien können mit eingeschränkten PDF-Rechten
versehen werden, etwa ohne Druckerlaubnis. Die Einschränkungen stehen in
\code{[deployment.permissions]} als Default für alle Dokumenttypen oder in
\code{[deployment.types.\meta{doctype}.permissions]}; eine eigene Tabelle eines
Dokumenttyps ersetzt den Default vollständig, \code{permissions = \{\}} hebt
ihn also auf. Nicht genannte Rechte bleiben erlaubt.}{Deployed copies can
carry restricted PDF permissions, for example without permission to print.
The restrictions are set in \code{[deployment.permissions]} as the default for
all document types or in
\code{[deployment.types.\meta{doctype}.permissions]}; a document type's own
table replaces the default completely, so \code{permissions = \{\}} lifts it.
Permissions that are not mentioned remain granted.}

\begin{verbatim}
[deployment.permissions]
print = "none"     # full | low | none
extract = false    # copy text and graphics
modify = false     # change page content
annotate = false   # add comments
form = false       # fill in forms and sign
assemble = false   # insert, delete, rotate pages

[deployment.types.handout]
permissions = {}   # handouts are meant to be printed
\end{verbatim}

\ldeen{\option{--permissions} ersetzt für einen Lauf die konfigurierten Rechte
aller Dokumenttypen, etwa \keyis*{--permissions}{print=none,extract=false};
\keyis*{--permissions}{all} deployt ohne Einschränkungen.}{\option{--permissions}
replaces the configured permissions of all document types for one run, for
example \keyis*{--permissions}{print=none,extract=false};
\keyis*{--permissions}{all} deploys without restrictions.}

\ldeen{Für eingeschränkte Kopien benötigt \OLLM\ das externe Programm
\code{qpdf}; \code{ollm doctor} meldet, ob es gefunden wird. Die Kopie wird
mit AES-256 verschlüsselt und öffnet ohne Kennwort; das Eigentümerkennwort ist
zufällig und wird nicht gespeichert, sofern Sie nicht mit
\keyis*{--owner-password}{KENNWORT} selbst eines angeben. Das gebaute Original
bleibt unverändert. Solche Einschränkungen lassen sich mit üblichen Werkzeugen leicht
entfernen; sie sind ein Hinweis an die Lesenden, keine Zugriffskontrolle.}{For
restricted copies, \OLLM\ needs the external program \code{qpdf};
\code{ollm doctor} reports whether it is found. The copy is encrypted with
AES-256 and opens without a password; the owner password is random and is not
stored unless you set one yourself with
\keyis*{--owner-password}{PASSWORD}. The built original remains unrestricted. Common tools remove such
restrictions easily; they are a hint to readers, not access control.}

\ldeen{Fehlt \code{qpdf}, fragt \code{deploy} im Terminal, ob die PDFs ohne
Einschränkungen kopiert werden sollen. Mit \option{--non-interactive} oder ohne
Terminal, etwa in CI, bricht es dagegen mit Exitcode~69 ab.}{If \code{qpdf} is
missing, \code{deploy} asks in the terminal whether to copy the PDFs without
restrictions. With \option{--non-interactive} or without a terminal, for
example in CI, it stops with exit code~69 instead.}

\subsection{\ldeen{Projekt anlegen und allgemeine Optionen}{Creating a Project and General Options}}

\ldeen{\code{ollm newproject} verlangt die Wahl der Profile mit
\keyis*{--profiles}{taggable|classic} und erzeugt ein neues
\File{ollmconfig.toml} sowie, falls noch nicht vorhanden,
\File{Include/projectconfig.tex} mit Dummy-Metadaten. \code{taggable}
stellt \cls{ltx-talk} und \cls{book} mit eingeschaltetem Tagging ein und
legt \File{Include/documentmetadata.tex} an; \code{classic} stellt
\cls{beamer} und \cls{scrbook} ohne Tagged PDF ein. Fehlt die Option,
erklärt der Befehl beide Varianten und schreibt nichts. Einzelne Targets
lassen sich danach im Manifest von Hand mischen. Der Befehl überschreibt
keine bestehende Datei. Für die
genaue Syntax einer installierten Version sind \code{ollm --help} und
\code{ollm --version} maßgeblich. Häufige globale Optionen sind
\keyis*{--config}{DATEI}, \keyis*{--project-root}{VERZEICHNIS},
\keyis*{--format}{text|json}, \keyis*{--color}{auto|always|never} und
\option{--non-interactive}.}{\code{ollm newproject} requires the profile
choice \keyis*{--profiles}{taggable|classic} and creates a new
\File{ollmconfig.toml} and, unless it already exists,
\File{Include/projectconfig.tex} with dummy metadata. \code{taggable}
selects \cls{ltx-talk} and \cls{book} with tagging switched on and creates
\File{Include/documentmetadata.tex}; \code{classic} selects \cls{beamer}
and \cls{scrbook} without Tagged PDF. Without the option the command
explains both variants and writes nothing. Single targets can be mixed by
hand in the manifest afterwards. The command never overwrites an existing
file. For the
exact syntax of an installed version, \code{ollm --help} and
\code{ollm --version} are authoritative. Common global options are
\keyis*{--config}{FILE}, \keyis*{--project-root}{DIRECTORY},
\keyis*{--format}{text|json}, \keyis*{--color}{auto|always|never}, and
\option{--non-interactive}.}

\ldeen{Für Builddiagnosen wählen \keyis*{--debug}{tex}, \code{ollm} oder
\code{tex+ollm} die Ausgabeschicht; \keyis*{--warnings}{all},
\code{important} oder \code{none} steuert die Warnungsmenge. Unbekannte
kompatible Minusoptionen werden beim Build an \code{latexmk} weitergereicht;
Optionen, die den kontrollierten Buildvertrag umgehen würden, weist OLLM
zurück.}{For build diagnostics, \keyis*{--debug}{tex}, \code{ollm}, or
\code{tex+ollm} selects the output layer; \keyis*{--warnings}{all},
\code{important}, or \code{none} controls warning verbosity. Compatible
unknown dash options are forwarded to \code{latexmk} during a build; OLLM
rejects options that would bypass the controlled build contract.}

\subsection{\ldeen{Vollständige Kommandoübersicht}{Complete Command Summary}}
\label{sec:ollm-reference}

\begin{description}
  \item[\code{build}] \ldeen{baut eine oder mehrere Instanzen einer Serie;
    dies ist die Standardaktion}{builds one or more instances of a series; this
    is the default action}.
  \item[\code{standalone}] \ldeen{baut eine manifestfreie Quelldatei anhand
    ihrer Klassenoptionen}{builds a manifest-free source file from its class
    options}.
  \item[\code{report}] \ldeen{beschreibt Units, Instanzen, Buildstände,
    Ausgabedateien und Abhängigkeiten, ohne sie zu bewerten}{describes units,
    instances, versions, output files, and dependencies without validating
    them}.
  \item[\code{check}] \ldeen{prüft denselben Zustand und liefert bei
    Inkonsistenzen einen Fehlerstatus}{validates the same state and returns a
    failing status for inconsistencies}.
  \item[\code{clean}] \ldeen{entfernt Daten gemäß \option{--level} und
    \option{--scope}}{removes data selected by \option{--level} and
    \option{--scope}}.
  \item[\code{prune}] \ldeen{entfernt ersetzte ältere Buildstände und optional den
    Zustand fehlender Units}{removes older, replaced build results and optionally the
    state of missing units}.
  \item[\code{doctor}] \ldeen{prüft Werkzeugkette und, innerhalb eines
    Projekts, dessen grundlegende Konfiguration}{checks the toolchain and,
    inside a project, its basic configuration}.
  \item[\code{deploy}] \ldeen{kopiert bereits gebaute PDFs nach den
    Deploymentregeln}{copies already built PDFs according to the deployment
    rules}.
  \item[\code{convertproject}] \ldeen{konvertiert ein altes
    \File{ollmconfig.pl} nach TOML und übernimmt erkennbare Metadaten aus
    \File{Include/lectdates.tex}}{converts a legacy \File{ollmconfig.pl} to
    TOML and imports recognizable metadata from
    \File{Include/lectdates.tex}}.
  \item[\code{newproject}] \ldeen{legt Manifest und TeX-Projektkonfiguration
    an und verwendet vorhandene Legacy-Dateien als Konvertierungsquelle}{creates
    the manifest and TeX project configuration, using existing legacy files as
    conversion sources}.
\end{description}

\paragraph{\ldeen{Targets und Aliase}{Targets and aliases}.}
\ldeen{Die eingebauten nackten Targetnamen sind \code{slides} mit den Aliasen
\code{beamer} und \code{presentation}, \code{handout}, \code{screen} sowie
\code{script} mit dem Alias \code{article}. Andere registrierte Targets werden mit
\keyis*{--target}{TARGET} gewählt.}{The built-in bare target names are
\code{slides}, with aliases \code{beamer} and \code{presentation},
\code{handout}, \code{screen}, and \code{script}, with alias \code{article}. Select other
registered targets with \keyis*{--target}{TARGET}.}

\paragraph{\ldeen{Alle OLLM-Optionen}{All OLLM options}.}
\begin{description}
  \item[\option{--help}, \option{-h}] \ldeen{Hilfe ausgeben}{show help}.
  \item[\option{--version}] \ldeen{Version ausgeben}{show the version}.
  \item[\keyis*{--format}{text|json}] \ldeen{menschen- oder
    maschinenlesbare Ausgabe}{human- or machine-readable output}.
  \item[\keyis*{--color}{auto|always|never}] \ldeen{Farbausgabe steuern}{control
    colored output}.
  \item[\option{--non-interactive}] \ldeen{interaktive Aktionen verbieten}{forbid
    interactive actions}.
  \item[\keyis*{--profiles}{taggable|classic}] \ldeen{Profilsatz des
    erzeugten Manifests; Pflicht für \code{newproject}, optional für
    \code{convertproject} (dort Vorgabe \code{classic})}{profile set of the
    generated manifest; required for \code{newproject}, optional for
    \code{convertproject} (default there: \code{classic})}.
  \item[\option{+enforce+}, \option{--enforce+}] \ldeen{das Präfix \code{+}
    für Aktions- und Targetwörter verlangen}{require the \code{+} prefix on
    action and target words}.
  \item[\option{--legacy}] \ldeen{ausdrücklich die alte
    \File{ollmconfig.pl} verwenden}{explicitly use the legacy
    \File{ollmconfig.pl}}.
  \item[\option{--overwrite}] \ldeen{Ersetzen erlauben, sofern die
    Projektpolicy dies zulässt}{allow replacement when permitted by project
    policy}.
  \item[\keyis*{--target}{TARGET}] \ldeen{Target wählen}{select a target}.
  \item[\keyis*{--language}{LANG}] \ldeen{Sprache wählen; kompatibel sind auch
    \code{lang=LANG} und \code{+lang=LANG}}{select a language; compatible forms
    are \code{lang=LANG} and \code{+lang=LANG}}.
  \item[\keyis*{--source}{FILE}] \ldeen{Hauptquelle wählen}{select the main
    source}.
  \item[\option{--all}] \ldeen{alle zulässigen Target-/Sprachkombinationen im
    Scope wählen}{select all permitted target/language combinations in the
    scope}.
  \item[\option{--resolve}] \ldeen{Abhängigkeiten bis zum Fixpunkt neu bauen}{rebuild
    dependencies to a fixed point}.
  \item[\option{--rebuild}] \ldeen{vollständigen \code{latexmk}-Neubau
    erzwingen}{force a complete \code{latexmk} rebuild}.
  \item[\option{--dry-run}] \ldeen{normalisierten Plan anzeigen, ohne ihn
    auszuführen}{show the normalized plan without executing it}.
  \item[\keyis*{--level}{aux|build|state|all}] \ldeen{Ebene für
    \code{clean} wählen}{select the level for \code{clean}}.
  \item[\keyis*{--scope}{current|unit|series|collection}] \ldeen{Reichweite für
    Build, Inspektion, Pflege oder Deployment wählen; nicht jede Aktion erlaubt
    jeden Wert}{select the range for building, inspection, maintenance, or
    deployment; not every action permits every value}.
  \item[\option{--stale-units}] \ldeen{bei \code{prune} auch physisch fehlende
    Units berücksichtigen}{include physically missing units in \code{prune}}.
  \item[\keyis*{--debug}{tex|ollm|tex+ollm}] \ldeen{Diagnoseebene wählen}{select
    the diagnostic layer}.
  \item[\keyis*{--warnings}{all|important|none}] \ldeen{Warnungsmenge wählen}{select
    warning verbosity}.
  \item[\keyis*{--config}{FILE}] \ldeen{Manifest ausdrücklich wählen}{select a
    manifest explicitly}.
  \item[\keyis*{--project-root}{DIR}] \ldeen{Projektwurzel ausdrücklich
    wählen}{select a project root explicitly}.
\end{description}

\ldeen{Unbekannte kompatible Minusoptionen werden nur bei Builds an
\code{latexmk} weitergegeben. Optionen, die Engine, Ausgabeformat oder
kontrollierte Sicherheitsparameter umgehen würden, werden abgewiesen. Für
\code{standalone} sind außer \option{--config} und \option{--project-root}
keine projektbezogenen Auswahloptionen zulässig.}{Compatible unknown dash
options are forwarded to \code{latexmk} only for builds. Options that would
bypass the engine, output format, or controlled security parameters are
rejected. For \code{standalone}, no project-related selection options other
than \option{--config} and \option{--project-root} are permitted.}
