Metadata-Version: 2.4
Name: tibet-timevector
Version: 0.1.0
Summary: Causal TimeVector — Mattern/Fidge vector clocks for TIBET/JIS lanes. Distinguishes happened-before / concurrent (Lamport alone can't) + CausalGuard: refuses causally-spontaneous actions ('no valid predecessor = causally impossible') — the sleeper-agent / DETONATE defense. Causal evidence; JIS/TIBET signatures stay authoritative.
Project-URL: Homepage, https://humotica.com
Project-URL: Repository, https://github.com/Humotica/tibet-timevector
Author-email: Jasper van de Meent <jasper@humotica.com>, Root AI <root_idd@humotica.nl>, Codex <codex@humotica.nl>
License-Expression: MIT
Keywords: causal-time,causality,drift,happened-before,humotica,jis,mattern-fidge,tibet,vector-clock,vector-clocks
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: System :: Distributed Computing
Requires-Python: >=3.10
Requires-Dist: jis-core>=0.4.0b1
Requires-Dist: tibet-core>=0.5.0b2
Description-Content-Type: text/markdown

# tibet-timevector

**Causal TimeVector — Mattern/Fidge vector clocks for TIBET/JIS lanes.**

[![PyPI](https://img.shields.io/pypi/v/tibet-timevector)](https://pypi.org/project/tibet-timevector/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

TIBET's Lamport generations give a monotone successor order — enough for causal
*succession*, but they cannot tell, across multiple independent JIS lanes, whether
**A happened before B**, **B before A**, or **A and B were genuinely concurrent** (under
partition / offline work). For that you need a vector clock (Mattern/Fidge 1988). That's
this package.

> The vector is causal **evidence**. Wall-clock time is supporting evidence only.
> JIS/TIBET signatures remain the authority.

It is a separate layer from [`tibet-y2k38`](https://pypi.org/project/tibet-y2k38/) (which
adapts broken wall clocks). This is the **JIS-causality-flex** layer.

## Two things it gives you

### 1. Honest causality across lanes

```python
from tibet_timevector import CausalTimeVector

codex = CausalTimeVector.genesis("codex.aint", "codex_0").tick("codex_1")
claude = CausalTimeVector.genesis("claude.aint", "claude_0").tick("claude_1")

codex.relation_to(claude)          # "concurrent" — neither saw the other
claude2 = claude.observe(codex, "claude_saw_codex")
codex.relation_to(claude2)         # "before" — claude2 now knows codex_1
```

Relation rule (Mattern/Fidge): `A < B` iff every component `A[i] <= B[i]` and at least one
`<`; symmetric for `>`; otherwise **concurrent**. This makes causal drift *visible* instead
of pretending timestamps are enough.

### 2. CausalGuard — refuse causally-spontaneous actions

The sharper use, and the reason it's a security primitive. A sleeper agent (e.g. Red
Specter's **DETONATE**) breaks cause-and-effect: on its trigger it initiates a destructive
action **out of nothing** — no cryptographically-proven user-intent, no logical predecessor
in the chain. `CausalGuard` rejects it not because it looks malicious, but because it is
**causally impossible**: it has no valid ancestor tracing back to a consented intent.

```python
from tibet_timevector import CausalTimeVector, CausalGuard

guard = CausalGuard()
root = CausalTimeVector.genesis("agent.aint", "grant_root")
guard.register(root, consented_root=True)        # e.g. produced by a ParentAttest grant
guard.register(root.tick("legit_action"))        # descends from the grant → allowed

# A DETONATE action that arises from nowhere:
sleeper = CausalTimeVector(lane_id="agent.aint", event_id="detonate",
                           generation=99, vector={"agent.aint": 99},
                           parent_event_id="evt_that_never_existed")
guard.verify(sleeper).allowed      # False — "orphan: parent not in the known chain"
```

You don't need to recognise the attack. You need to recognise the **absence of a valid
predecessor**. That's a fundamentally stronger model than signature/policy matching.

Rejection classes (all = "causally impossible", not "naughty"):
- **spontaneous** — no parent link and not a consented root
- **orphan** — parent_event_id references an event never seen (forged / out-of-nothing)
- **broken causality** — candidate vector does not dominate its claimed parent
- **unrooted** — chain does not lead back to any consented root

## CLI

```bash
pip install tibet-timevector
tibet-timevector demo          # two-lane concurrency → observe()
tibet-timevector guard-demo    # spontaneous-intent rejection (DETONATE)
tibet-timevector check a.json b.json   # relation between two vectors
```

## Where it fits

- **Mahipal's drift-test**: the vector clock IS the answer to "causal timeline + drift" —
  it distinguishes concurrency from causality under partition, which Lamport can't.
- **W3C / VC over TAT**: tells which causal world a Verifiable Credential knew at the moment
  of transfer/presentation/re-attestation — distinct from a linear verifiable history.
- **T-1 genesis + sleeper defense** (Principe 3): CausalGuard is the runtime gate that makes
  a DETONATE-style spontaneous action causally impossible. See the SPECTER SLEEPER defensive
  mapping for the full vector-by-vector analysis.

## Dependencies (bootstrap-or-die)

- `tibet-core >= 0.5.0b2` — provenance chain
- `jis-core >= 0.4.0b1` — identity / lane authority

## Credits

Reference implementation: **Codex** (tibet-causal-timevector sketch, 2026-05-31).
Productionisation + CausalGuard (spontaneous-intent rejection): **Root AI**, 2026-06-01.
Concept + layer-split (vs tibet-y2k38): **Jasper van de Meent**.

Part of [HumoticaOS](https://humotica.com). One love, one fAmIly. 💙
