Execute provider actions through a real transport and executor #16

Closed
opened 2026-10-11 15:48:34 +08:00 by Breadway · 3 comments
Owner

Gap found while delivering RAM-12 (the Ollama adapter) and RAM-44 (the plan-execute loop).

Provider relief is the biggest memory win breadram has, and the pieces exist on both sides but do not meet:

  • The adapters can describe an operation (AdapterOperation: request, expected deltas, note, confirmation) — RAM-12 landed one for Ollama and RAM-13/RAM-14 will add more.
  • The coordinator can execute an action through an Executor, confirm it, measure the observed effect, and journal it — and RAM-44 now runs that loop in the daemon with the real host-control executor.
  • AdapterRegistry is built from config.providers and its activity evidence reaches the planner, so an idle-model release is planned.

Nothing can perform a provider action:

  1. There is no real Transport. breadram_core::adapter::probe defines the trait and only ships ScriptedTransport, so nothing can send an HTTP request to a loopback provider or a unix socket.
  2. There is no executor that turns an AdapterOperation into a request, evaluates its confirmation, and reports the measured memory change, and no composite that lets the daemon dispatch host controls and provider actions through one Executor.

Scope

  • A real bounded transport: http (loopback) and unix: endpoints, per attempt timeout, response size cap, Connection: close, and no credential ever rendered.
  • An adapter executor implementing coordinator::Executor: revalidate the capability and the workload generation, refuse a release that needs proven idleness when activity is unknown, send the operation, evaluate the confirmation, and read the target's host and device memory before and after so the observed effect is real.
  • A composite executor so the daemon keeps host controls and provider actions in one pass.
  • Daemon wiring for the adapter executor, with the endpoint allow list coming from the configured providers.
  • Wire-level tests against an in-process fake provider server, since no provider is installed on this host: an idle release confirmed, a busy backend refused, a provider that cannot be reached, and an operation whose effect cannot be confirmed.

Acceptance criteria

  • With a configured provider and an in-memory fake serving the provider API, an idle-model release is planned, performed, confirmed, and journalled with a measured effect, and the journal names the cold start the release costs.
  • A backend with a live request lease is never released, and a failed or unconfirmed release is journalled rather than reported as success.
  • No request can reach an endpoint outside the configured allow list, and a credential never appears in a Debug, Display, error, or log line.
  • No provider needs to be installed: the fake server is part of the test support, and any suite that needs real hardware is gated and reports skips honestly (RAM-29).

Blocked by nothing. Related: RAM-11/RAM-45 (leases and the gateway), RAM-13, RAM-14.

Gap found while delivering RAM-12 (the Ollama adapter) and RAM-44 (the plan-execute loop). Provider relief is the biggest memory win breadram has, and the pieces exist on both sides but do not meet: - The adapters can describe an operation (`AdapterOperation`: request, expected deltas, note, confirmation) — RAM-12 landed one for Ollama and RAM-13/RAM-14 will add more. - The coordinator can execute an action through an `Executor`, confirm it, measure the observed effect, and journal it — and RAM-44 now runs that loop in the daemon with the real host-control executor. - `AdapterRegistry` is built from `config.providers` and its activity evidence reaches the planner, so an idle-model release is *planned*. Nothing can perform a provider action: 1. There is no real `Transport`. `breadram_core::adapter::probe` defines the trait and only ships `ScriptedTransport`, so nothing can send an HTTP request to a loopback provider or a unix socket. 2. There is no executor that turns an `AdapterOperation` into a request, evaluates its confirmation, and reports the measured memory change, and no composite that lets the daemon dispatch host controls and provider actions through one `Executor`. ### Scope - A real bounded transport: `http` (loopback) and `unix:` endpoints, per attempt timeout, response size cap, `Connection: close`, and no credential ever rendered. - An adapter executor implementing `coordinator::Executor`: revalidate the capability and the workload generation, refuse a release that needs proven idleness when activity is unknown, send the operation, evaluate the confirmation, and read the target's host and device memory before and after so the observed effect is real. - A composite executor so the daemon keeps host controls and provider actions in one pass. - Daemon wiring for the adapter executor, with the endpoint allow list coming from the configured providers. - Wire-level tests against an in-process fake provider server, since no provider is installed on this host: an idle release confirmed, a busy backend refused, a provider that cannot be reached, and an operation whose effect cannot be confirmed. ### Acceptance criteria - With a configured provider and an in-memory fake serving the provider API, an idle-model release is planned, performed, confirmed, and journalled with a measured effect, and the journal names the cold start the release costs. - A backend with a live request lease is never released, and a failed or unconfirmed release is journalled rather than reported as success. - No request can reach an endpoint outside the configured allow list, and a credential never appears in a Debug, Display, error, or log line. - No provider needs to be installed: the fake server is part of the test support, and any suite that needs real hardware is gated and reports skips honestly (RAM-29). Blocked by nothing. Related: RAM-11/RAM-45 (leases and the gateway), RAM-13, RAM-14.
Author
Owner

Started. Status, uncommitted in the working tree on main @ 639f630:

Done

The real transport, breadram-core/src/adapter/http.rs: loopback http only, one connection per request, connect/read/write timeouts, Connection: close, content-length and chunked parsing, a response size cap, credentials never rendered, and every resolved address tried in turn (localhost resolving to ::1 while the server listens on 127.0.0.1 was a real harness fault this caught). Transport carries probes; a separate OperationTransport carries writes, so a read-only path can never be handed a write request. 13 tests, all passing. fmt and clippy -D warnings clean, cargo test --workspace 349 pass, 0 fail.

Deviation from this card's scope

unix: is not supported, and it says so with a reason instead of failing silently. The hook protocol is a process protocol rather than HTTP, so a unix socket needs a framed message format and an ownership/permission check that does not exist yet. Recorded here rather than quietly dropped.

Two gaps found while wiring the executor, both needed before provider relief can fire in production

  1. Nothing refreshes an adapter's view. OllamaAdapter::observe_loaded / observe_version are called only from tests — the daemon never feeds probe results back, and operation() returns None unless the state is fresh. So an adapter executor wired up today would refuse every action as "nothing to release right now". Being fixed in this card: a WorkloadAdapter::observe hook, a ProbeOutcome, and a daemon refresh step each tick.
  2. Request tracking must be declared. With the default (TrackingCompleteness::Unknown) a loaded model reports Active, so a release is refused however long the model has been resident. That is the conservative direction and is correct, but it means the release path is dead until tracking is declared — and today nothing declares it, because the gateway that would feed real leases is RAM-45. Until then, provider relief is planned-never-executed by design, not by accident. This is a separate decision (a config field, or RAM-45) and is not being invented inside this card.
Started. Status, uncommitted in the working tree on `main` @ `639f630`: ## Done The real transport, `breadram-core/src/adapter/http.rs`: loopback `http` only, one connection per request, connect/read/write timeouts, `Connection: close`, content-length and chunked parsing, a response size cap, credentials never rendered, and every resolved address tried in turn (`localhost` resolving to `::1` while the server listens on `127.0.0.1` was a real harness fault this caught). `Transport` carries probes; a separate `OperationTransport` carries writes, so a read-only path can never be handed a write request. **13 tests, all passing.** `fmt` and `clippy -D warnings` clean, `cargo test --workspace` 349 pass, 0 fail. ## Deviation from this card's scope `unix:` is **not** supported, and it says so with a reason instead of failing silently. The hook protocol is a process protocol rather than HTTP, so a unix socket needs a framed message format and an ownership/permission check that does not exist yet. Recorded here rather than quietly dropped. ## Two gaps found while wiring the executor, both needed before provider relief can fire in production 1. **Nothing refreshes an adapter's view.** `OllamaAdapter::observe_loaded` / `observe_version` are called only from tests — the daemon never feeds probe results back, and `operation()` returns `None` unless the state is fresh. So an adapter executor wired up today would refuse every action as "nothing to release right now". Being fixed in this card: a `WorkloadAdapter::observe` hook, a `ProbeOutcome`, and a daemon refresh step each tick. 2. **Request tracking must be declared.** With the default (`TrackingCompleteness::Unknown`) a *loaded* model reports `Active`, so a release is refused however long the model has been resident. That is the conservative direction and is correct, but it means the release path is dead until tracking is declared — and today nothing declares it, because the gateway that would feed real leases is RAM-45. Until then, provider relief is planned-never-executed by design, not by accident. This is a separate decision (a config field, or RAM-45) and is not being invented inside this card.
Author
Owner

Implemented and verified, on feature/ram-48-provider-execution at a25f352 (not pushed, so no PR yet).

What landed

  • The real transport (adapter/http.rs): loopback http only, one connection per request, connect/read/write timeouts, Connection: close, content-length and chunked parsing, a response size cap, credentials never rendered, every resolved address tried in turn. Transport carries probes and OperationTransport carries writes, so a read-only path cannot be handed a write. 13 tests.
  • adapter::AdapterExecutor: an Executor for the provider-backed actions. It revalidates the capability and the workload generation, refuses a release that needs proven idleness when activity is unknown, active, or too recent, checks every URL against the configured endpoints before sending, applies, confirms with a read-only probe, and reports the memory the provider holds before and after. 17 tests.
  • coordinator::ChainedExecutor: host controls and provider actions in one pass, dispatched by what each claims, with the first real measurement winning on either memory axis. 4 tests.
  • Adapter observation: WorkloadAdapter::observe plus ProbeOutcome, AdapterRegistry::observe, adapter::refresh_adapters, and inventory_is_current, so an adapter is handed the answers to the probes it asked for and an empty current reading is a measured zero rather than a missing reading. The daemon refreshes every configured endpoint once per tick before policy runs, and reports a read that failed instead of leaving the previous success in place.
  • Daemon wiring: the pass now runs through the chain (host control + provider), and probe notes reach the operator.
  • A journal entry now carries the consequence: when an executor returns a note, it is recorded with the entry, so the cold start a model release costs is in the journal and not only in the pass that reported it.
  • Wire-level tests (tests/provider_execution.rs, 5 tests) against an in-process fake Ollama service on a real socket: an idle release planned, performed, confirmed, and journalled with a measured effect; a backend with a live request never written to; an unreachable provider reported and unable to release; a provider that ignores the unload journalled as unconfirmed with a zero observed delta; monitor mode writing nothing.

Verification

cargo fmt --all --check clean, cargo clippy --workspace --all-targets -- -D warnings clean, cargo test --workspace 376 passed, 0 failed, exit status 0 (up from 349).

Deviations, stated rather than dropped

  • unix: is not supported, with a reason. The hook protocol is a process protocol, not HTTP.
  • The requested host delta on a provider action is the plan's estimate (sized from the workload's memory), while the provider's own figure differs. Both are now recorded in the entry rather than one being silently preferred.
  • With default TrackingCompleteness::Unknown a resident model reports Active, so nothing is planned against it. Correct and conservative, but it means the release path is planned-never-executed until request tracking is declared (RAM-45). Filed as the one open dependency rather than inferred inside this card.

Left

Push and PR, then merge. No provider is installed on this host, so the daemon path itself is covered by build plus a unit test that drives the daemon's own read path against a closed port; the end-to-end release is proven at the core level over a real socket.

Implemented and verified, on `feature/ram-48-provider-execution` at `a25f352` (not pushed, so no PR yet). ## What landed - **The real transport** (`adapter/http.rs`): loopback `http` only, one connection per request, connect/read/write timeouts, `Connection: close`, content-length and chunked parsing, a response size cap, credentials never rendered, every resolved address tried in turn. `Transport` carries probes and `OperationTransport` carries writes, so a read-only path cannot be handed a write. 13 tests. - **`adapter::AdapterExecutor`**: an `Executor` for the provider-backed actions. It revalidates the capability and the workload generation, refuses a release that needs proven idleness when activity is unknown, active, or too recent, checks every URL against the configured endpoints before sending, applies, confirms with a read-only probe, and reports the memory the provider holds before and after. 17 tests. - **`coordinator::ChainedExecutor`**: host controls and provider actions in one pass, dispatched by what each claims, with the first real measurement winning on either memory axis. 4 tests. - **Adapter observation**: `WorkloadAdapter::observe` plus `ProbeOutcome`, `AdapterRegistry::observe`, `adapter::refresh_adapters`, and `inventory_is_current`, so an adapter is handed the answers to the probes it asked for and an empty current reading is a measured zero rather than a missing reading. The daemon refreshes every configured endpoint once per tick before policy runs, and reports a read that failed instead of leaving the previous success in place. - **Daemon wiring**: the pass now runs through the chain (host control + provider), and probe notes reach the operator. - **A journal entry now carries the consequence**: when an executor returns a note, it is recorded with the entry, so the cold start a model release costs is in the journal and not only in the pass that reported it. - **Wire-level tests** (`tests/provider_execution.rs`, 5 tests) against an in-process fake Ollama service on a real socket: an idle release planned, performed, confirmed, and journalled with a measured effect; a backend with a live request never written to; an unreachable provider reported and unable to release; a provider that ignores the unload journalled as unconfirmed with a zero observed delta; monitor mode writing nothing. ## Verification `cargo fmt --all --check` clean, `cargo clippy --workspace --all-targets -- -D warnings` clean, `cargo test --workspace` **376 passed, 0 failed, exit status 0** (up from 349). ## Deviations, stated rather than dropped - `unix:` is not supported, with a reason. The hook protocol is a process protocol, not HTTP. - The requested host delta on a provider action is the plan's estimate (sized from the workload's memory), while the provider's own figure differs. Both are now recorded in the entry rather than one being silently preferred. - With default `TrackingCompleteness::Unknown` a resident model reports `Active`, so nothing is planned against it. Correct and conservative, but it means the release path is planned-never-executed until request tracking is declared (RAM-45). Filed as the one open dependency rather than inferred inside this card. ## Left Push and PR, then merge. No provider is installed on this host, so the daemon path itself is covered by build plus a unit test that drives the daemon's own read path against a closed port; the end-to-end release is proven at the core level over a real socket.
Author
Owner

Merged as PR #17 into main at 774fe49. Verified on main after the merge: cargo fmt --all --check clean, cargo clippy --workspace --all-targets -- -D warnings clean, cargo test --workspace 376 passed, 0 failed. Branch deleted.

Provider relief is now executable end to end, with the two honest limits recorded above (no unix: transport, and no release until request tracking is declared).

Merged as PR #17 into `main` at `774fe49`. Verified on `main` after the merge: `cargo fmt --all --check` clean, `cargo clippy --workspace --all-targets -- -D warnings` clean, `cargo test --workspace` 376 passed, 0 failed. Branch deleted. Provider relief is now executable end to end, with the two honest limits recorded above (no `unix:` transport, and no release until request tracking is declared).
Sign in to join this conversation.
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#16
No description provided.