\appendix
\section{Factor-graph framing}\label{sec:factor-graphs}

This appendix re-expresses the gates and verifiers of
Section~\ref{sec:methods} in the language of \emph{factor
graphs}~\cite{dellaert2017factor}, the formalism that underpins
fixed-lag smoothing in robotics state estimation.  The point is not
novelty: the Operon code described here already runs and has been the
subject of this paper.  The point is \emph{lineage}.  A recent
exposition by Dellaert frames factor graphs as a concrete, structured
implementation of the energy-based ``world models'' currently
discussed in the JEPA literature, and calls the resulting rolling-past
/ rolling-future loop STAG\footnote{Sense-Think-Act with Graphs.}~\cite{dellaert2026stag}.
In that vocabulary, Operon's runtime guards are a discrete-state STAG
loop over symbolic agent trajectories, and \texttt{behavioral\_stability\_windowed}
(Section~\ref{sec:task}) is its past-graph smoother.

Making this correspondence explicit does two things.  First, it gives
the wedge artefacts of Operon --- \texttt{StagnationGate},
\texttt{IntegrityGate}, and the certificate codec --- a citable prior
art: the analogues in SLAM have been used in production robotics for
two decades.  Second, it clarifies what Operon is and is not doing.
It is \emph{not} training an energy function.  It is running the
classical fixed-structure variant of the same loop --- factor topology
and residual predicates fixed in advance, solver replaced by a
verifier over a discrete symbolic state.  Section~\ref{sec:fg-limits}
records where the analogy stops.

\subsection{Factor graphs in one paragraph}\label{sec:fg-recap}

A factor graph is a bipartite graph with variable nodes $x_i$ and
factor nodes $\varphi_j$, where each factor $\varphi_j$ is a
non-negative function of its adjacent variables.  The joint
distribution factors as $p(\mathbf{x} \mid \mathbf{z}) \propto
\prod_j \varphi_j(\mathbf{x}_{\partial j})$ and, in energy form,
$E(\mathbf{x}) = -\log p(\mathbf{x} \mid \mathbf{z}) =
\sum_j E_j(\mathbf{x}_{\partial j})$.  In the STAG presentation two
graphs share a common variable $x_t$ at the current time and a
common dynamics model: a \emph{past graph} anchored at $x_{t-w},
\ldots, x_t$ with measurement factors $\varphi^{\text{obs}}$ from
sensors and dynamics factors $\varphi^{\text{dyn}}$ between
consecutive states (fixed-lag smoothing), and a \emph{future graph}
anchored at $x_t, \ldots, x_{t+h}$ with the same dynamics and
goal / objective factors (predictive control)~\cite{dellaert2026stag}.
Perception is smoothing; planning is control; both are energy
minimisation.

\subsection{Operon gates as a discrete STAG loop}\label{sec:fg-mapping}

We translate the ingredients of Section~\ref{sec:methods} term by
term.  Each paragraph tags its claim as either
\textbf{[implemented]} --- the cited code already discharges the
mapping directly, \textbf{[derived]} --- the mapping follows from
existing behaviour but is not surfaced at the named line, or
\textbf{[analogy]} --- the structure lines up but no single code
path instantiates it; this is a description layered on top.  The
validation surface per claim is summarised in
Section~\ref{sec:fg-validation}.

\paragraph{Variables. [analogy]}
The latent variable $x_t$ is the \emph{abstract agent state at
stage $t$} --- the tuple \texttt{(genome, expression, short-term
memory)} tracked by the Operon runtime between stages.  This is
not the LangGraph \texttt{GuardedState} dict
(\texttt{operon\_ai/convergence/guarded\_graph.py}:59), which also
carries compile-time plumbing (\texttt{messages},
\texttt{stage\_outputs}, \texttt{retry\_count},
\texttt{watcher\_state}); those fields are part of the runtime
envelope, not of the factor-graph reading.  $x_t$ is symbolic, not
Euclidean.

\paragraph{Measurement factors. [implemented]}
A measurement factor is a non-negative function of $x_t$ and an
observation $z_t$; high values indicate consistency.  In Operon:

\begin{itemize}[leftmargin=*,itemsep=2pt,topsep=2pt]
\item For \texttt{behavioral\_stability\_windowed}, the observation
  at stage $t$ is the per-window mean $x_t^{\text{(obs)}}$ computed
  by the verifier at
  \texttt{operon\_ai/core/certificate.py}:261, and the residual is
  $r_t = \max(0, x_t^{\text{(obs)}} - \tau)$ where $\tau$ is the
  stability threshold.  The factor is
  $\varphi^{\text{obs}}_t = \mathbb{1}[r_t = 0]$.  A violating window
  contributes a zero factor; the smoothed belief --- ``the system is
  stable over the last $W$ windows'' --- is the product
  $\prod_{i=t-W+1}^{t} \varphi^{\text{obs}}_i$, which equals
  $\mathbb{1}[\max_i x_i \le \tau]$ and recovers exactly the predicate
  of Section~\ref{sec:task}.
\item For \texttt{DNARepair.scan()}
  (\texttt{operon\_ai/state/dna\_repair.py}:268), the observation is
  the current $(\mathrm{hash}, \mathrm{gene\_count},
  \mathrm{expression}, \mathrm{required\_genes})$ and the residual is
  the number of damage reports emitted.  Each of the five scans ---
  checksum (\S291), gene-value (\S307), gene-count (\S335),
  expression (\S351), and required-gene presence (\S381) ---
  corresponds to one measurement-factor component; their conjunction
  is the integrity certificate.
\end{itemize}

\paragraph{Dynamics factors. [implemented]}
A dynamics factor $\varphi^{\text{dyn}}_t$ is a non-negative
function of $(x_{t-1}, x_t)$ that encodes which transitions are
admissible.  In Operon, the admissible transition from $x_{t-1}$ to
$x_t$ is recorded by the checkpoint written in
\texttt{StateCheckpoint}.  The dynamics-residual at stage $t$ is the
mismatch between what the checkpoint predicts and what
\texttt{DNARepair.scan} sees at $t$; this is the ``DSB analog''
(checksum mismatch) in \texttt{dna\_repair.py}:292--305.  Dynamics
factors are thus not learned; they are deterministic consistency
factors driven by the genome-hash invariant.

\paragraph{Pre-guard = repeated invariant re-validation. [implemented]}
\texttt{compile\_guarded\_graph}
(\texttt{operon\_ai/convergence/guarded\_graph.py}:93) installs a
\texttt{pre\_guard} node before every LLM stage.  The pre-guard runs
\texttt{DNARepair.scan(genome, checkpoint)} and halts the run if any
damage is detected (lines~187--199).  In factor-graph language: each
stage evaluates the measurement-factor conjunction at a single
$x_t$ against a \emph{static} checkpoint baseline and routes to
HALT if any residual is positive.  This is deliberately \emph{not}
a rolling past-graph smoother: there is no per-stage checkpoint
evolution, no $W$-step window over evolving states, and no MAP
re-estimate across stages.  The caller-supplied
\texttt{StateCheckpoint} is plumbed once into
\texttt{compile\_guarded\_graph} (lines~524--535) and closed over
inside \texttt{make\_pre\_guard}; the same object is then re-checked
by the pre-guard before every stage, and retry routing sends
control back through the pre-guard (lines~186--199, 448).  The factor-graph
reading of the pre-guard is therefore ``repeated invariant
re-validation against a fixed baseline,'' and a genuine past-graph
smoother --- with per-stage checkpoint advancement and a
bounded-lag window --- is a deliberate non-goal at this scope
(see Section~\ref{sec:fg-limits}).  The windowed \emph{verifier}
(Section~\ref{sec:fg-mapping}, Measurement factors) is what plays
the smoother role; the pre-guard is its one-step invariant
counterpart in the compiled runtime.

\paragraph{Future graph = post-guard. [implemented]}
The \texttt{post\_guard} in \texttt{compile\_guarded\_graph}
evaluates the stage output against a rubric
(\texttt{\_evaluate\_quality}, line~248), threads a simplified
watcher state, and routes RETRY / ESCALATE / HALT via
\texttt{\_route\_intervention} (line~300).  The $h$-step future
graph collapses to a single goal factor ``quality $\ge$
rubric-threshold''; if it fails, the conditional router fires.
This is the degenerate but operationally honest version of a STAG
future graph: horizon $h = 1$, goal expressed as a discrete rubric
predicate, no cross-step control variables.  The rubric is called
as \texttt{rubric(output, stage\_name)} --- it does not read the
standing checkpoint.

\paragraph{Certificates are a separate channel. [implemented]}
Behavioural and structural certificates are carried in the
\emph{compiled organism artefact}, not emitted at run time by the
post-guard.  \texttt{run\_guarded\_graph} iterates
\texttt{compiled.get("certificates", [])} after the graph finishes
and re-verifies each one via
\texttt{certificate\_from\_dict} (line~557--572), populating
\texttt{GuardedGraphResult.certificates\_verified}.  The
factor-graph reading therefore has two distinct surfaces: the
compile-path post-guard that produces the routing decision (above),
and a post-run replay of compile-time certificates that attests
preservation-under-compilation rather than attaching a fresh
behavioural factor.  This split is the right place to pressure-test
the ``future graph'' framing: the goal factor realised in the
compiled graph is a rubric predicate, while the certificate layer
is a compile-time artefact that the runtime only \emph{replays}.

\paragraph{Shared dynamics. [analogy]}
STAG's past- and future-graph share a dynamics model.  In Operon,
the object that plays the closest role is the standing
\texttt{StateCheckpoint}, but only for the pre-guard: the pre-guard
consults it for integrity, the post-guard does not (the rubric call
does not take \texttt{checkpoint} as an argument).  The
category-theoretic machinery in
\texttt{operon\_ai/core/coalgebra.py} formalises discrete dynamics
for Operon in the abstract --- readout / update / bisimulation ---
and the compile path does not import it.  So this mapping is a
loose conceptual anchor, not a shared runtime object: both guards
live in a world whose dynamics model is discrete and deterministic,
but the compile path does not thread a single dynamics object
through both.  Flagging this so downstream work does not build on a
shared-object or coalgebra/compile coupling that does not exist.

\paragraph{Joining factor graphs across agents. [analogy]}
In the continuous STAG loop, two robots with overlapping
trajectories can join their graphs by sharing the variable nodes
their observations agree on.  The Operon code that plays a
superficially similar role is the A2A certificate codec
(\texttt{operon\_ai/convergence/a2a\_certificate.py}): it encodes
certificates as \texttt{DataPart} payloads, decodes them on
receipt, and implements a graceful-degradation rule for unknown
theorems (\S3.3 of \texttt{docs/site/external-frameworks.md}).
What the code does \emph{not} do is maintain an internal factor
graph, attach received factors to any shared-variable state, or
perform graph-level composition or joint inference.  A receiver
either verifies a single certificate locally or forwards it; there
is no ``my graph, your graph, joined along a shared variable''
surface anywhere in the codebase.  So the mapping here is analogy
only --- transport plus schema agreement, not graph joining.
Downgrading to \textbf{[analogy]} so readers do not treat the
transport layer as evidence of implemented cross-agent graph
composition semantics.  The
monoidal-category structure Operon's optimiser already exposes
(\texttt{operon\_ai/core/optimizer.py}, endofunctor composition) is
the category-theoretic statement that certificate joining is
associative.

\subsection{Claim-validation table}\label{sec:fg-validation}

Each mapping in Section~\ref{sec:fg-mapping} is tagged
\textbf{[implemented]}, \textbf{[derived]}, or \textbf{[analogy]}.
The table below names, for each \textbf{[implemented]} and
\textbf{[derived]} mapping, the owning code path and the artefact
that validates it.  The \textbf{[analogy]}-tagged mappings are
descriptive and have no validation artefact by design; they are
included for completeness and flagged so downstream work does not
treat them as code-level contracts.

\begin{center}
\small
\begin{tabular}{@{}p{3.6cm}p{5.8cm}p{4.4cm}@{}}
\toprule
Mapping & Owning code path & Validation artefact\\
\midrule
Variables & N/A (abstract) & --- \emph{[analogy]}\\[2pt]
Measurement factors ($\mathtt{behavioral\_stability\_windowed}$) &
\texttt{core/certificate.py}:261 &
Unit test \texttt{tests/unit/convergence/test\_paper6\_*.py};
Section~\ref{sec:fg-worked-example}\\[2pt]
Measurement factors ($\mathtt{DNARepair.scan}$) &
\texttt{state/dna\_repair.py}:268 (5 scans, \S291, 307, 335, 351, 381) &
Unit tests in \texttt{tests/unit/state/test\_dna\_repair*}\\[2pt]
Dynamics factors & \texttt{state/dna\_repair.py}:292--305 +
\texttt{StateCheckpoint} & Integrity certificate on pre-guard
(Paper~4 \S4.1)\\[2pt]
Pre-guard = repeated invariant re-validation (static checkpoint;
no rolling window) & \texttt{convergence/guarded\_graph.py}:93,
186--199, 448, 524--535 & Pre-guard halts on damage; Paper~4 \S4.1\\[2pt]
Future graph = post-guard (rubric routing) &
\texttt{convergence/guarded\_graph.py}:248, 300 &
Conditional-router decision trace in the compiled graph\\[2pt]
Certificates are a separate channel (post-run replay of
compile-time certificates) &
\texttt{convergence/guarded\_graph.py}:554--572
(\texttt{compiled.get("certificates")} +
\texttt{certificate\_from\_dict}) &
\texttt{GuardedGraphResult.certificates\_verified}; this attests
preservation-under-compilation, not runtime emission\\[2pt]
Shared dynamics (pre-guard only via \texttt{StateCheckpoint}; no
coalgebra coupling; rubric call \texttt{(output, stage\_name)}
ignores checkpoint) & --- & --- \emph{[analogy]}\\[2pt]
A2A transport of certificates (not graph joining) &
\texttt{convergence/a2a\_certificate.py} &
A2A DataPart round-trip + graceful-degradation (\S3.3,
\texttt{external-frameworks.md}); \emph{[analogy]} --- no
internal-graph join is implemented\\
\bottomrule
\end{tabular}
\end{center}

\paragraph{Reproducibility prerequisites.}
Claims split into three reproducibility tiers:

\begin{itemize}[leftmargin=*,itemsep=2pt,topsep=2pt]
\item \textbf{No dependencies.} The worked example in
Section~\ref{sec:fg-worked-example} runs purely from the harness
\texttt{run\_rollout} function
(\texttt{eval/convergence/synthetic\_signal\_harness.py}:192).  No
LM, no LangGraph, no model server.  Standalone verification of a
constructed \texttt{Certificate} via
\texttt{certificate\_from\_dict} + \texttt{verify()} also lives in
this tier.
\item \textbf{LangGraph optional-import.}  The
\texttt{[implemented]} guarded-graph claims require
\texttt{pip install operon-ai[langgraph]}:
\texttt{compile\_guarded\_graph} raises
\texttt{ImportError} at lines~133--140 without it, and
\texttt{run\_guarded\_graph} does the same at line~517--522.
Consequently the post-run certificate-replay claim (``Certificates
are a separate channel'') is in \emph{this} tier, not the
no-dependencies tier: it is reached via
\texttt{run\_guarded\_graph.certificates\_verified}
(lines~554--572), and therefore needs LangGraph.
\item \textbf{LangGraph + LM.}  End-to-end execution of the pre- /
post-guard routing needs a live or mock LM (Ollama or equivalent)
in addition to LangGraph.  The appendix does not depend on any
claim in this tier.
\end{itemize}

\paragraph{Maintenance checklist (documentation-drift contract).}
This appendix cites exact line numbers.  On any change to the
files below, a reviewer must verify or retag:

\begin{itemize}[leftmargin=*,itemsep=2pt,topsep=2pt]
\item \texttt{operon\_ai/core/certificate.py}:261 ---
verifier signature and \texttt{signal\_values} contract;
rebuild PDF if signature changes.
\item \texttt{operon\_ai/state/dna\_repair.py}:268, 291, 307, 335,
351, 381 --- five scan components; retag row as
\textbf{[analogy]} if any component is removed.
\item \texttt{operon\_ai/convergence/guarded\_graph.py}:93, 186--199,
248, 255, 300, 448, 524--535, 554--572 --- pre-guard, rubric call
signature, retry routing, checkpoint plumbing, post-run certificate
replay.  If \texttt{run\_guarded\_graph} begins emitting fresh
certificates from the post-guard, the ``certificates are a separate
channel'' paragraph must be rewritten.
\item \texttt{operon\_ai/convergence/a2a\_certificate.py} --- if any
internal graph-join API is added, the ``Joining factor graphs
across agents'' row may be re-tagged from \textbf{[analogy]} to
\textbf{[derived]} or \textbf{[implemented]}.
\end{itemize}

The contract is \emph{retag-or-rewrite}: a drifted anchor does not
block the build, but the corresponding row or paragraph must be
re-tagged as \textbf{[analogy]} until a reviewer has re-verified
the code.

\subsection{Worked example}\label{sec:fg-worked-example}

We replay the harness of Section~\ref{sec:task} deterministically on
$(\texttt{data\_inst\_id}{=}0,\ \texttt{run\_seed}{=}0)$ at default
calibration ($W=4$, $\tau=0.5$, $\sigma=0.08$, $O=8$).  The harness
seed is SHA-256 of $(\texttt{run\_seed}, \texttt{data\_inst\_id})$,
so these values are reproducible with no LM in the loop
(\texttt{eval/convergence/synthetic\_signal\_harness.py}:210).

\paragraph{Before convergence --- $\mathtt{policy\_throttle}=0.55$.}
The harness draws per-window means
\[
\mathbf{x}^{\text{(obs)}} = (0.5769,\ 0.5653,\ 0.4934,\ 0.5172).
\]
The past-graph smoother of this appendix attaches four measurement
factors
\[
\varphi^{\text{obs}}_i = \mathbb{1}[x_i^{\text{(obs)}} \le \tau],
\quad i = 0,1,2,3,
\]
with residuals $r_i = \max(0, x_i^{\text{(obs)}} - \tau) = (0.0769,
0.0653, 0,\ 0.0172)$.  Three factors are zero, so the smoothed
predicate $\prod_i \varphi^{\text{obs}}_i = 0$: the certificate does
not hold.  The obligation formatter of Section~\ref{sec:arms}
serialises exactly the windows $i \in \{0,1,3\}$ with positive
residuals --- these are the ``\texttt{[VIOLATING]}'' entries in the
reflection feedback handed to GEPA.  The
\texttt{scalar-with-evidence} arm sees the same per-window evidence
line but without the theorem-framing prefix.

\paragraph{After a reducing mutation --- $\mathtt{policy\_throttle}=0.42$.}
Replaying with the same instance under a smaller throttle gives
\[
\mathbf{x}^{\text{(obs)}} = (0.4469,\ 0.4353,\ 0.3634,\ 0.3872),
\]
residuals $(0,0,0,0)$, and $\prod_i \varphi^{\text{obs}}_i = 1$.
The certificate holds on this rollout.  Convergence
(Section~\ref{sec:conv}) is the first iteration whose best
candidate has $\mathrm{holds}=1$ for three consecutive
aggregate-over-16 validation evaluations.  Seed~0 of the
\texttt{cert-binary} arm reaches that streak at iteration 4; the
first three iterations have aggregate score $0.0$ and iterations
$4,5,6$ all score $1.0$
(\texttt{eval/results/theorem\_6/cert-binary/seed\_0.json}).

\subsection{What this framing buys}\label{sec:fg-buys}

\begin{enumerate}[leftmargin=*,itemsep=2pt,topsep=2pt]
\item \textbf{Citation lineage.}  The pre-/post-guard pattern is no
  longer a novel construct; it is the symbolic-state analogue of the
  rolling-past / rolling-future loop that has been standard in
  robotics state estimation since~\cite{kaess2012isam2}.  The
  LangGraph-gates wedge's theoretical-basis paragraph can cite this
  directly.
\item \textbf{Certificate composition has the \emph{shape} of
  factor joining.}  The A2A codec is transport plus graceful
  degradation; under this framing it reads as the transport-layer
  analogue of graph joining along shared theorem variables, not an
  implemented graph-join operation (see
  Section~\ref{sec:fg-mapping}, ``Joining factor graphs across
  agents'', tagged \textbf{[analogy]}).  What the framing gives us
  is a common vocabulary for cross-agent reliability ---
  model-agnostic agents still share a factor-structured
  certificate shape --- not a semantic claim about joint
  inference.
\item \textbf{A vocabulary for future scope.}  Any future extension
  --- longer pre-guard windows, $h > 1$ future graphs, learned
  residuals --- can be stated and bounded in this vocabulary.  The
  scope-discipline rule we adopt here is: \emph{factors and
  topology fixed; only the set of theorems grows.}
\end{enumerate}

\subsection{Where the analogy stops}\label{sec:fg-limits}

We record the load-bearing disanalogies so later work does not
overclaim.

\begin{itemize}[leftmargin=*,itemsep=2pt,topsep=2pt]
\item \textbf{No metric on state.}  Symbolic agent state has no
  inner product.  ``Energy'' in our usage is a residual count, not a
  differentiable potential; the gradient step behind MAP smoothing
  in SLAM has no counterpart.  Solving is replaced by verification.
\item \textbf{No learned factors.}  Every factor in the mapping
  above is a deterministic predicate defined in code.  The moment a
  factor is fit to data, the guarantee flips from structural to
  empirical.  This is the Paper 3 lesson (\cite{banu2026convergence}
  §``evolution did not beat random mutation''): the structure held,
  the learning did not.
\item \textbf{Future graph is degenerate.}  Operon's post-guard has
  horizon $h=1$.  A non-degenerate future graph would plan multiple
  stages ahead and fold goal factors into the run, which is the
  direction of energy-based agent planning we deliberately do not
  pursue.
\item \textbf{No variable elimination.}  SLAM's speed comes from
  eliminating variables in topological order.  Operon's guards
  verify one certificate at a time; there is no dual benefit from
  the structure, only a dual \emph{description}.
\end{itemize}

The framing is load-bearing for \emph{how we talk about} the gates,
not for how they are computed.  That is the correct line for a
structural-guarantees paper, and the line this appendix commits to.
