Add M2b plan: ten tasks, tests, recordings and the first system prompt
The tasks build the agent loop on M2a's client: channel messages and the usage record in proto, four config tables, the tool port and registry with find_tool and call_tool, the baseline and replay, the session store, the turn loop with its limits and the append-only property test, the channel server, loopd serve, bxctl chat, and the device checks including a four-turn conversation with a restart. Checked against a private reference implementation: the gate passes after every task in order, the new suites pass under CPU load, and the reference passes make verify-device on straylight with no cache loss. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# M2b task 08: `loopd serve`
|
||||
|
||||
**Branch:** `m2b` (run `git switch m2b`; `git status --short` must be empty, otherwise stop)
|
||||
**Commit subject:** `Add the loopd serve command`
|
||||
|
||||
## Goal
|
||||
|
||||
The command that runs the harness: self-test, then the channel server. It refuses to start if the
|
||||
self-test fails.
|
||||
|
||||
## Files
|
||||
|
||||
- Copy: `crates/loopd/tests/serve.rs`
|
||||
- Modify: `crates/loopd/src/main.rs`, `docs/implementer-log.md`
|
||||
|
||||
## What `loopd serve --config <path>` does, in order
|
||||
|
||||
1. Load the config; on failure print `loopd: <error>` and exit 1.
|
||||
2. Work out the socket path with `cfg.channel_socket()`. If a socket file is already there,
|
||||
remove it **now**, before the self-test, so that a client sees "not running" rather than
|
||||
"connection refused" while the self-test runs.
|
||||
3. Run the self-test exactly as `loopd selftest` does, printing the same lines. On failure exit 1
|
||||
without binding anything.
|
||||
4. Create the socket's parent directory, bind, set the socket file's mode to 0600, print
|
||||
`loopd: serving on <path>`, and call `channel::serve` with a `Context` made of the config, the
|
||||
client, `Box::new(FakeTools::new())` and `Registry::m2b()`.
|
||||
|
||||
`loopd selftest --config <path>` keeps working as before. Anything else prints the usage for both
|
||||
commands and exits 2.
|
||||
|
||||
## Steps
|
||||
|
||||
- [ ] **1. Copy.** `git switch m2b`, then
|
||||
`cp docs/plans/M2b/files/crates/loopd/tests/serve.rs crates/loopd/tests/`
|
||||
- [ ] **2. See the test fail.** `cargo test -p loopd --test serve`. Expected: all 3 fail, because
|
||||
`serve` is not a command yet.
|
||||
- [ ] **3. Rewrite `main.rs`.** Keep the `selftest` command. Run `cargo fmt --all`.
|
||||
- [ ] **4. See the tests pass.** `cargo test -p loopd --test serve`. Expected: `3 passed`.
|
||||
- [ ] **5. Run the gate.** `make gate`. Expected last line: `gate: ok`.
|
||||
- [ ] **6. Log and commit.** `git add crates/loopd docs/implementer-log.md && git commit`
|
||||
|
||||
## Done when
|
||||
|
||||
- `cargo test -p loopd --test serve` reports 3 passed; `make gate` prints `gate: ok`.
|
||||
|
||||
## Stop and report if
|
||||
|
||||
- The socket cannot be given mode 0600 with `std::fs::set_permissions`.
|
||||
Reference in New Issue
Block a user