99 lines
3.5 KiB
Markdown
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
|