memware 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memware-0.1.1/.claude-plugin/marketplace.json +19 -0
- memware-0.1.1/.github/CODEOWNERS +1 -0
- memware-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +21 -0
- memware-0.1.1/.github/ISSUE_TEMPLATE/config.yml +5 -0
- memware-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +17 -0
- memware-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- memware-0.1.1/.github/dependabot.yml +8 -0
- memware-0.1.1/.github/workflows/ci.yml +29 -0
- memware-0.1.1/.github/workflows/release.yml +74 -0
- memware-0.1.1/.gitignore +15 -0
- memware-0.1.1/.pre-commit-config.yaml +13 -0
- memware-0.1.1/CHANGELOG.md +53 -0
- memware-0.1.1/CODE_OF_CONDUCT.md +47 -0
- memware-0.1.1/CONTRIBUTING.md +45 -0
- memware-0.1.1/LICENSE +21 -0
- memware-0.1.1/PKG-INFO +163 -0
- memware-0.1.1/README.md +132 -0
- memware-0.1.1/RELEASING.md +136 -0
- memware-0.1.1/SECURITY.md +19 -0
- memware-0.1.1/docs/design.md +104 -0
- memware-0.1.1/docs/eval.md +111 -0
- memware-0.1.1/docs/integrations.md +62 -0
- memware-0.1.1/docs/upstream-hermes-pr.md +141 -0
- memware-0.1.1/eval/questions.example.jsonl +3 -0
- memware-0.1.1/integrations/claude-code/.claude-plugin/plugin.json +8 -0
- memware-0.1.1/integrations/claude-code/README.md +8 -0
- memware-0.1.1/integrations/claude-code/hooks/hooks.json +13 -0
- memware-0.1.1/integrations/hermes/README.md +23 -0
- memware-0.1.1/integrations/hermes/memware/__init__.py +376 -0
- memware-0.1.1/integrations/hermes/memware/plugin.yaml +12 -0
- memware-0.1.1/integrations/hermes/upstream/README.md +93 -0
- memware-0.1.1/integrations/hermes/upstream/plugins/memory/memware/README.md +69 -0
- memware-0.1.1/integrations/hermes/upstream/plugins/memory/memware/__init__.py +509 -0
- memware-0.1.1/integrations/hermes/upstream/plugins/memory/memware/config_schema.py +46 -0
- memware-0.1.1/integrations/hermes/upstream/plugins/memory/memware/plugin.yaml +14 -0
- memware-0.1.1/integrations/hermes/upstream/tests/plugins/memory/test_memware_provider.py +403 -0
- memware-0.1.1/integrations/hermes/upstream/website/docs/user-guide/features/memory-providers.memware.md +65 -0
- memware-0.1.1/pyproject.toml +72 -0
- memware-0.1.1/scripts/leak-check.sh +14 -0
- memware-0.1.1/src/memware/__init__.py +25 -0
- memware-0.1.1/src/memware/cli.py +311 -0
- memware-0.1.1/src/memware/eval.py +208 -0
- memware-0.1.1/src/memware/index.py +380 -0
- memware-0.1.1/src/memware/ingest/__init__.py +223 -0
- memware-0.1.1/src/memware/ingest/claude_code.py +58 -0
- memware-0.1.1/src/memware/ingest/generic.py +51 -0
- memware-0.1.1/src/memware/ledger.py +347 -0
- memware-0.1.1/src/memware/mcp_server.py +96 -0
- memware-0.1.1/src/memware/passage.py +87 -0
- memware-0.1.1/src/memware/py.typed +0 -0
- memware-0.1.1/src/memware/review.py +175 -0
- memware-0.1.1/src/memware/store.py +209 -0
- memware-0.1.1/tests/__init__.py +0 -0
- memware-0.1.1/tests/conftest.py +59 -0
- memware-0.1.1/tests/test_cli.py +34 -0
- memware-0.1.1/tests/test_eval.py +102 -0
- memware-0.1.1/tests/test_hermes_plugin.py +88 -0
- memware-0.1.1/tests/test_hermes_upstream_plugin.py +192 -0
- memware-0.1.1/tests/test_index.py +193 -0
- memware-0.1.1/tests/test_ingest.py +184 -0
- memware-0.1.1/tests/test_ledger.py +110 -0
- memware-0.1.1/tests/test_passage.py +136 -0
- memware-0.1.1/tests/test_review.py +19 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "memware",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "ericwalisko",
|
|
5
|
+
"url": "https://github.com/ericwalisko"
|
|
6
|
+
},
|
|
7
|
+
"description": "Memory for AI agents that only remembers the latest truth.",
|
|
8
|
+
"plugins": [
|
|
9
|
+
{
|
|
10
|
+
"name": "memware",
|
|
11
|
+
"source": "./integrations/claude-code",
|
|
12
|
+
"description": "Session transcripts indexed for recall; a belief ledger that only remembers the latest truth. Hooks: SessionEnd/PreCompact sync, prompt-time belief context.",
|
|
13
|
+
"version": "0.1.1",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "ericwalisko"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @ericwalisko
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something behaves differently from what the docs say
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: input
|
|
6
|
+
id: version
|
|
7
|
+
attributes: { label: memware version, placeholder: "memware --version" }
|
|
8
|
+
validations: { required: true }
|
|
9
|
+
- type: input
|
|
10
|
+
id: env
|
|
11
|
+
attributes: { label: Python and OS, placeholder: "3.12, macOS 15" }
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: repro
|
|
14
|
+
attributes:
|
|
15
|
+
label: Minimal reproduction
|
|
16
|
+
description: Commands or a short script using synthetic data. Never paste real transcripts.
|
|
17
|
+
validations: { required: true }
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: expected
|
|
20
|
+
attributes: { label: Expected vs actual }
|
|
21
|
+
validations: { required: true }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a change
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes: { label: The problem this solves }
|
|
8
|
+
validations: { required: true }
|
|
9
|
+
- type: textarea
|
|
10
|
+
id: proposal
|
|
11
|
+
attributes: { label: Proposal }
|
|
12
|
+
- type: dropdown
|
|
13
|
+
id: readpath
|
|
14
|
+
attributes:
|
|
15
|
+
label: Does this add a model call to capture or recall?
|
|
16
|
+
options: ["No", "Yes, as an optional extra", "Yes, in the default path"]
|
|
17
|
+
validations: { required: true }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## What
|
|
2
|
+
|
|
3
|
+
<!-- one or two sentences -->
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
<!-- the problem, with a link to the issue if there is one -->
|
|
8
|
+
|
|
9
|
+
## Checklist
|
|
10
|
+
|
|
11
|
+
- [ ] Tests added or updated (synthetic fixtures only)
|
|
12
|
+
- [ ] `ruff check`, `ruff format --check`, `mypy`, `pytest` pass locally
|
|
13
|
+
- [ ] Ledger semantics unchanged, or `docs/design.md` updated in this PR
|
|
14
|
+
- [ ] Commits are signed off (`git commit -s`)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ${{ matrix.os }}
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
os: [ubuntu-latest, macos-latest]
|
|
18
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
- run: python -m pip install --upgrade pip && pip install -e ".[dev,mcp]"
|
|
25
|
+
- run: ruff check src tests integrations
|
|
26
|
+
- run: ruff format --check src tests integrations
|
|
27
|
+
- run: mypy
|
|
28
|
+
- run: pytest --cov=memware --cov-report=term-missing
|
|
29
|
+
- run: python -m pip install build && python -m build
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishing is authorized by a PyPI *trusted publisher* (OIDC): no API token is
|
|
4
|
+
# stored anywhere. The binding on pypi.org names this repository, this workflow
|
|
5
|
+
# file, and the `pypi` environment below — change any of the three and the
|
|
6
|
+
# upload stops working. See RELEASING.md.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Build sdist and wheel
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip build twine
|
|
28
|
+
python -m build
|
|
29
|
+
twine check --strict dist/*
|
|
30
|
+
|
|
31
|
+
- name: Install the wheel into a clean venv
|
|
32
|
+
# Core memware has no runtime dependencies, so this must resolve with the
|
|
33
|
+
# index switched off — anything else means a dependency leaked in.
|
|
34
|
+
run: |
|
|
35
|
+
python -m venv /tmp/verify
|
|
36
|
+
/tmp/verify/bin/pip install --no-index --find-links dist memware
|
|
37
|
+
|
|
38
|
+
- name: The console script reports the built version
|
|
39
|
+
run: |
|
|
40
|
+
version="$(/tmp/verify/bin/memware --version)"
|
|
41
|
+
echo "built version: ${version}"
|
|
42
|
+
if [ "${GITHUB_REF_TYPE}" = "tag" ] && [ "${GITHUB_REF_NAME#v}" != "${version}" ]; then
|
|
43
|
+
echo "::error::tag ${GITHUB_REF_NAME} does not match package version ${version}"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
- name: The test suite passes against the installed wheel
|
|
48
|
+
# Imports resolve to site-packages, not src/ — this is what catches a
|
|
49
|
+
# subpackage or data file that never made it into the distribution.
|
|
50
|
+
run: |
|
|
51
|
+
/tmp/verify/bin/pip install pytest
|
|
52
|
+
/tmp/verify/bin/python -m pytest tests -q
|
|
53
|
+
|
|
54
|
+
- uses: actions/upload-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: dist
|
|
57
|
+
path: dist/
|
|
58
|
+
|
|
59
|
+
publish:
|
|
60
|
+
needs: build
|
|
61
|
+
# A manual run on a branch builds and verifies but never publishes.
|
|
62
|
+
if: github.ref_type == 'tag'
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
environment:
|
|
65
|
+
name: pypi
|
|
66
|
+
url: https://pypi.org/p/memware
|
|
67
|
+
permissions:
|
|
68
|
+
id-token: write
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/download-artifact@v4
|
|
71
|
+
with:
|
|
72
|
+
name: dist
|
|
73
|
+
path: dist/
|
|
74
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
memware-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.16.5
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
9
|
+
rev: v5.0.0
|
|
10
|
+
hooks:
|
|
11
|
+
- id: end-of-file-fixer
|
|
12
|
+
- id: trailing-whitespace
|
|
13
|
+
- id: check-added-large-files
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **Passage-level index.** Turns are split into ~300-500-token passages at ingest
|
|
11
|
+
(`memware.passage`), anchored by turn id and character offset, and FTS5 now indexes
|
|
12
|
+
passages instead of whole turns. Recall ranks passages, collapses to one hit per turn
|
|
13
|
+
and quotes only that turn's best matching passages (`passages_per_turn`, default 3);
|
|
14
|
+
`read_session` still returns whole turns. On a 24-question fact set this held accuracy
|
|
15
|
+
exactly (fact 24/24, stale 8/8, stale_rate 0) while halving the retrieved context,
|
|
16
|
+
30,403 -> 15,410 characters. The database is ~1.8x larger, since a passage stores its
|
|
17
|
+
own text.
|
|
18
|
+
- Existing stores migrate on first open (`PRAGMA user_version` 0 -> 1): `turn_fts` is
|
|
19
|
+
dropped and every turn on disk is chunked, ~5 s for an 18k-turn corpus.
|
|
20
|
+
- `memware-eval` reports the median retrieved context size per question.
|
|
21
|
+
|
|
22
|
+
## [0.1.1] - 2026-09-03
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Multi-query recall: `memware recall Q1 Q2 …`, MCP `recall(queries=[…])`, Hermes `memware_recall(queries)` — phrasings fused by reciprocal rank so the calling agent supplies synonyms and expected values at call time.
|
|
26
|
+
- Persistent skip list: `~/.memware/ignore-markers.txt` and `MEMWARE_IGNORE_MARKERS` — content markers every sync honours, so transcripts predating a marker or the no-capture flag are filtered by signature.
|
|
27
|
+
- Evaluation guardrails: `MEMWARE_NO_CAPTURE=1` (hooks/provider/`sync --from-hook` no-op), `sync --skip-if-contains TEXT` / `--exclude GLOB`, `memware prune`, `memware-eval --corpus/--beliefs-from` clean-store builds, `memware.eval.MARKER`.
|
|
28
|
+
- Hermes memory-provider plugin implementing the `MemoryProvider` ABC (prefetch, non-blocking sync_turn, session flush, built-in memory mirroring, four recall/remember tools); the repo is a Claude Code plugin marketplace (`claude plugin marketplace add ericwalisko/memware`).
|
|
29
|
+
- `integrations/hermes/upstream/`: the Hermes provider packaged as hermes-agent's own `plugins/memory/<name>/` tree — lazy-installed dependency, profile-scoped store, `backup_paths()`, declarative desktop config schema — with tests in their layout, a docs entry draft, and a draft PR description in `docs/upstream-hermes-pr.md`. Prepared, not submitted.
|
|
30
|
+
- Turn hits carry `snippet`: the FTS5 window around the matched terms (the head of a long turn often lacks the answer). Default window 96 tokens; `memware recall --snippet-tokens N`.
|
|
31
|
+
- Release workflow that publishes to PyPI from a `v*` tag via trusted publishing
|
|
32
|
+
(OIDC, no stored token). It installs the built wheel into a clean venv and refuses
|
|
33
|
+
to upload when the tag and the package version disagree; `RELEASING.md` documents
|
|
34
|
+
the one-time pypi.org setup and the per-release steps.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- Stale scoring is positional: an answer is stale only when the old value appears before the current one.
|
|
38
|
+
- `memware-eval` mirrors the hook's subject gate for the beliefs context and reports the belief injection rate (overall and on negatives).
|
|
39
|
+
- `memware-eval` now scores two contexts per question: `beliefs` (what a prompt-time hook injects) and `beliefs+turns`; negatives pass when the expected value is absent rather than when the context is empty.
|
|
40
|
+
- The package version is read from `memware.__version__` by the build backend, so
|
|
41
|
+
`memware --version` and the published distribution cannot disagree.
|
|
42
|
+
|
|
43
|
+
## [0.1.0] - 2026-09-02
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
- Bi-temporal belief ledger with deterministic `(subject, relation)` supersession,
|
|
47
|
+
event-time ordering, reinforcement, and reliability-gated review.
|
|
48
|
+
- FTS5 transcript index with BM25 × activation ranking.
|
|
49
|
+
- Ingest adapters for Claude Code session JSONL and generic message JSONL, with
|
|
50
|
+
idempotent byte-offset cursors.
|
|
51
|
+
- `memware` CLI, optional MCP server, and retrieval-level evaluation runner.
|
|
52
|
+
- `ReviewBackend` contract with JSONL and HTTP implementations.
|
|
53
|
+
- Claude Code hook bundle and Hermes memory-provider skeleton.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a
|
|
6
|
+
harassment-free experience for everyone, regardless of age, body size, visible or invisible
|
|
7
|
+
disability, ethnicity, sex characteristics, gender identity and expression, level of
|
|
8
|
+
experience, education, socio-economic status, nationality, personal appearance, race,
|
|
9
|
+
caste, color, religion, or sexual identity and orientation.
|
|
10
|
+
|
|
11
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse,
|
|
12
|
+
inclusive, and healthy community.
|
|
13
|
+
|
|
14
|
+
## Our Standards
|
|
15
|
+
|
|
16
|
+
Examples of behavior that contributes to a positive environment include demonstrating
|
|
17
|
+
empathy and kindness, being respectful of differing opinions, giving and gracefully
|
|
18
|
+
accepting constructive feedback, accepting responsibility and apologizing to those
|
|
19
|
+
affected by our mistakes, and focusing on what is best for the overall community.
|
|
20
|
+
|
|
21
|
+
Examples of unacceptable behavior include sexualized language or imagery, trolling,
|
|
22
|
+
insulting or derogatory comments, personal or political attacks, public or private
|
|
23
|
+
harassment, publishing others' private information without explicit permission, and other
|
|
24
|
+
conduct which could reasonably be considered inappropriate in a professional setting.
|
|
25
|
+
|
|
26
|
+
## Enforcement Responsibilities
|
|
27
|
+
|
|
28
|
+
Community leaders are responsible for clarifying and enforcing our standards and will take
|
|
29
|
+
appropriate and fair corrective action in response to any behavior they deem inappropriate,
|
|
30
|
+
threatening, offensive, or harmful.
|
|
31
|
+
|
|
32
|
+
## Scope
|
|
33
|
+
|
|
34
|
+
This Code of Conduct applies within all community spaces, and also applies when an
|
|
35
|
+
individual is officially representing the community in public spaces.
|
|
36
|
+
|
|
37
|
+
## Enforcement
|
|
38
|
+
|
|
39
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the
|
|
40
|
+
maintainers through GitHub's private vulnerability reporting for this repository or by
|
|
41
|
+
opening an issue marked confidential. All complaints will be reviewed and investigated
|
|
42
|
+
promptly and fairly.
|
|
43
|
+
|
|
44
|
+
## Attribution
|
|
45
|
+
|
|
46
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
47
|
+
version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for considering a contribution. Small, focused pull requests are easiest to review.
|
|
4
|
+
|
|
5
|
+
## Development
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/ericwalisko/memware && cd memware
|
|
9
|
+
uv venv && uv pip install -e ".[dev,mcp]" # or: python -m venv .venv && pip install -e ".[dev,mcp]"
|
|
10
|
+
ruff check src tests && ruff format --check src tests
|
|
11
|
+
mypy
|
|
12
|
+
pytest
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
CI runs the same commands on Python 3.11, 3.12 and 3.13.
|
|
16
|
+
|
|
17
|
+
## Ground rules
|
|
18
|
+
|
|
19
|
+
- **Tests first.** Every behaviour change comes with a test that fails without it.
|
|
20
|
+
Fixtures are synthetic — never commit real transcripts or memories.
|
|
21
|
+
- **The ledger semantics are a contract.** Changes to supersession ordering, policies,
|
|
22
|
+
or what `recall` may return need a design note in `docs/design.md` in the same PR.
|
|
23
|
+
- **No model in the read path.** Proposals that add an LLM call to capture or recall
|
|
24
|
+
should be framed as optional, off-by-default extras.
|
|
25
|
+
- Keep the core dependency-free. New runtime dependencies go behind an extra.
|
|
26
|
+
|
|
27
|
+
## Releasing
|
|
28
|
+
|
|
29
|
+
Maintainers only: [RELEASING.md](RELEASING.md) covers the one-time PyPI trusted-publisher
|
|
30
|
+
setup and the per-release steps. Releases are cut from a `v*` tag; nothing is published
|
|
31
|
+
by hand.
|
|
32
|
+
|
|
33
|
+
## Sign-off (DCO)
|
|
34
|
+
|
|
35
|
+
This project uses the [Developer Certificate of Origin](https://developercertificate.org/).
|
|
36
|
+
Sign each commit with `git commit -s`, which adds `Signed-off-by: Your Name <email>`.
|
|
37
|
+
No CLA.
|
|
38
|
+
|
|
39
|
+
## Reporting bugs and proposing features
|
|
40
|
+
|
|
41
|
+
Use the issue templates. For security issues, see [SECURITY.md](SECURITY.md).
|
|
42
|
+
|
|
43
|
+
## Code of conduct
|
|
44
|
+
|
|
45
|
+
Participation is governed by the [Code of Conduct](CODE_OF_CONDUCT.md).
|
memware-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eric Walisko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
memware-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: memware
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Memory for AI agents that only remembers the latest truth: a bi-temporal belief ledger plus a transcript index, in one SQLite file.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ericwalisko/memware
|
|
6
|
+
Project-URL: Issues, https://github.com/ericwalisko/memware/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/ericwalisko/memware/blob/main/CHANGELOG.md
|
|
8
|
+
Author: ericwalisko
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent-memory,bitemporal,claude-code,fts5,hermes,llm,mcp,sqlite
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
26
|
+
Requires-Dist: pyyaml>=6; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff==0.16.5; extra == 'dev'
|
|
28
|
+
Provides-Extra: mcp
|
|
29
|
+
Requires-Dist: mcp>=1.2; extra == 'mcp'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# memware
|
|
33
|
+
|
|
34
|
+
**Memory for AI agents that only remembers the latest truth.**
|
|
35
|
+
|
|
36
|
+
memware is one SQLite file with two stores:
|
|
37
|
+
|
|
38
|
+
- **turns** — immutable evidence. Every prompt and answer from past sessions,
|
|
39
|
+
split into ~400-token passages and indexed with FTS5. Recall ranks passages and
|
|
40
|
+
quotes only the matching ones; reading a session back returns whole turns.
|
|
41
|
+
BM25 × recency × use, no model in the loop.
|
|
42
|
+
- **beliefs** — a bi-temporal ledger of facts. A new value for the same
|
|
43
|
+
`(subject, relation)` **supersedes** the old one. Recall only ever returns the
|
|
44
|
+
currently valid belief; history is kept for audit and never reaches a prompt.
|
|
45
|
+
|
|
46
|
+
No daemon, no vector database, no LLM call at capture or read time. A 30-day
|
|
47
|
+
corpus of a busy coding agent — 18k turns, 40k passages — indexes in about
|
|
48
|
+
fourteen seconds into ~120 MB.
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
$ memware sync ~/.claude/projects --harness claude-code
|
|
52
|
+
{"added": 14348, "files": 1475}
|
|
53
|
+
|
|
54
|
+
$ memware assert "api" "listens on port" "8443" --source "session 3f2a, turn 41"
|
|
55
|
+
{"outcome": "superseded", "belief_id": 2, "incumbent_id": 1}
|
|
56
|
+
|
|
57
|
+
$ memware recall "which port does the api use" --what beliefs
|
|
58
|
+
api listens on port 8443 # 8080 is in the ledger, retired, and never surfaces
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Why
|
|
62
|
+
|
|
63
|
+
Agent memory systems that rewrite what they remember degrade: continuous
|
|
64
|
+
LLM consolidation can push utility *below* having no memory at all
|
|
65
|
+
([Useful Memories Become Faulty When Continuously Updated by LLMs](https://arxiv.org/abs/2605.12978)).
|
|
66
|
+
And embeddings cannot tell a *contradicted* fact from a *rephrased* one — AUROC 0.59 —
|
|
67
|
+
so vector stores serve stale facts 15–40% of the time on evolving knowledge
|
|
68
|
+
([Temporal Validity in Retrieval Memory](https://arxiv.org/abs/2606.26511)).
|
|
69
|
+
|
|
70
|
+
memware borrows four mechanisms from human memory research and keeps them deliberately small:
|
|
71
|
+
|
|
72
|
+
| mechanism | in the brain | in memware |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| evidence ≠ belief | hippocampus vs neocortex (complementary learning systems) | `turn` table is append-only; `belief` table is separate |
|
|
75
|
+
| update on surprise | reconsolidation driven by prediction error | `memware assert` at the moment an agent notices a conflict |
|
|
76
|
+
| only the latest understanding | reconsolidated traces overwrite in place | deterministic supersession keyed on `(subject, relation)`, ordered by **event time** |
|
|
77
|
+
| need-probability recall | Anderson & Schooler 1991 / ACT-R activation | `bm25 × (1+age)^-d × (1 + w·ln(1+uses))` |
|
|
78
|
+
|
|
79
|
+
Full rationale and citations: [docs/design.md](docs/design.md).
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install memware # core, stdlib only (SQLite with FTS5)
|
|
85
|
+
pip install "memware[mcp]" # + MCP server
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Use it from Claude Code
|
|
89
|
+
|
|
90
|
+
`integrations/claude-code/` is a Claude Code plugin (`claude plugin marketplace add
|
|
91
|
+
ericwalisko/memware`, then `claude plugin install memware@memware`). Hooks: `SessionEnd`/`PreCompact` sync the
|
|
92
|
+
transcript into the index; an optional `UserPromptSubmit` hook injects the handful of
|
|
93
|
+
currently valid beliefs relevant to the prompt (beliefs only — transcript search is
|
|
94
|
+
on demand through the MCP tools). See [docs/integrations.md](docs/integrations.md).
|
|
95
|
+
|
|
96
|
+
## Use it from Hermes Agent
|
|
97
|
+
|
|
98
|
+
`integrations/hermes/memware/` is a memory-provider plugin built on Hermes's
|
|
99
|
+
`MemoryProvider` ABC — prompt-time belief prefetch, non-blocking turn capture, and
|
|
100
|
+
`memware_recall` / `memware_remember` tools — sharing one store with Claude Code.
|
|
101
|
+
|
|
102
|
+
## The supersession rule
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
same key, same value → reinforce (reliability rises, use is counted)
|
|
106
|
+
same key, newer value → supersede: incumbent gets valid_to = new.valid_from
|
|
107
|
+
same key, older value → filed as history; the timeline stays consistent
|
|
108
|
+
weaker challenger → parked as a candidate and sent to review
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Ordering is decided by `valid_from` (when the evidence says it became true), never by
|
|
112
|
+
insertion order — so a backfill converges to the same state in any order, twice, or in
|
|
113
|
+
batches. Three policies: `auto` (last writer by event time), `gate_conflicts`
|
|
114
|
+
(default: a less reliable challenger goes to review), `await_confirmation`.
|
|
115
|
+
|
|
116
|
+
## Recall is keyword search; the agent supplies the meaning
|
|
117
|
+
|
|
118
|
+
The index is FTS5/BM25 — fast, model-free, and literal. The `recall` tool therefore takes
|
|
119
|
+
**several phrasings** and fuses them by reciprocal rank, so a tool-calling agent puts its
|
|
120
|
+
own reasoning into retrieval at call time (synonyms, related concepts, the literal value it
|
|
121
|
+
expects), the same way it would issue a few grep or web-search queries:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
recall(queries=["which port does the api listen on", "api port", "8443", "gateway listen port"])
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Prompt-time injection (the hooks) stays deterministic and only injects beliefs whose
|
|
128
|
+
*subject* the prompt names.
|
|
129
|
+
|
|
130
|
+
## Keeping evaluations out of the evidence
|
|
131
|
+
|
|
132
|
+
Headless runs write transcripts too. Set `MEMWARE_NO_CAPTURE=1` in any run you do not want
|
|
133
|
+
indexed (hooks, the Hermes provider and `memware sync --from-hook` all honour it), put
|
|
134
|
+
`[memware-eval]` in evaluation prompts, and use `memware-eval --corpus ROOT --db scratch.db
|
|
135
|
+
--beliefs-from ~/.memware/memware.db` to judge retrieval against a store that excludes them.
|
|
136
|
+
`memware prune --containing TEXT` un-indexes runs that already slipped in. For a durable filter that every sync honours — including runs that predate a marker — list content signatures in `~/.memware/ignore-markers.txt` (or `MEMWARE_IGNORE_MARKERS`); any transcript whose head contains one is never indexed.
|
|
137
|
+
|
|
138
|
+
## Reviewing contested supersessions
|
|
139
|
+
|
|
140
|
+
memware does not ship a UI. It ships a contract — `ReviewBackend` with `publish()` and
|
|
141
|
+
`collect()` — plus two implementations: JSONL outbox/inbox files and a plain HTTP
|
|
142
|
+
endpoint. Wire it to whatever you already use to make decisions.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
memware review sync # outbox ~/.memware/review-outbox.jsonl
|
|
146
|
+
echo '{"review_id": 7, "decision": "approve"}' >> ~/.memware/review-inbox.jsonl
|
|
147
|
+
memware review sync # applied
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Evaluation
|
|
151
|
+
|
|
152
|
+
`memware-eval` scores retrieval against a question set: does the right evidence
|
|
153
|
+
surface, and does the stale value stay hidden? It needs no model, so results are
|
|
154
|
+
reproducible. The protocol for end-to-end comparisons — agent alone vs agent + memware —
|
|
155
|
+
is in [docs/eval.md](docs/eval.md).
|
|
156
|
+
|
|
157
|
+
## Status
|
|
158
|
+
|
|
159
|
+
Alpha. The schema may change before 1.0; the ledger semantics will not.
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT. See [LICENSE](LICENSE).
|