3.5 KiB
3.5 KiB
M0.1 — Cargo workspace + crate skeletons
| Field | Value |
|---|---|
| Phase | M0 — Read-only spine |
| Size | S — under 1 day |
| Status | ⬜ Not started |
| 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
Cargo.tomlat the repo root with[workspace] members = [...]and a[workspace.dependencies]block holding every shared crate version.- Six member crates, each declaring deps as
foo.workspace = true. mem-cliis the only[[bin]]; the rest are libraries.- Add
rust-toolchain.tomlpinning a version, so CI and laptop agree. .gitignore:target/,vault/— but notlog/and notmemory-tasks/. The log is authoritative and the board carries acceptance criteria; both are tracked.- Wire a CI job running
cargo build --workspaceandcargo clippy --workspace -- -D warnings.
Acceptance
cargo build --workspacesucceeds from a clean checkout.cargo clippy --workspace -- -D warningsis clean.mem-corehas 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:
a1_all_members_build— shell out tocargo build --workspace, assert exit 0.a2_mem_core_has_no_sibling_deps— parsecrates/mem-core/Cargo.toml, assert no dependency name starts withmem-.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.a4_log_and_tasks_are_tracked— assert.gitignorematches neitherlog/normemory-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 buildin 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 ofserdein 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 — Repository layout