Appendix A - 14. Caused-by provenance (agent-side change traceability)

The Structure of Caused-by provenance (agent-side change traceability) — its shape at a glance:

The cause is minted where the change is decided (the dispatch), travels with it, and is asserted at the commit gate; an inferred cause carries an honest proxy label.

flowchart LR
  Dispatch[/Dispatch mints cause-id/] -->|carries cause| Agent[Agent works]
  Agent --> Gate{Commit gate}
  Taxonomy[(Closed cause taxonomy)] --> Gate
  Gate -->|field present + valid value| Land([Commit lands])
  Gate -->|absent or off-taxonomy| Reject([Rejected])

Accessible description: a dispatch mints a cause-id and carries it to the agent; at the commit gate the typed caused-by field is checked against a closed taxonomy; the commit lands when the field is present and names a known value and is rejected otherwise, with inferred causes labelled as proxies.

Projected from the catalogue entry lifecycle-and-observability / Caused-by provenance (agent-side change traceability).

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

Intent

Intent — When an agent-driven change alters system state, you must be able to trace it back to the reason that caused it, drawn from a closed taxonomy of causes, enforced by asserting a typed caused-by field at the commit gate. Upgrade correlation to causation wherever the cause is known at the moment of action (carry it with the dispatch); accept a labeled _proxy only where no artifact can hold the cause. Never reward a particular rate; the trace exists to explain, not to be optimized (our instance: a caused-by: epic:<id> | reflection:<fire_id> | ad-hoc field asserted by the code-agent pre-commit hook).

Motivation

The failure is the un-warranted change: a landed diff whose reason survives only as tribal knowledge. When the fleet does something surprising, RCA of "why did we do this?" becomes guesswork: the diff shows what changed, never what caused the fleet to change it. Two costs follow:

Applicability

Structure

The Structure diagram appears at the top of this page.

Sample Code

The cause travels with the dispatch, so the field "comes out for free" at commit — correlation upgraded to causation because the cause was known when the change was made. A commit gate asserts the field names a value in the closed taxonomy; an inferred cause is labelled _proxy, never hidden.

CAUSES = {"epic", "reflection", "ad-hoc"}   # closed taxonomy — a cause outside it fails loud

def assert_caused_by(commit_msg: str) -> int:
    line = next((l for l in commit_msg.splitlines() if l.startswith("caused-by:")), None)
    if line is None:
        print("REJECT: commit has no caused-by field"); return 1
    value = line.split(":", 1)[1].strip()
    base = value[:-6] if value.endswith("_proxy") else value   # _proxy = the cause had to be inferred
    if base not in CAUSES:
        print(f"REJECT: caused-by '{value}' is not in the taxonomy {sorted(CAUSES)}"); return 1
    return 0

# A telemetry read — NEVER a target. Optimizing the deterministic-vs-proxy ratio would only teach lying.
def caused_by_mix(commits) -> dict[str, int]:
    mix = {}
    for c in commits:
        v = c.caused_by
        mix[v] = mix.get(v, 0) + 1
    return mix

Consequences

Example use within DocAble

Contents
© James C. Davis, 2026–present