Forensic Inference Tools

Structured agent debugging through fact accumulation and Prolog-based transitive reasoning.

How it works

Forensic Inference is a debugging paradigm where agents assert structured facts into the _forensic Logic Cell namespace during investigation, then query pre-built Prolog rules that perform exhaustive reasoning over the unified fact base. The agent does the observation; Prolog does the deduction.

All forensic operations use the standard Logic Cell tools (logic.assert, logic.query, logic.constrain, logic.reflect) with namespace set to "_forensic". The forensic rule library is loaded automatically.


Standard predicates

Agents assert these predicates as facts. The rule library reasons over them.

Predicate Arity Description
causes(A, B) 2 A causally leads to B
requires(X, Dep) 2 X requires dependency Dep
provides(Source, Cap) 2 Source provides capability Cap
config_value(C, K, V) 3 Component C has config key K with value V
runtime_behavior(C, B, V) 3 Component C exhibits behavior B with value V
code_behavior(F, B) 2 Function F has code-level behavior B
invariant(Name, Cond) 2 Named invariant with callable condition
asserts_property(S, P, V) 3 Source S asserts property P has value V
depends_on(A, B, Kind, _) 4 A depends on B with dependency kind (Invariant bridge)
calls_external(Caller, Mod, Func, Arity, Line) 5 Call graph edge (Invariant bridge)

Rule library predicates

These are the pre-built rules agents can query. All return results derived from the asserted facts.

Causal analysis

Predicate Description
causal_chain(A, B, Chain) Finds a transitive causal path from A to B, returning the full chain as a list
blast_radius(Origin, Affected) Everything transitively affected by Origin
all_affected(Origin, List) Sorted list of all entities in the blast radius
common_cause(Effect1, Effect2, Cause) Finds a shared upstream cause of two effects

Invariant checking

Predicate Description
invariant_holds(Name) True if the named invariant’s condition succeeds
invariant_violated(Name, Cond) Binds Name and Cond for invariants whose conditions fail
all_violations(List) Collects all violated invariants as inv(Name, Cond) terms

Dependency analysis

Predicate Description
missing_dependency(X, Dep) X requires Dep but nothing provides it
all_missing(List) Sorted list of all missing(X, Dep) terms
transitive_dep(A, B) A transitively depends on B (tabled for performance)
circular_dep(A, B) A and B are in a dependency cycle

Contradiction detection

Predicate Description
contradiction(S1, S2, Prop) Two sources assert conflicting values for the same property

Cross-domain analysis

Predicate Description
timeout_risk(Component, TimeoutMs, DeadlineMs) Component’s idle timeout is shorter than a configured deadline
code_runtime_mismatch(Func, CodeBehavior, RuntimeBehavior) Code-level behavior doesn’t match observed runtime behavior
unreachable_from(Origin, Target, Domain) Target is in Domain but not reachable from Origin via causal chains

Workflow

1. Assert facts during investigation

{
  "name": "data-grout@1/logic.assert@1",
  "arguments": {
    "namespace": "_forensic",
    "facts": [
      {"subject": "code_change", "relation": "causes", "object": "no_keepalives"},
      {"subject": "no_keepalives", "relation": "causes", "object": "idle_connection"},
      {"subject": "idle_connection", "relation": "causes", "object": "proxy_kill"},
      {"subject": "proxy_kill", "relation": "causes", "object": "timeout_504"}
    ]
  }
}

2. Query the rule library

{
  "name": "data-grout@1/logic.query@1",
  "arguments": {
    "namespace": "_forensic",
    "query": "causal_chain(code_change, timeout_504, Chain)"
  }
}

Returns: Chain = [code_change, no_keepalives, idle_connection, proxy_kill, timeout_504]

3. Check for contradictions

{
  "name": "data-grout@1/logic.query@1",
  "arguments": {
    "namespace": "_forensic",
    "query": "contradiction(S1, S2, Property)"
  }
}

4. Verify invariants

{
  "name": "data-grout@1/logic.query@1",
  "arguments": {
    "namespace": "_forensic",
    "query": "all_violations(V)"
  }
}

The _forensic namespace

The _forensic namespace is a dedicated, visible Logic Cell namespace for forensic debugging. It is isolated from the user’s default fact space, so forensic facts never pollute normal logic operations. Use logic.worlds to see it alongside other namespaces.