Eight closed tasks for epochs and compaction, then ten for the scheduler, ToolSummary, and tiers. Given tests first. Gate 1456 → 1507 → 1572. Co-Authored-By: Grok 4.6 <noreply@x.ai>
210 lines
7.9 KiB
Markdown
210 lines
7.9 KiB
Markdown
# M5d-1 task 01: `[compact]` on `loopd.toml`
|
|
|
|
**Branch:** `m5d1`. Check it: `git branch --show-current` prints `m5d1` and `git status --short`
|
|
is empty; otherwise stop. Never switch branch.
|
|
**Commit subject:** `loopd: [compact] threshold, summary_chars and summarise`
|
|
**Log row:** the Task cell is `M5d1/01-loopd-compact-config`.
|
|
|
|
## Goal
|
|
|
|
M5d-1 compact after a turn whose last `Usage` is at or above a fraction of `expect.n_ctx` (spec
|
|
3.3, 5). This task adds only the `[compact]` table so later tasks can read it:
|
|
|
|
- `threshold` (float, default `0.85`)
|
|
- `summary_chars` (default `4000`)
|
|
- `summarise` (list of tool names, default `["http_fetch"]`)
|
|
|
|
Nothing in this task uses the values. `summarise` is stored so a spec-complete `loopd.toml`
|
|
loads; M5d-2 reads it. Unknown keys in `[compact]` are errors, as in every table we define.
|
|
|
|
`Config::compact_prompt` is `compact.md` beside `[baseline] system` (the same directory join
|
|
`load` already does for `system.md`). The starter file is copied in task 05.
|
|
|
|
## Every place that changes
|
|
|
|
This is the complete list.
|
|
|
|
| Place | What happens there |
|
|
|---|---|
|
|
| `crates/loopd/src/config.rs` | `Compact`; `Config.compact`; `Config::compact_prompt` (edits C1 to C3) |
|
|
| `crates/loopd/tests/config_compact.rs` | new, given |
|
|
| everything else | **no change**: not `session.rs`, not the existing `config.rs` tests or fixtures |
|
|
|
|
## Files
|
|
|
|
- Copy, from `docs/plans/M5d1/files/` (the same path under it): the new test
|
|
`crates/loopd/tests/config_compact.rs`.
|
|
- Modify: `crates/loopd/src/config.rs`, `docs/implementer-log.md`.
|
|
- Do not touch: any other file.
|
|
|
|
## Facts you need
|
|
|
|
- **`Config` already has `#[serde(default)]` on optional tables** (`sampling`, `limits`, `paths`,
|
|
`channel`, `loop`, `baseline`, `broker`, `memory`). `[compact]` is the same: missing means
|
|
`Compact::default()`.
|
|
- **`threshold` is `f64`.** `Sampling.temperature` is already `f64` on `Config`, so `PartialEq`
|
|
on `Config` still compiles. Do not add a range check: the spec does not name one.
|
|
- **`summarise` default.** `vec!["http_fetch".to_string()]`. An explicit `summarise = []` is
|
|
allowed and is empty. Unknown names are not checked here (M5d-2).
|
|
- **`compact_prompt`.** `self.baseline.system.with_file_name("compact.md")`. After `load`,
|
|
`baseline.system` is already joined to the config file's directory, so the prompt follows it
|
|
into a subdirectory when `system` does (`prompts/agent.md` → `prompts/compact.md`).
|
|
- The items the edits use. This table is complete; `serde` is already a dependency of `loopd`.
|
|
|
|
| Item | What it does |
|
|
|---|---|
|
|
| `#[serde(deny_unknown_fields, default)]` | on `Compact`: missing table uses `Default`; unknown keys error |
|
|
| `Path::with_file_name` | `compact.md` beside `system.md` |
|
|
| `Vec<String>` | `summarise` |
|
|
|
|
## The edits, exactly
|
|
|
|
Nothing else in this file changes. Each quoted "before" block occurs exactly once in its file
|
|
when its turn comes (make them in order). Keep the fields in the order shown.
|
|
|
|
### `crates/loopd/src/config.rs`
|
|
|
|
**C1.** After the `Memory` struct (the lines)
|
|
|
|
```rust
|
|
pub struct Memory {
|
|
pub socket: std::path::PathBuf,
|
|
}
|
|
```
|
|
|
|
become
|
|
|
|
```rust
|
|
pub struct Memory {
|
|
pub socket: std::path::PathBuf,
|
|
}
|
|
|
|
/// `[compact]`: when a session starts a new epoch, and how long a summary may be (M5d spec,
|
|
/// section 5). `summarise` is stored here and unused until M5d-2.
|
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
|
#[serde(deny_unknown_fields, default)]
|
|
pub struct Compact {
|
|
pub threshold: f64,
|
|
pub summary_chars: usize,
|
|
pub summarise: Vec<String>,
|
|
}
|
|
|
|
impl Default for Compact {
|
|
fn default() -> Self {
|
|
Self {
|
|
threshold: 0.85,
|
|
summary_chars: 4_000,
|
|
summarise: vec!["http_fetch".to_string()],
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**C2.** The lines
|
|
|
|
```rust
|
|
#[serde(default)]
|
|
pub memory: Memory,
|
|
}
|
|
```
|
|
|
|
become
|
|
|
|
```rust
|
|
#[serde(default)]
|
|
pub memory: Memory,
|
|
#[serde(default)]
|
|
pub compact: Compact,
|
|
}
|
|
```
|
|
|
|
**C3.** After `channel_socket` (the lines)
|
|
|
|
```rust
|
|
pub fn channel_socket(&self) -> std::path::PathBuf {
|
|
if self.channel.socket.as_os_str().is_empty() {
|
|
self.paths.home.join("run/loop/loop.sock")
|
|
} else {
|
|
self.channel.socket.clone()
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
become
|
|
|
|
```rust
|
|
pub fn channel_socket(&self) -> std::path::PathBuf {
|
|
if self.channel.socket.as_os_str().is_empty() {
|
|
self.paths.home.join("run/loop/loop.sock")
|
|
} else {
|
|
self.channel.socket.clone()
|
|
}
|
|
}
|
|
|
|
/// `compact.md` beside the system prompt: the summary call's last user message.
|
|
pub fn compact_prompt(&self) -> std::path::PathBuf {
|
|
self.baseline.system.with_file_name("compact.md")
|
|
}
|
|
}
|
|
```
|
|
|
|
## Steps
|
|
|
|
- [ ] **1. Copy the given test.** From the repository root, one command:
|
|
|
|
```sh
|
|
cp docs/plans/M5d1/files/crates/loopd/tests/config_compact.rs crates/loopd/tests/
|
|
```
|
|
|
|
Then `git status --short` lists one new file, `crates/loopd/tests/config_compact.rs`.
|
|
- [ ] **2. See it fail.** `cargo build --tests --keep-going -p loopd`, with a shell timeout of
|
|
600000 ms: one test target, `config_compact`, does not compile, with `E0609` (`no field
|
|
\`compact\` on type \`Config\``) and `E0599` (`no method named \`compact_prompt\`` /
|
|
`no variant or associated item named \`default\` for \`Compact\``). Every other target
|
|
compiles.
|
|
- [ ] **3. The edits.** Make edits C1 to C3, in order. `cargo check -p loopd` prints no error and
|
|
no warning.
|
|
- [ ] **4. The tests.** `cargo test -p loopd --test config_compact --test config`: every test
|
|
passes, 8 in `config_compact` and the others as before.
|
|
- [ ] **5. Check.** `git diff --stat` lists exactly `crates/loopd/src/config.rs`.
|
|
- [ ] **6. Run the gate.** `cargo fmt --all`, then `make gate`, with a shell timeout of 600000 ms.
|
|
Expected last line: `gate: ok`. The test count is **1464** after this task, 1456 before it
|
|
(1455 passed in `cargo test --workspace`, plus 1), and the 8 new ones are the tests of
|
|
`config_compact.rs`. To count, add up the `N passed` of every `test result:` line the gate's
|
|
`cargo test --workspace` printed, and add 1. Never run the gate again only to count.
|
|
- [ ] **7. Log and commit.** Add your row to `docs/implementer-log.md`; its Task cell is
|
|
`M5d1/01-loopd-compact-config`. Stage with
|
|
`git add crates/loopd docs/implementer-log.md Cargo.lock`, then commit as `AGENTS.md` says.
|
|
`Cargo.lock` does not change in this task; the `git add` is harmless.
|
|
|
|
## Done when
|
|
|
|
- `make gate` prints `gate: ok` with 1464 tests.
|
|
- `git diff HEAD~1 --stat` lists only `crates/loopd/src/config.rs`,
|
|
`crates/loopd/tests/config_compact.rs` and `docs/implementer-log.md`.
|
|
|
|
## Stop and report if
|
|
|
|
- The branch check at the top fails.
|
|
- A "before" block is not in its file exactly as shown when its turn comes, or is there more
|
|
than once.
|
|
- Step 2 shows a different result: another target failing, or other errors.
|
|
- `cargo check` in step 3 prints an error or a warning. Quote it, and stop.
|
|
- A test fails in step 4. Do not change the test: stop, and give the failing tests' names and
|
|
their messages.
|
|
- The fix seems to need a change anywhere else: a fixture, `config.rs` tests, a range check on
|
|
`threshold`. It does not; stop and say why you think so.
|
|
- A test outside `config_compact.rs` fails in the gate: check once whether it fails without your
|
|
change (`git stash -u`, run it, `git stash pop`), then stop and report both results.
|
|
- The gate passes with a count other than 1464.
|
|
- A comment in an edit does not fit the code under it. Quote it and stop.
|
|
|
|
## What the given tests pin
|
|
|
|
Each of these changes to the finished code makes at least one given test fail: the default
|
|
threshold moved; `summary_chars` default moved; `summarise` default emptied or given another
|
|
name; unknown keys accepted; a misspelt `summary_char` accepted; a partial table wiping the
|
|
other defaults; `compact_prompt` using `home` or the config file's name instead of `system.md`'s
|
|
directory; `Compact::default` disagreeing with a missing table.
|