Skip to main content

Conditioning

The operator's complaint: "it saw the same thing happen twice and now it talks like it's a law of nature." An AI treats one occurrence as a pattern and overreacts, or it sees two and declares a habit. Real conditioning does not work that way, and neither should the machine that reports on it.

A Conditioning Analyzer reads a sequence of events and looks for the loop that behavioral conditioning is made of: a cue leads to a behavior, the behavior has a consequence, and the consequence provides reinforcement that makes the behavior more or less likely next time. What makes this analyzer useful is not that it finds loops. It is what it refuses to do: it never asserts a pattern from two ordinary points.

The mechanism

You hand it events. Each event is a dict:

{
  "ts": 1690000000,          # unix seconds, used for ordering and dedupe
  "cue": "deploy alert",     # what preceded the behavior (optional)
  "behavior": "override",    # what was done (required)
  "consequence": "passed",   # what happened after (optional)
  "consequence_class": "money",   # optional; some classes are high-stakes
  "valence": 1.0,            # optional; >0 rewarding, <0 aversive
  "externally_imposed": False,    # optional; was this forced from outside
}

The analyzer groups events by cue and behavior into episodes, then tiers each chain. Events can come from logs, ledgers, or receipts. They are injected, so the engine stays standalone.

from conditioning import analyze

HOUR = 3600
res = analyze([
    {"ts": 0,          "cue": "alert", "behavior": "override", "consequence": "passed"},
    {"ts": 10 * HOUR,  "cue": "alert", "behavior": "override", "consequence": "passed"},
    {"ts": 20 * HOUR,  "cue": "alert", "behavior": "override", "consequence": "passed"},
])

res["loops"][0]["status"]        # 'claimed_loop'  (three distinct episodes)
res["loops"][0]["direction"]     # 'mixed_or_unclear' (no valence was given)

The tiered-claims rule

This is the whole point. A claim is only as loud as the evidence earns.

Tier When What it means
noise 1 episode a single occurrence, reported as nothing
candidate_loop 2 ordinary episodes an investigation question ("possible loop?"), never an asserted pattern
claimed_loop >= 3 distinct episodes, or >= 2 when the consequence class is high-stakes a pattern the analyzer is willing to stand behind

The high-stakes classes are hard_line_near_miss, money, public, and class_a. Two near misses is a claimed loop, because two chances to get hurt is already a pattern worth naming. Two ordinary passes is only a question.

Even a high-stakes consequence never claims a loop from a single point. One is always noise.

Episode dedupe

Repetition inside one sitting is one episode, not a habit. Same cue and behavior within a 2 hour window collapses to a single episode, unless the consequence differs. Five rapid identical log rows do not manufacture a claim. This is how the analyzer avoids the "saw it twice in five minutes, must be a law" failure.

Direction is never forced

The loop's direction is one of reward_seeking, avoidance, externally_imposed, or mixed_or_unclear. When valence is missing, the answer is mixed_or_unclear, not a guess. A forced direction is a fabricated finding, so the analyzer declines to pick a side it cannot support.

Feeding investigations

Detected loops can become investigation questions ("should this loop exist?"). feed_investigations drafts them and, if you pass a sink, hands each draft to it. A failing sink is disclosed, never silently swallowed.

from conditioning import analyze, feed_investigations

fed = feed_investigations(analyze(events))
fed["drafts"][0]["title"]   # "Loop claimed loop: 'alert' -> 'override' x3 ... should this loop exist?"

# with your own queue or ledger as the sink:
fed = feed_investigations(analyze(events), open_investigation=my_queue.open)

The honest metric

The analyzer publishes its false-positive residual: the percentage of claimed loops the reviewer marks wrong in review. That number gets published, not hidden. status() reports the claim rule, the dedupe window, and the residual metric so the contract is inspectable at runtime.

from conditioning import status
status()["claim_rule"]        # ">=3 distinct episodes, or >=2 high-stakes"

Install

pip install conditioning

Zero dependencies, standard library only. Bring your own event source and, if you want it, your own investigation sink.

Fits with

Part of The Operator's Honesty Stack, open-source honesty engines from the same production system, composed, never merged:

License

Apache 2.0. Copyright 2026 Dave DePew Enterprises, Inc.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

conditioning-0.1.0.tar.gz (78.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

conditioning-0.1.0-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file conditioning-0.1.0.tar.gz.

File metadata

  • Download URL: conditioning-0.1.0.tar.gz
  • Upload date:
  • Size: 78.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for conditioning-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e54403b76b056aa5e26fc69280f8a59412505f11966e92417bd40f8ad17b2524
MD5 55994837463af3819c65aa77c87b5d06
BLAKE2b-256 da3b7d8ff33a3fbe1bcaa8fa4fb6cc96114d3f03aa8d0b38372d88f3a88e2dbf

See more details on using hashes here.

File details

Details for the file conditioning-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: conditioning-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for conditioning-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 21ddd87ede7d82bf3de59279d1c3506caf6f9f1d46411630265beca10a7919a8
MD5 882a98b87038a4043456611e0362cb28
BLAKE2b-256 d7ae8c36525a2534820b2dd9441c8b1031bdff81b19b4e28d52ab9d36d12737c

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page