Metadata-Version: 2.4
Name: provenance-engine
Version: 0.1.0
Summary: Portal GC — attractor-based graph lifecycle management for persistent knowledge systems
Author-email: PortalVision <provenance@portalvision.dev>
License-Expression: MIT
Project-URL: Homepage, https://github.com/portalvision/provenance-engine
Project-URL: Repository, https://github.com/portalvision/provenance-engine
Project-URL: Documentation, https://github.com/portalvision/provenance-engine#readme
Keywords: graph,portal-gc,garbage-collection,knowledge-graph,llm,persistence,lorenz
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.0
Provides-Extra: llm
Requires-Dist: openai>=1.0; extra == "llm"
Provides-Extra: chart
Requires-Dist: numpy>=1.24; extra == "chart"
Requires-Dist: sentence-transformers>=2.2; extra == "chart"
Provides-Extra: sim
Requires-Dist: pygame>=2.5; extra == "sim"
Provides-Extra: all
Requires-Dist: provenance-engine[chart,llm,sim]; extra == "all"
Provides-Extra: dev
Requires-Dist: provenance-engine[all]; extra == "dev"
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# ProvenanceEngine

Portal GC — attractor-based graph lifecycle management for persistent knowledge systems.

Three-phase architecture that uses the geometry of chaos (Lorenz equations) to decide what your graph remembers and what it forgets:

1. **Map** — graph nodes → Portal initial conditions (x₀, y₀, z₀) based on structural connectivity, association strength, and temporal vitality
2. **Integrate** — RK4 integration per node; classify KEEP / EVICT / REVIEW based on attractor wing residence
3. **Govern** — parameter sweep for stability, LLM probe + gap agents for semantic governance, reports + eviction notices

The attractor's two-wing structure maps to memory dynamics:
- **Left wing** (x < 0): consolidation / retention
- **Right wing** (x > 0): decay / eviction candidate
- **Chaotic boundary**: uncertain — requires review

## Install

```bash
pip install provenance-engine
```

Or with all optional dependencies (LLM governance + semantic search):

```bash
pip install provenance-engine[all]
```

### From source

```bash
git clone https://github.com/portalvision/provenance-engine.git
cd provenance-engine
./setup_venv.sh
```

This creates a `.ProvenanceEngine` venv with everything installed.

## Quick Start

### 1. Initialize

```bash
pe init
```

Creates `.provenance/` with a sample graph.

### 2. Run a scan

```bash
pe scan --graph .provenance/sample_graph.jsonl
```

Classifies every node as KEEP, EVICT, or REVIEW.

### 3. Parameter sweep

```bash
pe sweep --graph .provenance/sample_graph.jsonl
```

Tests Portal ρ × τ grid, identifies the governance-stable band (eviction < 30%, zero load-bearing evictions).

### 4. Generate reports

```bash
pe report --classification classification_rho28.0_tau2.0.json
```

Produces JSON scan, markdown report, and eviction notice.

### 5. LLM governance (optional)

Requires `OPENAI_API_KEY` in your environment:

```bash
pe probe --classification classification_rho28.0_tau2.0.json --graph your_graph.jsonl
pe gap --probe-report probe_report.json
```

The probe agent reviews each EVICT candidate for structural centrality and governance risk. The gap agent synthesizes into final evict / review / explore / keep buckets.

### 6. Semantic search (optional)

Build and query an embedding index over file metadata:

```bash
pe chart-build --source repo_vision.json
pe chart-search --index chart_index.jsonl --query "authentication flow"
```

## Graph Format

Input is JSONL, one node per line:

```json
{
  "id": "unique_node_id",
  "edges": [
    {"target": "other_id", "type": "STRUCTURAL", "strength": 0.8}
  ],
  "importance": "high",
  "load_bearing": true,
  "created_at": "2026-01-01T00:00:00Z",
  "metadata": {}
}
```

**Edge types** (with default connascence weights):
- `STRUCTURAL` (1.2) — direct structural dependency
- `CONCEPTUAL` (1.0) — conceptual relationship
- `CO_VARIANCE` (0.8) — co-varying properties
- `CO_OCCURRENCE` (0.6) — co-occurring references
- `TEMPORAL` (0.4) — temporal association
- `SUPPORTING` (0.8) — supporting evidence
- `SOURCE` (1.0) — source reference

**Importance levels**: `high` (1.0), `medium` (0.6), `low` (0.2)

**Load-bearing**: if `true`, node is escalated from EVICT → REVIEW (never auto-evicted).

## Python API

```python
from provenance_engine import build_graph, normalize_and_scale, integrate_portal, classify_node

nodes = [
    {"id": "a", "edges": [{"target": "b", "strength": 0.9}], "importance": "high"},
    {"id": "b", "edges": [], "importance": "low", "created_at": "2024-01-01T00:00:00Z"},
]

graph = build_graph(nodes)
scaled = normalize_and_scale(graph)

for node in scaled:
    traj = integrate_portal(node["x0"], node["y0"], node["z0"])
    result = classify_node(traj, tau=2.0, load_bearing=node.get("load_bearing", False))
    print(f"{node['id']}: {result['classification']} (mean_x={result['mean_x']:.2f})")
```

## Logging

Every CLI command writes dual-channel logs:

1. **Console** — timestamped, emoji-prefixed, color-coded, scannable
2. **File** — JSON lines at `.provenance/logs/`, machine-readable

```python
from provenance_engine import get_logger

log = get_logger("my_scan")
log.info("Classified 42 nodes", emoji="🔍", counts={"KEEP": 30, "EVICT": 5})
log.warn("High eviction rate", emoji="⚠️", evict_pct=0.35)
log.success("Sweep complete", emoji="✅")
log.section("PHASE 2", emoji="🌀")
```

Emojis are not decoration. They are pre-lexical navigation anchors — the same principle as RAG embeddings, applied to human scanning.

Disable color: `NO_COLOR=1` or `PE_COLOR=off`

## Sound Library

Optional audio feedback using Mario × Dark Souls design:

- **Mario-style**: light, affirming sounds for progress (scan complete, report generated)
- **Dark Souls-style**: deep, grave sounds for boundaries (eviction blocked, invariant violated)

```bash
pe audio-demo               # hear all events
pe audio-demo --style mario  # just the positive ones
```

**Accessibility (hard constraints):**
- Sounds are ALWAYS optional — text + emoji always displayed
- Disable: `PE_AUDIO=off`
- Volume capped, max 500ms, fails silently if audio unavailable

Drop `.wav` files into `provenance_engine/sounds/` to enable playback. See `sounds/README.md` for the event-to-file mapping.

```python
from provenance_engine import play, SoundEvent

play(SoundEvent.SCAN_COMPLETE)       # Mario: affirming
play(SoundEvent.EVICTION_BLOCKED)    # Dark Souls: grave
```

## Verification

```bash
pe verify
```

Runs the full verification suite: tests, sample scan, parameter sweep. Produces a timestamped JSONL log of every step.

## Optional Dependencies

| Extra | What it adds | Install |
|-------|-------------|---------|
| `llm` | LLM governance agents (probe + gap) | `pip install provenance-engine[llm]` |
| `chart` | Semantic search (sentence-transformers) | `pip install provenance-engine[chart]` |
| `all` | Everything | `pip install provenance-engine[all]` |
| `dev` | All + pytest, ruff, build tools | `pip install provenance-engine[dev]` |

## How It Works

### Portal Initial Conditions

Each node maps to (x₀, y₀, z₀):
- **x₀** — structural connectivity (normalized degree in the graph)
- **y₀** — connascence strength (weighted mean of edge associations)
- **z₀** — temporal vitality (inverse log decay from last update)

### RK4 Integration

The Lorenz equations are integrated using 4th-order Runge-Kutta (pure Python, zero dependencies):

```
dx/dt = σ(y - x)       σ = 10
dy/dt = x(ρ - z) - y   ρ = tunable (default 28)
dz/dt = xy - βz         β = 8/3
```

### Classification

After integration, the mean x-coordinate over the last 200 steps determines fate:
- `mean_x < -τ` → **KEEP** (left wing: consolidated memory)
- `mean_x > τ` → **EVICT** (right wing: decayed, safe to remove)
- `|mean_x| ≤ τ` → **REVIEW** (chaotic boundary: operator inspection required)

### Parameter Sweep

The sweep tests combinations of ρ (eviction pressure) and τ (classification threshold) to find the governance-stable band:
- Total eviction rate < 30%
- High-importance eviction rate < 5%
- Zero load-bearing evictions

### LLM Governance

Two-layer LLM review of eviction candidates:
1. **Probe agent** — reviews each Portal EVICT node with graph context; recommends evict/review/explore/keep
2. **Gap agent** — synthesizes probe assessments into final governance decisions

## License

MIT
