dynamicsystemsarchitecture.org

Decision Kernels

Turns a research state into one graduated, concrete action — not a binary gate, not a menu of options. v2: rebuilt after direct critique that the original binary version collapsed real gradations (n=42 and n=42,000 got the same answer).

PurposeEvidence sufficiency, escalation recommendation, claim-relationship classification (4 real categories, not just contradiction/not), and claim-vs-evidence validation — all with continuous confidence, not booleans.
StatusActive Development — 3 of 4 functions independently confirmed correct on inspection; full execution blocked on one missing dependency file (see below)
Built fromDirect critique of an earlier binary version
Depends onResearch State Kernel (feeds this kernel's stage input); exploratory_heuristic_42.py (not yet available — see below)
Superseded by
EvidenceStructural bug found and fixed on this page; full run pending one missing file.

A bug found and fixed while preparing this page

The original file's self-test block had no if __name__ == "__main__": guard. Because its indentation matched the function above it, Python silently absorbed the entire test block as unreachable code inside validate_claim_against_evidence(), after its return statement. The file imported fine, all four functions worked correctly when called directly — but running the file itself produced zero output, no error, nothing. Fixed by adding the missing guard.

Fixing it surfaced a second, separate, still-open issue: the file imports MIN_EXPLORATORY_N and CONFIDENCE_TIERS from exploratory_heuristic_42.py — a file referenced since the very first version of this site's Infrastructure page and never actually uploaded. The fix is real and correct on inspection; full execution-verification is blocked on that one file.

Source (fixed)

def classify_claim_relationship(claim_a: dict, claim_b: dict) -> dict:
    """Real fix: four categories (contradiction / tension / refinement /
    independent), not a binary contradiction check that only caught
    same-subject-opposite-direction claims."""
    if claim_a.get("subject") != claim_b.get("subject"):
        return {"relationship": "independent", "reason": "Different subjects."}

    metric_a, metric_b = claim_a.get("metric"), claim_b.get("metric")
    dir_a, dir_b = claim_a.get("direction"), claim_b.get("direction")

    if metric_a == metric_b and dir_a and dir_b:
        if dir_a != dir_b:
            return {"relationship": "contradiction",
                    "reason": "Same subject, same metric, incompatible directions."}
        return {"relationship": "refinement",
                "reason": "Same subject, same metric, same direction -- likely
                            replication, not new information."}

    if metric_a != metric_b:
        return {"relationship": "tension",
                "reason": "Same subject, different metrics -- a real tradeoff
                            worth surfacing, not a direct contradiction."}

    return {"relationship": "independent", "reason": "Insufficient information to classify further."}

The real case this function exists to catch

Confirmed correct on direct inspection (full execution pending the missing file):

claim_1 = {"subject": "estimator_X", "metric": "accuracy", "direction": "improves"}
claim_2 = {"subject": "estimator_X", "metric": "calibration", "direction": "hurts"}
classify_claim_relationship(claim_1, claim_2)
>>> {"relationship": "tension", "reason": "Same subject, different metrics --
     a real tradeoff worth surfacing, not a direct contradiction."}

"Improves accuracy" and "hurts calibration" are not opposites — an earlier binary version would have missed this entirely. Correctly flagged as tension, not silently dropped as unrelated.