docs: M5d-2 task 06: cp first, tick is glue
The second 06 session listed tests/, read eight loopd modules and support/mod.rs, grepped bxcore, then hit Context size exceeded with no commit. The cp is now the first action; tick is glue over two todo!() bodies; run-plan tells the session to run step 1 before reading crate source. Co-Authored-By: Grok 4.6 <noreply@x.ai>
This commit is contained in:
@@ -5,6 +5,14 @@ is empty; otherwise stop. Never switch branch.
|
||||
**Commit subject:** `loopd: heartbeat tick on the background slot`
|
||||
**Log row:** the Task cell is `M5d2/06-loopd-scheduler-heartbeat`.
|
||||
|
||||
**First action.** Run this before any Read of crate source. Do not `ls` `crates/loopd/tests/`.
|
||||
Do not Read `tests/support/`, `session.rs`, `turn.rs`, `compact.rs`, `config.rs`, `jobs.rs`,
|
||||
`baseline.rs`, `bxcore`, or `docs/implementer-log.md`. The signatures below are complete.
|
||||
|
||||
```sh
|
||||
cp docs/plans/M5d2/files/crates/loopd/tests/scheduler_heartbeat.rs crates/loopd/tests/
|
||||
```
|
||||
|
||||
## Goal
|
||||
|
||||
A `Scheduler` whose `tick(&Context, now)` runs the standing `heartbeat` session when
|
||||
@@ -38,11 +46,8 @@ Tests call `tick(ctx, now)` with injected time. No sleeps (T27).
|
||||
`crates/loopd/src/main.rs`, `docs/implementer-log.md`.
|
||||
- Do not touch: any other file.
|
||||
|
||||
**Read only what the step names.** Step 1 is the `cp`. Do not open `docs/implementer-log.md`,
|
||||
`docs/runbook.md`, or `crates/loopd/src/{turn,session,compact,baseline,config}.rs` to start.
|
||||
The facts table is complete. At step 7, read only the first 12 lines of
|
||||
`docs/implementer-log.md` (title through the header row) and insert the new row immediately
|
||||
under the header. The rest of that file fills the session (~360 kB).
|
||||
At step 7, read only the first 12 lines of `docs/implementer-log.md`. The rest of that file
|
||||
fills the session (~360 kB).
|
||||
|
||||
## Facts you need
|
||||
|
||||
@@ -93,15 +98,25 @@ under the header. The rest of that file fills the session (~360 kB).
|
||||
|
||||
That sleep is production only. Tests never sleep.
|
||||
- **`channel.rs` stays ≤ 500 lines.** `hold` is about 15 lines.
|
||||
- **Uses.** The skeleton compiles with only `Context` and `Timestamp`. When filling `heartbeat`,
|
||||
add `use std::fs`, `Baseline`, `compact`, `Session`/`SessionError`, `Runtime`/`run_turn`,
|
||||
`TurnEvent`. When filling leftovers, add `jobs::{self, Run, RunStatus}`.
|
||||
- The items the edits use. This table is complete.
|
||||
|
||||
| Item | What it does |
|
||||
| Item | Signature |
|
||||
|---|---|
|
||||
| `Session::slot` / `create` / `open` | standing session |
|
||||
| `run_turn` / `finish_turn` | the pulse |
|
||||
| `Baseline::assemble` | new session |
|
||||
| `jobs::close_leftovers` / `live_session` / `append` | leftovers |
|
||||
| `Timestamp::unix_millis` / `to_rfc3339` | due and the time line |
|
||||
| `Session::open` | `open(home: &Path, id: SessionId) -> Result<Session, SessionError>` |
|
||||
| `Session::create` | `create(home, id, baseline, slot: u32) -> Result<Session, SessionError>` |
|
||||
| `SessionError::NotFound` | `_` |
|
||||
| `Baseline::assemble` | `assemble(&ctx.cfg, &ctx.registry) -> Result<Baseline, _>` |
|
||||
| `Runtime` | `{ cfg: &ctx.cfg, client: &ctx.client, port: &*ctx.port, registry: &ctx.registry }` |
|
||||
| `run_turn` | `run_turn(&mut session, &runtime, &text, None, &mut emit)` |
|
||||
| `compact::finish_turn` | `finish_turn(&mut session, &runtime, &*ctx.memory, &text, None, &mut emit, outcome)` |
|
||||
| `jobs::load` | `load(dir: &Path) -> Result<Vec<Job>, JobsError>` |
|
||||
| `jobs::live_session` | `live_session(ledger, name) -> Result<Option<SessionId>, _>` |
|
||||
| `jobs::append` | `append(ledger, &Run { time, name, session, status })` |
|
||||
| `RunStatus::Failed` | leftover close |
|
||||
| `Timestamp` | `unix_millis() -> u64`, `to_rfc3339() -> String`, `now()` |
|
||||
|
||||
## The edits, exactly
|
||||
|
||||
@@ -134,8 +149,9 @@ pub struct Busy;
|
||||
|
||||
### `crates/loopd/src/scheduler.rs`
|
||||
|
||||
Write this module. Fill `tick`. Cron jobs stay a comment until task 07: after heartbeat, do
|
||||
not iterate job files yet.
|
||||
Write this module. `tick` is already glue. Fill `heartbeat` then `close_idle_leftovers`,
|
||||
`cargo check -p loopd` after each (T25). Do not iterate job files (task 07). Do not add
|
||||
`run_jobs`.
|
||||
|
||||
```rust
|
||||
//! Isolated heartbeat (and, from task 07, cron) turns (M5d spec, section 4).
|
||||
@@ -170,14 +186,26 @@ impl Scheduler {
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, ctx: &Context, now: Timestamp) -> Vec<TickWork> {
|
||||
let _ = (ctx, now);
|
||||
Vec::new()
|
||||
let mut work = Vec::new();
|
||||
if !self.leftovers_closed {
|
||||
close_idle_leftovers(ctx, now);
|
||||
self.leftovers_closed = true;
|
||||
}
|
||||
self.heartbeat(ctx, now, &mut work);
|
||||
work
|
||||
}
|
||||
|
||||
fn heartbeat(&mut self, ctx: &Context, now: Timestamp, work: &mut Vec<TickWork>) {
|
||||
let _ = (ctx, now, work);
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Replace the `tick` body in this task. `leftovers_closed` is set true after the first leftover
|
||||
pass so it runs once.
|
||||
fn close_idle_leftovers(ctx: &Context, now: Timestamp) {
|
||||
let _ = (ctx, now);
|
||||
todo!()
|
||||
}
|
||||
```
|
||||
|
||||
## Steps
|
||||
|
||||
@@ -190,9 +218,10 @@ pass so it runs once.
|
||||
- [ ] **2. See it fail.** `cargo build --tests --keep-going -p loopd`, timeout 600000 ms: test
|
||||
target `scheduler_heartbeat` does not compile (`E0432` unresolved `loopd::scheduler`,
|
||||
`E0599` no method `hold`). Every other target compiles.
|
||||
- [ ] **3. The edits.** C1, C2, `scheduler.rs`, `pub mod scheduler;`, main thread. Fill
|
||||
`tick`. `cargo check -p loopd` prints no error and no warning.
|
||||
`wc -l crates/loopd/src/scheduler.rs` and `wc -l crates/loopd/src/channel.rs` each ≤ 500.
|
||||
- [ ] **3. The edits.** C1, C2, `scheduler.rs` (fill `heartbeat` then `close_idle_leftovers`,
|
||||
`cargo check -p loopd` after each), `pub mod scheduler;`, main thread. `cargo check -p loopd`
|
||||
prints no error and no warning. `wc -l crates/loopd/src/scheduler.rs` and
|
||||
`wc -l crates/loopd/src/channel.rs` each ≤ 500.
|
||||
- [ ] **4. The tests.** `cargo test -p loopd --test scheduler_heartbeat --test channel --test
|
||||
session_slot`: every test passes, 6 in `scheduler_heartbeat`.
|
||||
- [ ] **5. The runbook.**
|
||||
|
||||
Reference in New Issue
Block a user