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.