Skip to main content

jabr (الجبر) — Reversible Prompt-Context Restoration

Part of the Mizan stack — the Arabic-first reliability scale for AI agents.

License: MIT Python 3.10+ Tests: 31 passing

Reversible. Audited. Deterministic. The Restore operation as a standalone primitive for AI agent pipelines.


What it does

Takes an under-specified prompt and a context, returns the prompt with implicit terms made explicit, plus a full audit trail. The original prompt is always recoverable from the output.

from datetime import datetime, timezone
from jabr import restore, unrestore, RestorationContext

ctx = RestorationContext(
    now=datetime(2026, 4, 25, 14, 30, tzinfo=timezone.utc),
    referents={"her": "Alice"},
    defaults={"channel": "#engineering"},
)

result = restore("tell her tomorrow to post in <channel>", ctx)

print(result.output)
# tell her[[jabr:abc123:pronoun:Alice]] tomorrow[[jabr:def456:date:2026-04-26]]
# to post in <channel>[[jabr:ghi789:default:#engineering]]

# Reversible
assert unrestore(result.output, result.trace) == "tell her tomorrow to post in <channel>"

Design properties

The library guarantees four properties:

  1. Reversibility. unrestore(restore(p, ctx).output, trace) == p for any (p, ctx). Verified by 31 tests including round-trip property tests.

  2. Tag-only insertion. Every added term is bracketed with [[jabr:<id>:<kind>:<value>]]. Original characters are never modified, only interspersed with tags.

  3. Trace integrity. Every tag in the output has a corresponding entry in the trace. unrestore() with a wrong trace raises RestorationError.

  4. Determinism. Given the same (prompt, context, resolvers), the output is byte-identical across runs.

Why this matters

In modern LLM agent pipelines, prompts are routinely rewritten, summarized, and "expanded" silently. The original cannot be recovered. Debugging is dream interpretation.

jabr makes that explicit. Every restoration is tagged, every tag is in the trace, every trace entry has provenance (source, confidence, original span). When the agent does something unexpected, you can replay the input through the same restoration and see exactly what was added.

Built-in resolvers

Resolver What it handles Confidence
DateTimeResolver today, tomorrow, yesterday, this morning/afternoon/evening, next/last , now 0.85–1.0
PronounResolver he/she/it/they/etc., resolved against explicit context.referents 1.0
DefaultResolver <placeholder> and @PLACEHOLDER resolved against context.defaults 1.0
QuantityResolver a few, several, many, a couple, lots of → numeric ranges 0.5–0.85

Add your own resolver by implementing the Resolver Protocol:

from jabr import Resolver, RestorationEntry, RestorationContext

class MyResolver:
    name = "my_domain"
    def find(self, input: str, context: RestorationContext) -> list[RestorationEntry]:
        ...

CLI

# Restore
jabr restore --prompt "tell her tomorrow" --context ctx.json

# Restore with system clock
jabr restore --prompt "ping me tomorrow" --now system

# Round-trip verify
jabr roundtrip --prompt "tomorrow morning" --now system

# Unrestore (recover original from output)
jabr unrestore --output "[output with tags]"

Where ctx.json looks like:

{
  "now": "2026-04-25T14:30:00+00:00",
  "timezone": "UTC",
  "referents": {"her": "Alice"},
  "defaults": {"channel": "#engineering"}
}

Install

pip install -e .

Tests

pytest tests/ -v

31/31 pass on Python 3.10+. No runtime dependencies.

What it is not

  • Not an LLM-powered prompt rewriter. There is no model in jabr. All resolvers are deterministic regex/dict-based functions.
  • Not a coreference-resolution library. Pronoun restoration only happens when an explicit referent map is supplied. There is no inference from prior conversation.
  • Not a guesser. If a term cannot be resolved (e.g., "tomorrow" without a now), jabr does nothing. Silence is the correct behavior on missing context.

Structure

jabr/
├── jabr/
│   ├── __init__.py       Public API
│   ├── core.py           restore() + unrestore() + dataclasses
│   ├── resolvers.py      4 built-in resolvers
│   └── cli.py            command-line interface
├── tests/
│   ├── test_core.py      core property tests
│   └── test_resolvers.py resolver-specific tests
├── pyproject.toml
├── README.md
├── LICENSE
└── FAILURES.md

Failure modes

See FAILURES.md for the honest list of what this library does not handle.

License

MIT.

Metadata

Release files for jabr 0.1.0

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

Source distribution (sdist)

Source distribution for jabr 0.1.0
File Size Uploaded Provenance Actions
jabr-0.1.0.tar.gz 18.4 kB With provenance Details for jabr-0.1.0.tar.gz

Built distribution (wheel)

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

Total release size: 32.0 kB

Release files / jabr-0.1.0.tar.gz

Download URL jabr-0.1.0.tar.gz
Size 18.4 kB
Tags Source
SHA-256 checksum
How to use checksums
90657697d890d9fd42b66e78f89601569f90893e3ddf747f946fa26f42e83e1d
BLAKE2b-256 checksum
How to use checksums
13c54462b5c31b62e0d9ea7773273c4ebc381273f98ccb63643663a394756b57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 1, 2026.

Transparency log

Release files / jabr-0.1.0-py3-none-any.whl

Download URL jabr-0.1.0-py3-none-any.whl
Size 13.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78456aa2ebb7de0ee6bacd6e20ec3424c268308925e7f100228e69b30c49901b
BLAKE2b-256 checksum
How to use checksums
074ea9171549ba0b40a7b0a15e6d55f291adaebdcb01744f8aa0d5423d2cb5a7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 1, 2026.

Transparency log

Security for jabr 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for jabr-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 1, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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