# M1 task 01: workspace and gate **Branch:** `m1` (create it: `git switch -c m1`) **Commit subject:** `Add Cargo workspace, crate skeletons and the gate` ## Goal Create the Cargo workspace with seven empty crates, and the gate that every later task must pass. At the end `make gate` prints `gate: ok`. ## Context From the design brief: "Rust stable, Cargo workspace. Crates: `proto` (shared types), `loopd`, `brokerd`, `gatewayd`, `inferproxy`, `toolkit` (tool container entrypoints), `bxctl` (owner CLI). No source file over 500 lines. No crate depends on another role's crate, only on `proto`. Dependencies are few and justified in `docs/dependencies.md`. No outbound call not listed in `docs/egress.md`." Every crate except `proto` is a library with a thin `main.rs`, so that doctests can run later. ## Files - Copy (never edit afterwards): `Makefile`, `deny.toml`, `scripts/test-gate-scripts.sh` - Create: `Cargo.toml`, `Cargo.lock` (generated), `crates//Cargo.toml` for all seven crates, `crates//src/lib.rs` for all seven, `crates//src/main.rs` for the six that are not `proto` - Create: `scripts/check-lines.sh`, `scripts/check-crate-deps.sh`, `scripts/check-dep-docs.sh` - Create: `docs/dependencies.md`, `docs/egress.md` - Modify: `docs/implementer-log.md` ## Steps - [ ] **1. Branch and copy the given files.** ```sh git switch -c m1 mkdir -p scripts cp docs/plans/M1/files/Makefile docs/plans/M1/files/deny.toml . cp docs/plans/M1/files/scripts/test-gate-scripts.sh scripts/ ``` Read `Makefile` and `scripts/test-gate-scripts.sh`. The second one is the test for the three scripts you write in step 4: it shows exactly which inputs must pass and which must fail. - [ ] **2. Write the root `Cargo.toml`** with exactly this content: ```toml [workspace] resolver = "3" members = [ "crates/proto", "crates/loopd", "crates/brokerd", "crates/gatewayd", "crates/inferproxy", "crates/toolkit", "crates/bxctl", ] [workspace.package] edition = "2024" rust-version = "1.95" publish = false [workspace.lints.rust] unsafe_code = "forbid" [workspace.dependencies] proto = { path = "crates/proto" } ``` - [ ] **3. Write the seven crates.** `crates/loopd/Cargo.toml` is: ```toml [package] name = "loopd" version = "0.1.0" edition.workspace = true rust-version.workspace = true publish.workspace = true [lints] workspace = true [dependencies] proto.workspace = true ``` The other five role crates are the same with their own `name`. `crates/proto/Cargo.toml` is the same with `name = "proto"` and an empty `[dependencies]` section. Each `src/lib.rs` is one doc comment line and nothing else: | Crate | `src/lib.rs` | |---|---| | `proto` | `//! Shared data types and the frame codec for Boxmaker. No policy and no I/O beyond frames.` | | `loopd` | `//! The agent loop: sessions, prompt assembly and memory. It holds no authority.` | | `brokerd` | `//! The broker: the only role that holds authority.` | | `gatewayd` | `//! The Mattermost channel. Outbound connections only.` | | `inferproxy` | ``//! Forwards bytes between `infer.sock` and the llama-server router. It logs nothing.`` | | `toolkit` | `//! Entry points that run inside tool containers.` | | `bxctl` | `//! The owner's command-line tool.` | Each `src/main.rs` (not for `proto`) follows this pattern, with its own name and milestone (`loopd` M2, `brokerd` M3, `gatewayd` M4, `inferproxy` M2, `toolkit` M3, `bxctl` M2): ```rust fn main() { eprintln!("loopd: not implemented until M2"); std::process::exit(2); } ``` Run `cargo build`. Expected: it finishes without warnings and creates `Cargo.lock`. - [ ] **4. Write the three gate scripts.** POSIX `sh` only: no bash features, no Python, no `jq`. Each takes an optional `ROOT` argument that defaults to `.`, prints one line per problem to stderr starting with the script's name, and exits 1 if there was any problem, 0 otherwise. - `scripts/check-lines.sh [ROOT]`: fails if any `*.rs` file under `ROOT/crates` has more than 500 lines. Files under any `target/` directory are ignored. Test files count. - `scripts/check-crate-deps.sh [ROOT]`: the workspace crates are the directories in `ROOT/crates`. Fails if `proto` depends on any workspace crate, or if any other crate depends on a workspace crate other than `proto`. Look at every manifest section whose name contains `dependencies` (so `[dev-dependencies]` counts). A dependency is any key in such a section, however it is written: `x.workspace = true`, `x = { path = "…" }`, `x = "1"`. - `scripts/check-dep-docs.sh [ROOT]`: fails if a key in `[workspace.dependencies]` of `ROOT/Cargo.toml` that is not a workspace crate has no table row starting ``| `name` |`` in `ROOT/docs/dependencies.md`. It also fails if any dependency line in any `ROOT/crates/*/Cargo.toml` lacks `workspace = true`. Run `sh scripts/test-gate-scripts.sh`. Expected: `test-gate-scripts: ok`. If it reports failures, fix your scripts, never the test. - [ ] **5. Write the two documents.** `docs/dependencies.md`: ```markdown # Dependencies Every external crate has a row here. `scripts/check-dep-docs.sh` enforces it. | Crate | Version | Used by | Why | |---|---|---|---| ``` `docs/egress.md`: ```markdown # Egress Every outbound network call the project makes, at run time or in development. Nothing else is allowed. | When | From | To | What | |---|---|---|---| | Development | `cargo` | crates.io | Downloading the crates listed in `docs/dependencies.md` | | Development | `make audit` | github.com/rustsec/advisory-db | The RustSec advisory database, fetched by `cargo deny check advisories` | ``` - [ ] **6. Run the gate.** `make gate`. Expected last line: `gate: ok`. At this stage `cargo deny` prints `license-not-encountered` warnings, because there are no dependencies yet. They are expected and they go away in task 02. Do not edit `deny.toml`. - [ ] **7. Log and commit.** Add your row to `docs/implementer-log.md`, then: ```sh git add Cargo.toml Cargo.lock Makefile deny.toml crates scripts docs/dependencies.md docs/egress.md docs/implementer-log.md git status --short git commit ``` `git status --short` must show nothing untracked except ignored files. Use the commit subject at the top of this file and the trailer from `AGENTS.md`. ## Done when - `make gate` prints `gate: ok`. - `cmp Makefile docs/plans/M1/files/Makefile` and the same for `deny.toml` and `scripts/test-gate-scripts.sh` print nothing. - One new commit on `m1`. ## Stop and report if - `cargo deny` is not installed (`cargo deny --version` fails). - `make gate` fails in a step that is not one of your scripts and you cannot see why.