Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

sinmonto

tests License: Apache-2.0 Python 3.11+

Moteur de décision événementiel, explicable, en Python pur — zéro dépendance.

Du fon Sɛ́n mɔto ("moteur de règle"). Chaque décision porte sa propre preuve : pourquoi une règle a matché, pourquoi une autre non, dans quel ordre, avec quelles valeurs réelles au moment de l'évaluation.

Statut : 0.1.0rc3 — preview technique. Le noyau est testé (43 tests, modules + intégration bout-en-bout) et les bugs silencieux trouvés en revue croisée multi-IA sont corrigés (voir « Limitations connues » plus bas pour ce qui reste volontairement ouvert). Reste en pre-release le temps d'un premier retour d'usage externe réel — l'API 0.x n'est pas encore figée.

Pourquoi

  • Zéro dépendance — s'installe et s'audite n'importe où, sans arbre de dépendances à faire valider par une équipe sécurité.
  • Explicabilité native — chaque décision produit un arbre de traçage complet, pas un log ajouté après coup.
  • Effects-as-data — une règle ne fait jamais d'appel réseau ni d'écriture en base. Elle décrit un Effect. Un exécuteur séparé l'applique. Ça rend le moteur testable et rejouable par construction.
  • État persistant par entité — un ContextStore garde la mémoire d'une entité (utilisateur, appareil, transaction) d'un événement à l'autre, sans quoi aucun comptage ou score cumulé n'est possible.
  • Déterministe — mêmes entrées, même ordre d'enregistrement des règles ⇒ même sortie, bit à bit, y compris en cas d'égalité de priorité. (Exception explicite : DecisionTrace.trace_id, un UUID généré à chaque évaluation, non reproductible par construction — la garantie porte sur les règles matchées, les effets, l'ordre d'évaluation et l'état du contexte, pas sur les identifiants générés.)

Installation

pip install sinmonto

(La version étant une pre-release (0.1.0rc3), un pip install sinmonto seul ne l'installera pas une fois publié sur PyPI — il faudra pip install --pre sinmonto, cohérent avec le statut preview ci-dessus. En attendant la publication : pip install -e . depuis une copie locale du dépôt.)

Exemple

from decimal import Decimal
from uuid import uuid4

from sinmonto import DecisionEngine, Effect, Fact, Field, Signal, rule

engine = DecisionEngine()

@rule(name="high_amount_alert", priority=100,
      condition=(Field("amount") > 1000) & (Field("vip") == False),
      engine=engine)
def check_high_amount(ctx, fact):
    return Effect("FLAG_TRANSACTION", {"reason": "high_amount_non_vip"}, "high_amount_alert")

engine.compile()

fact = Fact(fact_id=uuid4(), entity_id="usr_99", fact_type="payment",
            _payload={"amount": 2500, "vip": False}, timestamp=Decimal("0"))
signal = Signal(signal_id=uuid4(), fact=fact, signal_type="payment_received", timestamp=Decimal("0"))

decision = engine.evaluate(signal)

print(decision.effects)
# (Effect(effect_type='FLAG_TRANSACTION', payload={'reason': 'high_amount_non_vip'}, rule_id='high_amount_alert'),)

trace = decision.trace.rule_traces[0]
print(trace.condition_tree.description, "->", trace.condition_tree.result)
# amount gt 1000 -> True

Un deuxième signal pour usr_99 reprend automatiquement le contexte du premier — voir examples/end_to_end.py et le ContextStore.

Statut de la revue croisée (2026-08)

Le dépôt est passé par une revue de code croisée multi-IA (ChatGPT, Grok, DeepSeek, Kimi, Qwen, Meta AI). Six bugs silencieux — ceux qui trahissaient la promesse d'explicabilité/déterminisme plutôt que de simples trous documentés — ont été corrigés avant cette preview : copie profonde du contexte, atomicité réelle des règles (snapshot/restore, y compris mutation directe de ctx), validation Signal.entity_id/opérateurs de condition/retours d'action, copie défensive du payload, causality chaînée. Un second passage (rc2 → rc3), sur le dépôt cette fois plutôt qu'un zip, a corrigé trois points additionnels : copie profonde (pas seulement superficielle) sur Fact.payload/Effect.payload, clarification que le déterminisme bit-à-bit exclut trace_id, et un souci de packaging sur CLAUDE.md. Détail complet, bug par bug : journal-integration.md.

Limitations connues (v0.1.0-preview) — assumées, pas des bugs

  • Les signaux dérivés (EvaluationResult.derived_signals) sont acceptés par l'API mais non traités — pas de cascade de règles dans cette version. Décision d'architecture (file séparée ? récursif ?) reportée à un tour dédié plutôt que corrigée en urgence. Prévu en v0.2.0.
  • RuleTrace.duration_ms est toujours Decimal("0") — pas de mesure réelle du temps d'exécution.
  • AND chaînés imbriqués plutôt qu'aplatis dans la trace — cosmétique, la logique et le court-circuit restent corrects.
  • Pas de politique de rétention sur InMemoryContextStore/InMemoryFactStore — stores mémoire pensés pour tests/démo/prototype, pas pour une production longue durée sans adaptateur dédié.
  • Pas encore de fenêtres temporelles, de transitions d'état (FSM), ni de engine.replay() — voir docs/roadmap-vision.md.
  • Fact.payload/Effect.payload/FrozenContext.values sont protégés par deep copy à la construction (une mutation externe ne les affecte plus) et MappingProxyType en lecture seule au premier niveau — mais MappingProxyType ne protège que ce premier niveau : muter une valeur imbriquée à travers le proxy (obj.payload["nested"]["x"] = ...) reste possible. Pas un trou de sécurité (l'appelant externe ne peut plus rien depuis sa propre référence), mais pas un deep-freeze récursif non plus.

Architecture et gouvernance

Ce projet est construit avec une discipline de documentation stricte, en revue croisée avec plusieurs IA :

  • constitution-finale.md — principes architecturaux verrouillés, stables à travers toutes les versions.
  • constitution-noyau.md — spécification technique complète de ce que le noyau construit.
  • journal-integration.md — historique honnête : ce qui a été tenté, les bugs trouvés, comment ils ont été corrigés.
  • roadmap-vision.md — ce qui n'est pas encore construit, et pourquoi ce n'est pas encore le moment.

Licence

Apache License 2.0 — voir LICENSE.

Release files for sinmonto 0.1.0rc3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sinmonto 0.1.0rc3
File Size Uploaded
sinmonto-0.1.0rc3.tar.gz 59.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sinmonto 0.1.0rc3
File Interpreter ABI Platform
sinmonto-0.1.0rc3-py3-none-any.whl Python 3 none any Details

Total release size: 93.0 kB

Release files / sinmonto-0.1.0rc3.tar.gz

Download URL sinmonto-0.1.0rc3.tar.gz
Size 59.7 kB
Tags Source
SHA-256 checksum
How to use checksums
80061baf46e1e1954debd92a69c386071771cdb5708ba97e4b7bc85126e2caed
BLAKE2b-256 checksum
How to use checksums
27b6e00e48d0299b56d507680c735a9449118841ab88e1cbae4cf7d5172a1acd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / sinmonto-0.1.0rc3-py3-none-any.whl

Download URL sinmonto-0.1.0rc3-py3-none-any.whl
Size 33.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
04478077be182116682512850168c2861f82c4d5cf2cd5f240f4ce3ab79e82cd
BLAKE2b-256 checksum
How to use checksums
9592857f4bbbd56d7d40651bc29836dc97d8c18dd5cd540ff2d969a4cc22946c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.1.0rc3 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page