Files
poimen-memory/tasks/M0.1-cargo-workspace.md
T

99 lines
3.5 KiB
Markdown

# M0.1 — Cargo workspace + crate skeletons
| Field | Value |
|---|---|
| Phase | M0 — Read-only spine |
| Size | S — under 1 day |
| Status | ✅ Done |
| Flags | — |
| Spec | inlined below |
| Blocks | — |
## Goal
The six-crate workspace, building clean, with the dependency direction fixed
before any code exists to violate it.
## Facts (inlined — no spec read needed)
```
crates/
mem-core/ domain types; Level; gate-response parser; the gated loop
mem-chunk/ RecordSource trait; ChunkPolicy; FlushTrigger
mem-llm/ gateway client — chat, embeddings, rerank
mem-ingest/ source adapters: pi sessions, claude transcripts
mem-store/ JSONL log; pgvector repo; Obsidian projector
mem-cli/ binary `mem`
```
Dependency direction, enforced from the start:
```
mem-cli -> mem-ingest, mem-store, mem-llm, mem-chunk, mem-core
mem-store -> mem-core
mem-ingest -> mem-chunk, mem-core
mem-chunk -> mem-core
mem-llm -> mem-core
mem-core -> (nothing in this workspace)
```
`mem-core` depends on no sibling. It holds the types every other crate speaks,
so a dependency out of it is a cycle waiting to happen.
Workspace deps to pin now, so versions do not drift per crate: `tokio`,
`futures`, `serde`, `serde_json`, `serde_yaml`, `anyhow`, `thiserror`,
`sha2`, `clap`, `reqwest`, `tracing`.
## Steps
1. `Cargo.toml` at the repo root with `[workspace] members = [...]` and a
`[workspace.dependencies]` block holding every shared crate version.
2. Six member crates, each declaring deps as `foo.workspace = true`.
3. `mem-cli` is the only `[[bin]]`; the rest are libraries.
4. Add `rust-toolchain.toml` pinning a version, so CI and laptop agree.
5. `.gitignore`: `target/`, `vault/` — but **not** `log/` and **not**
`memory-tasks/`. The log is authoritative and the board carries acceptance
criteria; both are tracked.
6. Wire a CI job running `cargo build --workspace` and `cargo clippy --workspace
-- -D warnings`.
## Acceptance
- `cargo build --workspace` succeeds from a clean checkout.
- `cargo clippy --workspace -- -D warnings` is clean.
- `mem-core` has zero intra-workspace dependencies.
## Verify
**Harness:** cargo itself, plus a dependency assertion that does not trust the
manifests to be read by a human.
**Integration test** — `tests/it_workspace.rs` in the root:
1. `a1_all_members_build` — shell out to `cargo build --workspace`, assert exit 0.
2. `a2_mem_core_has_no_sibling_deps` — parse `crates/mem-core/Cargo.toml`, assert
no dependency name starts with `mem-`.
3. `a3_dependency_direction` — parse every member manifest, build the edge set,
assert it is a subset of the table above and that the graph is acyclic.
4. `a4_log_and_tasks_are_tracked` — assert `.gitignore` matches neither
`log/` nor `memory-tasks/`.
**Command:** `cargo test --workspace workspace`
**False pass:**
- Asserting the graph is acyclic **only**. Acyclic permits `mem-core ->
mem-store`, which is backwards and still acyclic. Assertion 3 must check the
edge set against the table, not just for cycles.
- A CI job that runs `cargo build` in the root without `--workspace`. It builds
the virtual manifest and can miss a member that does not compile.
## Traps
- Per-crate dependency versions instead of `workspace.dependencies`. They drift,
and two versions of `serde` in one tree is a confusing type error much later.
- Gitignoring `log/`. It is the authoritative record; ignoring it makes the whole
authority model a fiction.
---
Background: [DESIGN.md](../DESIGN.md) — Repository layout