Skip to main content

Constraint-control testbed for local LLM agents

Project description

MorphSAT

Python 3.10+ License Tests Checkpoint

Evidence-based commit control, novelty response, and auditable execution traces.

What is this?

MorphSAT is a testbed for studying when a local LLM agent should stop gathering evidence and commit to an action.

An LLM agent with tool access can loop indefinitely — calling tools, reading results, calling more tools — without ever deciding. MorphSAT layers constraint-control mechanisms around the agent's loop and measures their effect on accuracy, tool usage, and commit timing.

The current checkpoint (v7) compares an evidence-pressure controller against an anticipatory posture controller that treats novelty as an orienting state rather than a scalar penalty.

For cognitive architecture researchers: See docs/COGNITIVE_ARCHITECTURE_TRANSLATION.md for a term mapping between MorphSAT internal names and concepts from Soar, ACT-R, and active inference.

The proof chain

Seven versions tested on a 20-scenario security alert triage benchmark:

Version Mechanism Accuracy Key finding
v1 Static FSA constraints 55% 0 useful interventions — too weak
v2 Fixed tool-call counter 67.5% Any pressure helps
v3 Adaptive budget (2/3/5) 55–67.5% Ceiling irrelevant, floor matters
v4 Evidence-pressure gate 65% Best escalation (77.8%), best pre-v7
v5 + pattern memory 62.5% Mechanics work, accuracy fails — learned threats without tolerance
v6 + bidirectional pressure 55% Novelty-as-penalty is the wrong abstraction
v7 Anticipatory posture control 70% Best accuracy, benign recovery 78.6% (was 35.7%)

v7 result

Evidence-pressure (v4) Anticipatory posture (v7)
Overall accuracy 62.5% 70.0%
Tool-loop rate 35.0% 25.0%
Avg turns to decision 5.4 4.8
Benign accuracy 35.7% 78.6%
Suspicious accuracy 75.0% 62.5%
Escalation accuracy 77.8% 66.7%

v7 fixes the tolerance problem (benign +42.9pp) at the cost of suspicious/escalate regression. The tradeoff is real and not yet resolved.

Key insight: Novelty handling is a posture problem, not a threshold problem. When novelty was treated as a penalty (raise the commit threshold), the agent over-investigated benign scenarios and never learned tolerance. When novelty was treated as an orienting state (enter protective posture, gather bounded evidence, relax on safe evidence), benign recovery improved dramatically.

Architecture

Layer 1: FSA lifecycle gate
         Legal task-state transitions. Blocks impossible sequences.

Layer 2: Evidence-pressure gate (v4)
         Sensor-driven commit timing. Se complexity threshold,
         evidence quality, sidecar confidence, urgency decay.
         Fires irreversibly when pressure crosses threshold.

Layer 3: Anticipatory posture controller (v7)
         Hidden state machine wrapping the agent's loop.
         Novelty → ORIENT → bounded investigation → decide.
         Safe evidence decays protective posture (tolerance).
         Multi-axis pressure → escalation signal.

Layer 4: Dual-store memory
         Threat patterns and tolerance patterns stored separately.
         Familiarity with known configurations speeds future decisions.

Layer 5: Episodic traces
         Turn-by-turn audit records of state, evidence, posture,
         and outcomes. Every decision is reproducible.

Shadow monitor states

NORMAL ──→ ORIENTING ──→ SAFE_DISTANCE ──→ NORMAL (safe recovery)
              │
              └──→ INVESTIGATING ──→ COMMIT_READY (clear evidence)
                        │            ESCALATE_READY (high threat)
                        │            ABSTAIN_READY (contradictory)
                        └──→ SWARM_CALL (multi-axis pressure)

Install

# From source
git clone https://github.com/echo313unfolding/MorphSAT.git
cd MorphSAT
pip install -e .

# Optional dev tools
pip install -e ".[dev]"

Quick start

FSA lifecycle gate

from morphsat import MorphSATGate, TaskState, TaskEvent

gate = MorphSATGate()
state, legal, action = gate.step(TaskEvent.NEW_TASK)
assert state == TaskState.PLANNING
assert legal is True

Evidence-pressure gate

from morphsat import CommitGate, SplitMemoryStore

memory = SplitMemoryStore("/tmp/memory.json")
gate = CommitGate(memory=memory)
gate.initialize(alert_text="Suspicious process spawned by cron")

# Feed tool results
action = gate.process_evidence("check_process", "PID 1234: /usr/bin/curl ...")
# action.action is "CONTINUE", "COMMIT", or "ABSTAIN"
# action.direction is "escalate", "benign", or None

Shadow monitor (v7)

from morphsat import ShadowMonitor, SplitMemoryStore

memory = SplitMemoryStore("/tmp/memory.json")
monitor = ShadowMonitor(memory=memory)
monitor.initialize(alert_text="Unknown binary in /tmp")

# Monitor enters ORIENT if alert is novel
print(monitor.state)  # ShadowState.ORIENTING

# Feed evidence — monitor transitions through states
action = monitor.process_evidence("check_hash", "Hash not in VirusTotal")
print(monitor.state)       # ShadowState.INVESTIGATING
print(action.action)       # "CONTINUE"

action = monitor.process_evidence("check_parent", "Parent: systemd")
print(monitor.state)       # ShadowState.COMMIT_READY
print(action.action)       # "COMMIT"
print(action.direction)    # "benign"

# Close episode — updates memory for next run
monitor.close_episode("benign", confidence=0.8)

Project structure

morphsat/
├── morphsat/
│   ├── __init__.py           # Public API
│   ├── core.py               # FSA gate, TaskState/TaskEvent, classify_event
│   ├── token.py              # Token adjacency scoring (4-lane structure)
│   ├── pressure_gate.py      # v4 evidence-pressure gate
│   ├── commit_gate.py        # v6 bidirectional commit gate + split memory
│   ├── shadow_monitor.py     # v7 anticipatory posture controller
│   └── receipt.py            # Receipt wrapping with SHA256 content hash
├── tests/
│   ├── test_core.py          # 31 tests: FSA structure, transitions, receipts
│   ├── test_token.py         # 22 tests: lane scoring, temperature, masking
│   └── test_shadow_monitor.py # 22 tests: v7 posture predictions
├── docs/
│   ├── PRESSURE_GATE_SPEC.md
│   └── COGNITIVE_ARCHITECTURE_TRANSLATION.md
├── receipts/
│   └── v7_shadow_monitor/    # Benchmark receipts (single-seed + 3-seed)
└── pyproject.toml

109/109 tests passing (Python 3.10).

Caveats

  • N=20 scenario benchmark with simulated tool responses
  • Temperature=0 (deterministic) — no stochastic variance across seeds
  • Qwen2.5-Coder-3B doing security triage — small model, not its strongest domain
  • The shadow monitor is tested on one task type (alert triage)
  • This is a research testbed, not a production system

Companion projects

Project Description
helix-substrate Calibration-free neural network compression (HXQ).
sentinel-hybrid-stack Hybrid SSM-Transformer security monitoring pipeline.
helix-codec Standalone C99 tensor codec library.

License

MIT — see LICENSE.

Project details


Download files

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

Source Distribution

morphsat-0.3.0.tar.gz (48.1 kB view details)

Uploaded Source

Built Distribution

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

morphsat-0.3.0-py3-none-any.whl (36.2 kB view details)

Uploaded Python 3

File details

Details for the file morphsat-0.3.0.tar.gz.

File metadata

  • Download URL: morphsat-0.3.0.tar.gz
  • Upload date:
  • Size: 48.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for morphsat-0.3.0.tar.gz
Algorithm Hash digest
SHA256 1ea97faabba3818705e9d194d7b999b0ae0ac0601e2c5f21a8ccb9581c2df47d
MD5 b370760fa05f05640b432f6e22ae227e
BLAKE2b-256 491a9065a96d77a20dcc3be0cc62f3f41fdf69b78e611d47158e7a4a9ed03ae5

See more details on using hashes here.

File details

Details for the file morphsat-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: morphsat-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 36.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for morphsat-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0871c11355b35aa955144fd8d33aa7b69229abf4e65d7737f4467c748d5fb658
MD5 6c72e9d39b99cafa9d03e41d3e73b2b4
BLAKE2b-256 415e06c9db0465313cfddf35c1b6572beb5fd1fa2dfcb4e209d3610977113342

See more details on using hashes here.

Supported by

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