Metadata-Version: 2.5
Name: spendsignal
Version: 0.9.3
Summary: A small local-first library for logging line-item purchases with your own retrospective outcomes, and retrieving that history when you're about to buy something similar.
Project-URL: Homepage, https://github.com/YemaneSG/SpendSignal
Project-URL: Issues, https://github.com/YemaneSG/SpendSignal/issues
Project-URL: Source, https://github.com/YemaneSG/SpendSignal
Project-URL: Changelog, https://github.com/YemaneSG/SpendSignal/blob/main/CHANGELOG.md
Author: Yemane
License-Expression: MIT
License-File: LICENSE
Keywords: evidence,local-first,personal-finance,personal-informatics,purchase-history,receipts
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: pydantic<3,>=2.5
Provides-Extra: actual
Requires-Dist: actualpy>=0.20; extra == 'actual'
Provides-Extra: all
Requires-Dist: actualpy>=0.20; extra == 'all'
Requires-Dist: invoice2data>=1.0; extra == 'all'
Requires-Dist: mcp>=1.0; extra == 'all'
Provides-Extra: extract
Requires-Dist: invoice2data>=1.0; extra == 'extract'
Provides-Extra: match
Provides-Extra: mcp
Requires-Dist: mcp>=1.0; extra == 'mcp'
Provides-Extra: retrieval
Description-Content-Type: text/markdown

# SpendSignal

A deterministic behavioral feedback loop for personal purchases.

`v0.8.0` · [PyPI](https://pypi.org/project/spendsignal/) · Private (in development)

Also available as `signal` — the short alias.

---

## The loop

```
log      — bring in your purchases with real item-level detail
reflect  — answer questions about each item, build your knowledge base
recall   — have I bought anything like this before?
distill  — what does my history say about this specific item?
```

Retrieval over your own past, not prediction. The engine never invents a score. Missing evidence = explicit abstention.

---

## Try it in 2 minutes

Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/getting-started/installation/).

```bash
git clone git@github.com:YemaneSG/SpendSignal.git
cd SpendSignal
uv sync

# Set up the demo with real purchase data
uv run signal demo

# Answer questions — build your knowledge base
uv run signal reflect

# Query it
uv run signal recall  --query "protein powder"
uv run signal distill --subject nutricost-whey-protein

# Reset and try again with a fresh selection
uv run signal demo --reset
uv run signal reflect
```

The seed data contains real Amazon purchases — real item names, real prices — across 15 months. Seven behavioral patterns are embedded: repeat purchases, regretted purchases, revised opinions, contradictions, and items with no feedback yet.

---

## Your Amazon data

Download your full order history: amazon.com → Account & Lists → Download Order Reports

```bash
signal log --csv ~/Downloads/amazon-orders.csv

signal reflect
signal recall  --query "what I bought for sleep"
signal distill --subject zonli-weighted-blanket
```

No bank credentials. No API keys. No OCR.

---

## Development

```bash
git clone git@github.com:YemaneSG/SpendSignal.git
cd SpendSignal
uv sync
uv tool install -e .   # puts `signal` on PATH, live-reloads source changes

signal demo            # try it immediately

uv run pytest -q
uv run ruff check .
uv run mypy
```

To remove `signal` from your PATH when you're done:

```bash
uv tool uninstall spendsignal
```

Regenerate the fixtures:

```bash
uv run python scripts/generate_fixtures.py
```

---

## How it works

**Four JSON schemas** in [`schemas/`](schemas/) define the contracts. Same input, same output, always.

```
purchase-event        → what you bought and what was in the basket
reflection-exposure   → when you were asked about a purchase
feedback-event        → your answer  (worth_it · would_buy_again · still_using)
evidence-summary      → deterministic output of your knowledge base query
```

The engine lives in [`src/spendsignal/aggregate.py`](src/spendsignal/aggregate.py). It handles:

- **Point-in-time reconstruction** — query at any past date and get the state of your knowledge as of that moment
- **Supersession** — change your mind later; the old answer is preserved, the new one is current
- **Contradiction detection** — bought the same thing twice and rated it differently? The engine surfaces the disagreement
- **Explicit abstention** — no feedback yet means "insufficient evidence", never a guess

---

## License

MIT. See [LICENSE](LICENSE).
