lean-memory-console 0.2.0__tar.gz → 0.2.2__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.
Files changed (44) hide show
  1. lean_memory_console-0.2.2/PKG-INFO +246 -0
  2. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/README.md +2 -2
  3. lean_memory_console-0.2.2/pyproject.toml +65 -0
  4. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/__init__.py +1 -1
  5. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_plugin_manifest.py +1 -1
  6. lean_memory_console-0.2.0/PKG-INFO +0 -14
  7. lean_memory_console-0.2.0/pyproject.toml +0 -34
  8. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/.gitignore +0 -0
  9. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/deploy/docker-compose.yml +0 -0
  10. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/app.py +0 -0
  11. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/cli.py +0 -0
  12. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/config.py +0 -0
  13. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/deploy/__init__.py +0 -0
  14. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/engine.py +0 -0
  15. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/events.py +0 -0
  16. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/inspect_sql.py +0 -0
  17. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/mcp_tools.py +0 -0
  18. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/observe_mcp.py +0 -0
  19. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/routes/__init__.py +0 -0
  20. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/routes/data.py +0 -0
  21. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/routes/mcp.py +0 -0
  22. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/routes/review.py +0 -0
  23. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/src/lean_memory_console/routes/views.py +0 -0
  24. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/__init__.py +0 -0
  25. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/conftest.py +0 -0
  26. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/fixtures/__init__.py +0 -0
  27. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/fixtures/build_fixture.py +0 -0
  28. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/fixtures/data_root/.gitignore +0 -0
  29. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/fixtures/data_root/_events.db +0 -0
  30. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/fixtures/data_root/proj-alpha.db +0 -0
  31. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/fixtures/data_root/proj-beta.db +0 -0
  32. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_cli.py +0 -0
  33. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_config.py +0 -0
  34. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_data_plane.py +0 -0
  35. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_deploy_artifacts.py +0 -0
  36. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_engine.py +0 -0
  37. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_events.py +0 -0
  38. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_inspect_facts.py +0 -0
  39. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_inspect_namespaces.py +0 -0
  40. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_mcp_parity.py +0 -0
  41. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_observe_mcp.py +0 -0
  42. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_readme_contract.py +0 -0
  43. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_review_views.py +0 -0
  44. {lean_memory_console-0.2.0 → lean_memory_console-0.2.2}/tests/test_views.py +0 -0
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.4
2
+ Name: lean-memory-console
3
+ Version: 0.2.2
4
+ Summary: Agent-first read-only verification console for lean-memory
5
+ Project-URL: Homepage, https://github.com/Wuesteon/lean-memory
6
+ Project-URL: Repository, https://github.com/Wuesteon/lean-memory
7
+ Project-URL: Changelog, https://github.com/Wuesteon/lean-memory/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/Wuesteon/lean-memory/issues
9
+ Author: lean-memory
10
+ License: Apache-2.0
11
+ Keywords: agent-memory,console,lean-memory,local-first,mcp,memory,verification
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: fastapi>=0.115
24
+ Requires-Dist: lean-memory
25
+ Requires-Dist: mcp<2,>=1.2
26
+ Requires-Dist: uvicorn>=0.30
27
+ Provides-Extra: dev
28
+ Requires-Dist: anyio>=4; extra == 'dev'
29
+ Requires-Dist: httpx>=0.27; extra == 'dev'
30
+ Requires-Dist: pytest>=8; extra == 'dev'
31
+ Requires-Dist: pyyaml; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # lean-memory-console
35
+
36
+ A read-only verification console for [lean-memory](https://github.com/Wuesteon/lean-memory#readme).
37
+
38
+ **Agents write and search; the human verifies.** Your agent (Claude Code via
39
+ the observing MCP, or any HTTP client in Docker mode) is the only writer of
40
+ memory content. You open the console **read-only over stored memory** — no
41
+ adding, editing, or deleting facts — to see the engine's invisible signals for
42
+ the first time: the ADD-only supersession spine, per-hit score decomposition,
43
+ and provenance episodes.
44
+
45
+ > The single write exception is the manual **test-search box**: it runs a real
46
+ > engine search and therefore bumps access stats (`touch()`). That is
47
+ > observability of live-search behavior, not a memory mutation.
48
+
49
+ ## Two modes
50
+
51
+ ### Local (default — zero Docker, nothing runs when the agent doesn't)
52
+
53
+ Two transient localhost processes over one shared data root:
54
+
55
+ ```bash
56
+ # 1. The observing MCP wrapper — your agent stores + searches through this.
57
+ uvx lean-memory-console mcp
58
+
59
+ # 2. The console — you open this to verify. Binds 127.0.0.1, prints a
60
+ # tokened URL, Ctrl-C to stop.
61
+ uvx lean-memory-console serve
62
+ ```
63
+
64
+ `serve` accepts `--root`, `--port`, and `--no-open` (skip the browser launch).
65
+ On load the SPA captures the token from `?token=…` — held in memory and sent as
66
+ the `X-Console-Token` header on every request — and strips it from the address
67
+ bar (`history.replaceState`). There is no cookie; a page refresh without the
68
+ token drops the session.
69
+
70
+ Via the Claude Code plugin (recommended), the MCP is wired automatically:
71
+
72
+ ```
73
+ /plugin marketplace add Wuesteon/lean-memory
74
+ /plugin install lean-memory
75
+ /memory:ui # launch + open the console
76
+ /memory:status # resolved root, namespaces, connect snippets
77
+ /memory:server-up # start the Docker data plane
78
+ /memory:server-down # stop it (the data volume persists)
79
+ ```
80
+
81
+ (From a local checkout you can register the marketplace with
82
+ `/plugin marketplace add ./` at the repo root instead of the GitHub slug.)
83
+
84
+ ### Docker (single-tenant, long-running, container owns /data)
85
+
86
+ ```bash
87
+ export LM_API_KEY=$(openssl rand -hex 24) # REQUIRED — the container refuses to boot without it
88
+ docker compose -f "$(lean-memory-console --print-compose-path)" up -d
89
+ ```
90
+
91
+ Then connect an agent over streamable-HTTP MCP and open the UI:
92
+
93
+ ```bash
94
+ claude mcp add --transport http lean-memory http://127.0.0.1:8377/mcp \
95
+ --header "Authorization: Bearer $LM_API_KEY"
96
+ # UI: http://127.0.0.1:8377/ (authenticate with the same LM_API_KEY)
97
+ ```
98
+
99
+ Docker mode binds `0.0.0.0` so the published port is reachable; there is **no**
100
+ local-mode Host guard and no per-launch session token. The controls are the
101
+ bearer gate (`LM_API_KEY`) plus the MCP transport-security Host allowlist. If
102
+ you reach the container over a LAN hostname/IP (no reverse proxy), list the
103
+ host(s) in `LM_MCP_ALLOWED_HOSTS` (comma-separated; `:*` matches any port) or
104
+ the `/mcp` mount 421s on its Host check — a commented example sits in the
105
+ packaged `docker-compose.yml`. The compose service builds the
106
+ `full` image target; container env is `LM_DATA_ROOT` / `LM_API_KEY` (required) /
107
+ `PORT` / `LM_CONSOLE_MODELS` / `LM_MCP_ALLOWED_HOSTS`.
108
+
109
+ A plain REST mirror exists for non-MCP agents:
110
+ `POST /v1/{namespace}/memories` and `POST /v1/{namespace}/search`.
111
+
112
+ ## The data-root rule (read this — it is the #1 trap)
113
+
114
+ The console serves **exactly one** data root and never auto-merges roots.
115
+ Resolution order, both `serve` and `mcp`:
116
+
117
+ ```
118
+ --root > $LM_DATA_ROOT > ~/.lean_memory
119
+ ```
120
+
121
+ **The ./lm_data trap.** The core `lean-memory` engine's *own* default root is
122
+ `./lm_data` (a directory in your current working directory), **not**
123
+ `~/.lean_memory`. So if you ran the engine directly (or the core stdio MCP
124
+ server pointed at the default) your memories may be under `./lm_data` while the
125
+ console defaults to `~/.lean_memory` — and you would inspect an empty root.
126
+
127
+ - `/memory:status` **prints the resolved root** and **warns** when `./lm_data`
128
+ exists in the working directory but is not the served root.
129
+ - Fix: point the console at the right root, e.g.
130
+ `uvx lean-memory-console serve --root ./lm_data`, or set
131
+ `export LM_DATA_ROOT=$(pwd)/lm_data`.
132
+
133
+ The console adds exactly one file to the data root: `_events.db` (search/add
134
+ traces). Everything else is the engine's own `<namespace>.db` files.
135
+
136
+ ## Live vs. replay: the `t_ref` rule
137
+
138
+ `t_ref` (epoch-ms) is the **world/event time** that becomes a fact's `valid_at`
139
+ and anchors the temporal supersession spine.
140
+
141
+ - **Live agents omit it.** The observing MCP fills `now`, so facts are ordered
142
+ by wall-clock ingest — correct for an agent capturing memories as they happen.
143
+ - **Replay / import supplies it.** When backfilling historical conversations,
144
+ pass the original event time as `t_ref` (epoch-ms) on every add. **Omitting
145
+ `t_ref` on historical data silently collapses the spine's ordering** — every
146
+ backfilled fact gets `now`, so supersession and point-in-time queries become
147
+ meaningless.
148
+
149
+ Rule of thumb: if you are importing anything that did not happen right now,
150
+ set `t_ref`.
151
+
152
+ ## One namespace per project
153
+
154
+ Namespaces replace tenants: the engine stores one SQLite file per namespace,
155
+ which is the isolation boundary. Use **one namespace per project/session**.
156
+
157
+ Cross-process writers on a *single* namespace (e.g. two Claude Code sessions
158
+ spawning the wrapper on the same data root) are supported but serialized by a
159
+ bounded retry-on-`SQLITE_BUSY` loop — not a lock manager. Pathological
160
+ contention degrades to retries and, eventually, a `SQLITE_BUSY` surfaced in the
161
+ event's `payload.error`. Keeping namespaces per-project avoids the contention
162
+ entirely.
163
+
164
+ Namespaces are created implicitly on first accepted `memory_add`. There is no
165
+ create-namespace step, and no delete-namespace surface (ADD-only discipline —
166
+ to remove a namespace, delete its `.db` file while nothing is running).
167
+ Namespaces whose sanitized name starts with `_` are **rejected** (the
168
+ `_events.db` sidecar is reserved); an empty name is not rejected — it sanitizes
169
+ to `default`.
170
+
171
+ ## Image size (Docker `full`)
172
+
173
+ The default Docker image is the `full` target: it installs `lean-memory[models]`
174
+ (CPU **torch** + sentence-transformers + a cross-encoder reranker), so the image
175
+ is large (~1.46 GB) and the first run downloads model weights into the mounted
176
+ HF cache volume. The CPU torch build is pinned from
177
+ `download.pytorch.org/whl/cpu` so the resolve never pulls the multi-GB CUDA
178
+ wheels. This is deliberate — stub vectors would recreate the FakeEmbedder
179
+ first-impression failure the quality gate exists to fix. A `slim` target
180
+ (~365 MB, stub embedder, no models) exists for API/UI development
181
+ (`docker build --target slim …`) but is never the documented first-run path.
182
+
183
+ ## Offline by default
184
+
185
+ The console runs fully on deterministic stub backends with no network and no
186
+ model downloads (`LM_CONSOLE_MODELS=stub`, or `auto` when `[models]` is not
187
+ importable). When scores are stub-generated the UI shows a banner saying so.
188
+
189
+ ## License
190
+
191
+ Apache-2.0
192
+
193
+ ## Manual E2E verification (pre-merge)
194
+
195
+ Run this before merge. It is a **manual** gate, not automated — steps that need
196
+ a live interactive Claude Code session are marked `[manual]` and are driven by a
197
+ human, not by tooling. Capture the observed outcome next to each step.
198
+
199
+ **Local mode (plugin + observing MCP):**
200
+
201
+ - [ ] `[manual]` `/plugin marketplace add ./` (from the repo root marketplace),
202
+ then `/plugin install lean-memory`.
203
+ Expected: plugin installs; the `lean-memory` MCP server appears in the
204
+ session's MCP list, and `/memory:ui|status|server-up|server-down` are
205
+ offered as commands.
206
+ - [ ] `[manual]` In a real Claude Code session, ask the agent to store a couple
207
+ of facts and then search them (through the observing MCP
208
+ `memory_add`/`memory_search`).
209
+ Expected: `memory_add` returns `{fact_ids, superseded_count}`;
210
+ `memory_search` returns hits whose `fact_text` matches what was stored;
211
+ rows land in `<root>/_events.db`.
212
+ - [ ] `[manual]` Run `/memory:ui`.
213
+ Expected: browser opens `http://127.0.0.1:8377/?token=…`; the address bar
214
+ loses `?token` after boot; no login screen (local mode).
215
+ - [ ] `[manual]` Verify all four pages render the resulting state:
216
+ - **Overview** — the namespace card shows fact counts, top predicates,
217
+ the 7-day adds/searches sparkline, supersession rate, and facts-per-add.
218
+ - **Memories** — the fact table lists the stored facts; opening a fact
219
+ drawer shows metadata, the supersession timeline (chain oldest→newest),
220
+ and the provenance episode.
221
+ - **Episodes** — the transcript shows the stored turns, each expanding to
222
+ the facts extracted from it.
223
+ - **Activity & Traces** — the polled feed shows the `add`/`search` events;
224
+ a search row expands to the per-hit score decomposition
225
+ (`0.6·relevance + 0.2·recency + 0.2·importance`, dense/sparse ranks,
226
+ RRF); the test-query box runs a live search and its row is labeled
227
+ `origin: ui`.
228
+
229
+ **Docker mode (HTTP data plane):**
230
+
231
+ - [ ] `[manual]` `export LM_API_KEY=$(openssl rand -hex 24)` then
232
+ `docker compose -f "$(lean-memory-console --print-compose-path)" up -d`
233
+ (or `/memory:server-up`).
234
+ Expected: container starts; boot validation passes (data root writable,
235
+ `LM_API_KEY` set, sqlite-vec loadable).
236
+ - [ ] `[manual]` `claude mcp add --transport http lean-memory
237
+ http://127.0.0.1:8377/mcp --header "Authorization: Bearer $LM_API_KEY"`.
238
+ Expected: the MCP connection registers; a store+search from the agent
239
+ succeeds and records events in the container's `/data/_events.db`.
240
+ - [ ] `[manual]` Open `http://127.0.0.1:8377/`.
241
+ Expected: the login screen prompts for the key; entering `LM_API_KEY`
242
+ authenticates; all four pages render the same as local mode, and the
243
+ Overview shows the Docker connect snippet.
244
+ - [ ] `[manual]` `/memory:server-down`.
245
+ Expected: container stops; the `lm_data` volume persists (re-`up` shows
246
+ the same memories).
@@ -1,6 +1,6 @@
1
1
  # lean-memory-console
2
2
 
3
- A read-only verification console for [lean-memory](../README.md).
3
+ A read-only verification console for [lean-memory](https://github.com/Wuesteon/lean-memory#readme).
4
4
 
5
5
  **Agents write and search; the human verifies.** Your agent (Claude Code via
6
6
  the observing MCP, or any HTTP client in Docker mode) is the only writer of
@@ -37,7 +37,7 @@ token drops the session.
37
37
  Via the Claude Code plugin (recommended), the MCP is wired automatically:
38
38
 
39
39
  ```
40
- /plugin marketplace add Wuesteon/lean-memory-console
40
+ /plugin marketplace add Wuesteon/lean-memory
41
41
  /plugin install lean-memory
42
42
  /memory:ui # launch + open the console
43
43
  /memory:status # resolved root, namespaces, connect snippets
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "lean-memory-console"
7
+ version = "0.2.2"
8
+ description = "Agent-first read-only verification console for lean-memory"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "Apache-2.0" }
12
+ authors = [{ name = "lean-memory" }]
13
+ keywords = [
14
+ "agent-memory",
15
+ "memory",
16
+ "mcp",
17
+ "lean-memory",
18
+ "console",
19
+ "verification",
20
+ "local-first",
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 4 - Beta",
24
+ "License :: OSI Approved :: Apache Software License",
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
31
+ "Intended Audience :: Developers",
32
+ "Operating System :: OS Independent",
33
+ ]
34
+ dependencies = [
35
+ "lean-memory",
36
+ "fastapi>=0.115",
37
+ "uvicorn>=0.30",
38
+ # <2: mcp 2.0.0 removed mcp.server.fastmcp (see core [mcp] extra note).
39
+ "mcp>=1.2,<2",
40
+ ]
41
+
42
+ [project.optional-dependencies]
43
+ dev = ["pytest>=8", "anyio>=4", "httpx>=0.27", "pyyaml"]
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/Wuesteon/lean-memory"
47
+ Repository = "https://github.com/Wuesteon/lean-memory"
48
+ Changelog = "https://github.com/Wuesteon/lean-memory/blob/main/CHANGELOG.md"
49
+ Issues = "https://github.com/Wuesteon/lean-memory/issues"
50
+
51
+ [project.scripts]
52
+ lean-memory-console = "lean_memory_console.cli:main"
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/lean_memory_console"]
56
+
57
+ # Packaging copy lives IN-TREE (console/deploy/) so the sdist->wheel path can
58
+ # resolve it — a parent-relative ../deploy source escapes the sdist root and
59
+ # fails any pip/uvx install from sdist (v0.2.0 readiness-board finding). The
60
+ # operational file stays at repo-root deploy/; a test pins the two identical.
61
+ [tool.hatch.build.targets.wheel.force-include]
62
+ "deploy/docker-compose.yml" = "lean_memory_console/deploy/docker-compose.yml"
63
+
64
+ [tool.pytest.ini_options]
65
+ testpaths = ["tests"]
@@ -1,3 +1,3 @@
1
1
  """lean-memory-console — agent-first read-only verification console."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.2"
@@ -18,7 +18,7 @@ MARKETPLACE = REPO_ROOT / ".claude-plugin" / "marketplace.json"
18
18
  def test_plugin_json_identity() -> None:
19
19
  data = json.loads((PLUGIN / ".claude-plugin" / "plugin.json").read_text())
20
20
  assert data["name"] == "lean-memory"
21
- assert data["version"] == "0.2.0"
21
+ assert data["version"] == "0.2.1"
22
22
  assert data["description"] # non-empty
23
23
 
24
24
 
@@ -1,14 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: lean-memory-console
3
- Version: 0.2.0
4
- Summary: Agent-first read-only verification console for lean-memory
5
- Requires-Python: >=3.10
6
- Requires-Dist: fastapi>=0.115
7
- Requires-Dist: lean-memory
8
- Requires-Dist: mcp>=1.0
9
- Requires-Dist: uvicorn>=0.30
10
- Provides-Extra: dev
11
- Requires-Dist: anyio>=4; extra == 'dev'
12
- Requires-Dist: httpx>=0.27; extra == 'dev'
13
- Requires-Dist: pytest>=8; extra == 'dev'
14
- Requires-Dist: pyyaml; extra == 'dev'
@@ -1,34 +0,0 @@
1
- [build-system]
2
- requires = ["hatchling"]
3
- build-backend = "hatchling.build"
4
-
5
- [project]
6
- name = "lean-memory-console"
7
- version = "0.2.0"
8
- description = "Agent-first read-only verification console for lean-memory"
9
- requires-python = ">=3.10"
10
- dependencies = [
11
- "lean-memory",
12
- "fastapi>=0.115",
13
- "uvicorn>=0.30",
14
- "mcp>=1.0",
15
- ]
16
-
17
- [project.optional-dependencies]
18
- dev = ["pytest>=8", "anyio>=4", "httpx>=0.27", "pyyaml"]
19
-
20
- [project.scripts]
21
- lean-memory-console = "lean_memory_console.cli:main"
22
-
23
- [tool.hatch.build.targets.wheel]
24
- packages = ["src/lean_memory_console"]
25
-
26
- # Packaging copy lives IN-TREE (console/deploy/) so the sdist->wheel path can
27
- # resolve it — a parent-relative ../deploy source escapes the sdist root and
28
- # fails any pip/uvx install from sdist (v0.2.0 readiness-board finding). The
29
- # operational file stays at repo-root deploy/; a test pins the two identical.
30
- [tool.hatch.build.targets.wheel.force-include]
31
- "deploy/docker-compose.yml" = "lean_memory_console/deploy/docker-compose.yml"
32
-
33
- [tool.pytest.ini_options]
34
- testpaths = ["tests"]