# 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