Run the plan-execute loop inside the daemon #15

Merged
Breadway merged 1 commit from feature/ram-44-plan-execute into main 2026-10-11 15:46:39 +08:00
Owner

Closes RAM-44.

The coordinator could execute a plan and the daemon could plan one, but nothing joined them, so the journal was always empty and the end-to-end path was never demonstrable.

What landed

breadram_core::execution — the join, in one place. requests_for_plan turns a plan into action requests (resolving the value to apply from the configured budget, and refusing what the configuration no longer allows with a named reason), and execute_plan runs them through the coordinator. It is the only code that decides whether a proposed action may be written: the mode is checked there, so no caller can bypass it, and a refusal is recorded rather than dropped.

Restart recovery — breadram_core::coordinator::persist holds a versioned state file of the values breadram owns; ActionJournal::from_owned_values rebuilds a journal that owns them; Coordinator::recover restores a value only while it still equals what breadram last wrote. A value something else changed is left alone, a gone target is skipped, and a state file this build does not understand is reported and ignored. The daemon writes it beside the runtime socket's state directory and reports what a startup restore did.

Daemon wiring — the monitor pass now builds the adapter registry from the configured providers (a provider names the workload scope it owns; an endpoint with no scope, or a kind this build has no adapter for, is reported as contributing nothing), hands the real systemd ControlExecutor to the execute step, publishes what it wrote, and marks journal.executing honestly. Only automatic mode writes; the plan is still built and explained in monitor mode, labelled dry_run.

Verification

Live on this host, with a transient user scope holding 200 MiB and a 4 MiB budget, in automatic mode: breadram set MemoryHigh through systemd (MemoryCurrent 66.8 MiB → 4.2 MiB), and breadram actions showed confirmed with the reason, the target, the timestamp, requested: -62599168, observed: -9408512, and the owned value with its original. Subsequent passes reported skipped_duplicate, so the same action is not applied twice. After a restart the setting went back to its recorded original and the journal showed rolled_back | restored systemd:breadram-live-probe.scope:MemoryHigh to its original value. In monitor mode the same configuration wrote nothing, left the state file byte for byte unchanged, and still reported the plan as dry_run with a monitor note.

Tests: 336 pass. cargo fmt --all -- --check and cargo clippy --workspace --all-targets -- -D warnings are clean.

Two defects were caught by running it rather than by reading it: a recovered ownership record made has_confirmed true, which would have suppressed the action forever after a restart even though the restart had just undone it; and the startup restore note was being cleared by the first tick.

Not done here, named rather than implied

  • No provider action can be executed yet: there is still no HTTP Transport in breadram_core::adapter, so only host controls run. Configured providers are attached and their activity evidence reaches policy, which is what makes an idle-model release plannable; executing it needs the transport from RAM-13/RAM-14/RAM-45.
  • A mode switch to monitor stops new writes but does not restore values already applied; the switch is reported, and the next automatic run restores them.
  • The plan-execute step is verified against a fake executor in-process and against a real transient scope live; it has not been run against a sustained, host-wide memory shortage, because pressuring this host is exactly what RAM-29 forbids.
Closes RAM-44. The coordinator could execute a plan and the daemon could plan one, but nothing joined them, so the journal was always empty and the end-to-end path was never demonstrable. ## What landed **`breadram_core::execution`** — the join, in one place. `requests_for_plan` turns a plan into action requests (resolving the value to apply from the configured budget, and refusing what the configuration no longer allows with a named reason), and `execute_plan` runs them through the coordinator. It is the only code that decides whether a proposed action may be written: the mode is checked there, so no caller can bypass it, and a refusal is recorded rather than dropped. **Restart recovery** — `breadram_core::coordinator::persist` holds a versioned state file of the values breadram owns; `ActionJournal::from_owned_values` rebuilds a journal that owns them; `Coordinator::recover` restores a value only while it still equals what breadram last wrote. A value something else changed is left alone, a gone target is skipped, and a state file this build does not understand is reported and ignored. The daemon writes it beside the runtime socket's state directory and reports what a startup restore did. **Daemon wiring** — the monitor pass now builds the adapter registry from the configured providers (a provider names the workload scope it owns; an endpoint with no scope, or a kind this build has no adapter for, is reported as contributing nothing), hands the real systemd `ControlExecutor` to the execute step, publishes what it wrote, and marks `journal.executing` honestly. Only `automatic` mode writes; the plan is still built and explained in monitor mode, labelled `dry_run`. ## Verification Live on this host, with a transient user scope holding 200 MiB and a 4 MiB budget, in `automatic` mode: breadram set `MemoryHigh` through systemd (`MemoryCurrent` 66.8 MiB → 4.2 MiB), and `breadram actions` showed `confirmed` with the reason, the target, the timestamp, `requested: -62599168`, `observed: -9408512`, and the owned value with its original. Subsequent passes reported `skipped_duplicate`, so the same action is not applied twice. After a restart the setting went back to its recorded original and the journal showed `rolled_back | restored systemd:breadram-live-probe.scope:MemoryHigh to its original value`. In `monitor` mode the same configuration wrote nothing, left the state file byte for byte unchanged, and still reported the plan as `dry_run` with a monitor note. Tests: 336 pass. `cargo fmt --all -- --check` and `cargo clippy --workspace --all-targets -- -D warnings` are clean. Two defects were caught by running it rather than by reading it: a recovered ownership record made `has_confirmed` true, which would have suppressed the action forever after a restart even though the restart had just undone it; and the startup restore note was being cleared by the first tick. ## Not done here, named rather than implied - No provider action can be executed yet: there is still no HTTP `Transport` in `breadram_core::adapter`, so only host controls run. Configured providers are attached and their activity evidence reaches policy, which is what makes an idle-model release plannable; executing it needs the transport from RAM-13/RAM-14/RAM-45. - A mode switch to `monitor` stops new writes but does not restore values already applied; the switch is reported, and the next automatic run restores them. - The plan-execute step is verified against a fake executor in-process and against a real transient scope live; it has not been run against a sustained, host-wide memory shortage, because pressuring this host is exactly what RAM-29 forbids.
The coordinator could execute a plan and the daemon could plan one,
but nothing joined them, so the journal was always empty and the
"pressure in, memory released, pressure down" path was never
demonstrable.

The plan-execute step is now one function in the core, and it is the
only place that decides whether a proposed action may be written: the
mode is checked there, the allowed actions are checked again, and a
refusal is recorded rather than dropped. The daemon runs it on each
pass with the real systemd control executor and the adapter registry
built from the configured providers, publishes what it wrote, and
remembers the values it owns in a versioned state file. A restart
restores a value only while it still equals what breadram last wrote.
Breadway deleted branch feature/ram-44-plan-execute 2026-10-11 15:46:39 +08:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/breadram!15
No description provided.