Appendix B - 1. The agent-first MBSE harness

The Structure of The agent-first MBSE harness — its shape at a glance:

Five disciplines wrap the frozen records. The loader discovers each record file; the look-up seam projects fields from the code; the derive-and-assert step recomputes any function-of-other-fields; the drift check set-diffs model against reality; the query projection turns records into JSON for the fleet.

flowchart LR
  Code[(Code source)] --> Seam[Look-up seam]
  Seam --> Rec["Frozen records<br/>(one per view)"]
  Loader([Auto-discovery loader]) --> Rec
  Rec --> Derive[Derive + assert]
  Rec --> Drift{{Drift check}}
  Rec --> Query[JSON query projection]

Accessible description: frozen records sit at the center. The look-up seam feeds them from the code source, the loader discovers them, and three consumers read them — a derive-and-assert step, a drift check that fails the build on divergence, and a query projection that emits JSON.

Projected from the catalogue entry system-models / The agent-first MBSE harness.

On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns

Intent

Intent — Build the typed system-models as a thin, hand-rolled harness over plain frozen records: adopt the vocabulary and schema of the right modeling genre per view, but skip its runtime and hand-roll the executable layer. The model then captures your project's own invariants, and a set of build-time checks keeps it equal to the code (our instance: frozen Python dataclasses under five recurring disciplines, not a SysML tool).

Motivation

You decide to model your system as executable source-of-truth, and the first instinct is to reach for a real modeling tool: SysML, Alloy, an EMF metamodel. Then two failures land. First, the tool's schema doesn't fit. A real system-model carries project-specific invariants (a verification tier derived from an invariant's temporal shape, a lock-ordering rule, a zone-boundary predicate) that don't map onto any standard library's schema, so you spend more effort fighting the tool's model than building yours. Second, the tool draws or checks; it does not run inside your own lints. A SysML diagram is data a viewer renders; an Alloy model is data a solver checks. Neither ships the discipline that makes the model unable to lie about your code: a build-time check that loads the model, loads the code, and blocks on divergence. The failure is a modeling layer that either doesn't fit your invariants or doesn't wire into your build, so it drifts, and a drifted model is worse than none.

Applicability

Structure

The Structure diagram appears at the top of this page.

Sample Code

A frozen record holds the model. One field is derived from other fields, so a check recomputes the derivation and fails if the stored value went stale — the discipline that turns a snapshot into a bridge that cannot lie about its own inputs.

from dataclasses import dataclass
import sys

@dataclass(frozen=True)
class Invariant:
    name: str
    temporal_form: str        # "always" (safety) or "leads-to" (liveness)
    verification_tier: str    # DERIVED from temporal_form — never hand-typed

def derive_tier(temporal_form: str) -> str:
    """The one derivation function. Stored tier must equal what this returns."""
    return "exhaustive-check" if temporal_form == "leads-to" else "state-search"

def assert_derived(records: list[Invariant]) -> list[str]:
    findings = []
    for r in records:
        expected = derive_tier(r.temporal_form)
        if r.verification_tier != expected:
            findings.append(f"{r.name}: stored tier '{r.verification_tier}' != derived '{expected}'")
    return findings

if __name__ == "__main__":
    # `load_view` auto-discovers and loads the frozen records for one model view.
    findings = assert_derived(load_view())
    for f in findings:
        print(f"STALE-DERIVED: {f}")
    sys.exit(1 if findings else 0)   # a hand-typed derived field that drifted fails the build

Consequences

Example use within DocAble

Contents
© James C. Davis, 2026–present