Reasons — automatic belief retraction and dependency-directed backtracking
Project description
Reasons
An implementation of Doyle's (1979) Truth Maintenance System. Tracks beliefs as nodes in a dependency network with automatic retraction cascades and restoration.
Core Ideas
A node is a belief with a truth value: IN (believed) or OUT (retracted). Nodes can be premises (believed by default) or derived (believed because of justifications).
A justification is a reason for believing a node. Type SL (Support List) means the node is IN when all its antecedents are IN. A node can have multiple justifications — it's IN if any of them are valid.
When a node goes OUT, all dependents whose justifications become invalid go OUT too — this is the retraction cascade. When a retracted node comes back IN, dependents are automatically recomputed — restoration without rederivation.
A nogood records a contradiction: a set of nodes that cannot all be IN simultaneously. When a nogood is detected, the system uses dependency-directed backtracking to trace backward through the justification graph and retract the responsible premise with minimal disruption — not an arbitrary node.
Justifications support non-monotonic reasoning via the outlist: "believe X unless Y is believed." A justification is valid when all inlist nodes are IN and all outlist nodes are OUT. This enables default reasoning and dialectical argumentation — beliefs can be formally challenged and defended.
Install
pip install ftl-reasons
Or with uv:
uv tool install ftl-reasons
Or run without installing:
uvx ftl-reasons <command>
Usage
# Initialize database
reasons init
# Add premises
reasons add source-uses-langgraph "Source code uses LangGraph" --source "agents-python:src/graph.py"
reasons add graph-has-cycles "Graph contains cycles"
# Add derived nodes with SL justifications
reasons add topology-is-static "Graph topology is static" --sl source-uses-langgraph --label "observed from source"
reasons add no-runtime-modification "No runtime graph modification" --sl topology-is-static
# See what's believed
reasons status
# [+] graph-has-cycles: Graph contains cycles (premise)
# [+] no-runtime-modification: No runtime graph modification (1 justification)
# [+] source-uses-langgraph: Source code uses LangGraph (premise)
# [+] topology-is-static: Graph topology is static (1 justification)
#
# 4/4 IN
# Retract a premise — cascade propagates
reasons retract source-uses-langgraph
# Retracted: source-uses-langgraph, topology-is-static, no-runtime-modification
reasons status
# [+] graph-has-cycles: Graph contains cycles (premise)
# [-] no-runtime-modification: No runtime graph modification (1 justification)
# [-] source-uses-langgraph: Source code uses LangGraph (premise)
# [-] topology-is-static: Graph topology is static (1 justification)
#
# 1/4 IN
# Restore — dependents come back automatically
reasons assert source-uses-langgraph
# Asserted: source-uses-langgraph, topology-is-static, no-runtime-modification
# Record a contradiction
reasons add graph-is-dynamic "Graph is dynamically modified"
reasons nogood topology-is-static graph-is-dynamic
# Recorded nogood-001: topology-is-static, graph-is-dynamic
# Retracted: graph-is-dynamic
# Explain why a node is IN or OUT
reasons explain no-runtime-modification
# [+] no-runtime-modification: SL justification valid — antecedents: topology-is-static
# [+] topology-is-static: SL justification valid — antecedents: source-uses-langgraph [observed from source]
# [+] source-uses-langgraph: premise
# Show node details
reasons show topology-is-static
# View propagation history
reasons log
# Export as JSON
reasons export
# Import from a beliefs CLI registry
reasons import-beliefs ~/git/physics-pi-meta/beliefs.md
# Imported 39 claims (2 retracted)
# Imported 8 nogoods
# nogoods.md is auto-detected next to beliefs.md, or specify explicitly:
reasons import-beliefs ~/git/physics-pi-meta/beliefs.md --nogoods ~/git/physics-pi-meta/nogoods.md
# After import, cascading works on the imported dependency graph:
reasons retract beliefs-improve-accuracy
# Retracted: beliefs-improve-accuracy, engineering-intuition-unreliable, beliefs-beat-expert-prompting, ...
# Search for nodes
reasons search "tool-use"
# [+] tool-use-calibration-determines-benefit: Whether beliefs help a model... (5 dependents)
# [+] tool-deference-failure-mode: Models with poor tool-use calibration...
# 7 results
# List premises (foundations of the argument)
reasons list --premises
# List nodes that others depend on
reasons list --has-dependents
# List only OUT nodes
reasons list --status OUT
# Export as readable markdown
reasons export-markdown -o beliefs.md
# Check for source file changes
reasons check-stale
# 5 fresh, 14 STALE (of 19 checked)
# Token-budgeted summary for context injection
reasons compact --budget 500
# Non-monotonic reasoning: believe X unless Y
reasons add default-approx "Newtonian approximation holds" --unless strong-field
reasons assert strong-field # default-approx goes OUT automatically
reasons retract strong-field # default-approx restored
# Backfill source hashes
reasons hash-sources
# 26 backfilled
# Trace assumptions — what premises does a conclusion rest on?
reasons trace no-single-best-configuration
# no-single-best-configuration rests on 1 premise(s):
# [+] beliefs-improve-accuracy (7 dependents)
# Challenge a belief — target goes OUT
reasons challenge velocity-constraint "Not derived — postulated"
# Challenged velocity-constraint with challenge-velocity-constraint
# Changed: velocity-constraint, acoustic-metric-schwarzschild, ...
# Defend against a challenge — target restored
reasons defend velocity-constraint challenge-velocity-constraint \
"Follows from variational principle on elastic medium"
# Defended velocity-constraint with defense-challenge-velocity-constraint
# Changed: challenge-velocity-constraint, velocity-constraint, ...
# List challenged nodes
reasons list --challenged
Commands
| Command | Description |
|---|---|
reasons init |
Create reasons.db |
reasons add ID "text" |
Add a premise |
reasons add ID "text" --sl a,b |
Add with SL justification (all antecedents must be IN) |
reasons add ID "text" --sl a --unless y |
Add with outlist (must be OUT for justification to hold) |
reasons add ID "text" --cp a,b |
Add with CP justification (assumptions must be consistent) |
reasons retract ID |
Mark OUT + cascade to dependents |
reasons assert ID |
Mark IN + cascade restoration |
reasons status |
Show all nodes with truth values |
reasons show ID |
Show node details, justifications, dependents |
reasons explain ID |
Trace why a node is IN or OUT |
reasons challenge ID "reason" |
Challenge a node — target goes OUT |
reasons defend TARGET CHALLENGE "reason" |
Defend against a challenge — target restored |
reasons nogood A B ... |
Record contradiction, backtrack to responsible premise |
reasons trace ID |
Trace backward to find all premises a node rests on |
reasons hash-sources |
Backfill source hashes for unhashed nodes (--force to re-hash all) |
reasons propagate |
Recompute all truth values |
reasons log |
Show propagation audit trail |
reasons search QUERY |
Search nodes by text or ID (case-insensitive) |
reasons list |
List with filters (--status, --premises, --has-dependents, --challenged) |
reasons import-beliefs FILE |
Import a beliefs.md registry (auto-detects nogoods.md) |
reasons export |
Export network as JSON |
reasons export-markdown |
Export as beliefs.md-compatible markdown (-o FILE to write) |
reasons check-stale |
Check IN nodes for source file hash changes |
reasons compact |
Token-budgeted summary (--budget N, --no-truncate) |
Tests
uv run --extra test pytest tests/ -v
211 tests covering propagation, retraction cascades, restoration, multiple justifications, diamond dependencies, nogoods, dependency-directed backtracking, non-monotonic justifications (outlist), dialectical argumentation (challenge/defend), explain traces, SQLite round-trips, beliefs.md import, export-markdown, check-stale, hash-sources, compact, search, and list.
References
Doyle, J. (1979). A Truth Maintenance System. Artificial Intelligence, 12(3), 231–272.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ftl_reasons-0.17.0.tar.gz.
File metadata
- Download URL: ftl_reasons-0.17.0.tar.gz
- Upload date:
- Size: 70.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19912aedb3ba0fd26fde46bfd60899d64eac13e553016cdcf8fb9fb794fdf2d7
|
|
| MD5 |
49bafdc0887c6bae572708ff7ab8dcd3
|
|
| BLAKE2b-256 |
507d16724456cfc768cc547160a662d24e0ebee180f3d058f993d72b3682d2e4
|
File details
Details for the file ftl_reasons-0.17.0-py3-none-any.whl.
File metadata
- Download URL: ftl_reasons-0.17.0-py3-none-any.whl
- Upload date:
- Size: 51.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
623057efd6c86b50b5406e380228b3b5e6a60cc8bd926e7e712c4e6f691e1aaa
|
|
| MD5 |
b4fc9723df70867d32320e57ac3fc191
|
|
| BLAKE2b-256 |
e076ced15103eb153a2f604ab12f3978902eb33d7ec4a90508cf5fcd65b882e7
|