Wire breadcrumbs into the bread event fabric (app id crumbs)
All checks were successful
check / check (push) Successful in 36s

The watch daemon publishes bread.crumbs.profile.changed and
bread.crumbs.health.changed on real transitions (not every poll tick)
and honors bread.command.crumbs.set_profile via the existing
state::set_profile path. BreadClient is fail-silent: if breadd is
down, breadcrumbs behaves exactly as before.

Document the contract in EVENTS.md. CLAUDE.md now points at
CONTRIBUTING (single-trunk, no three-branch model), bakery, and
EVENTS.md.
This commit is contained in:
Breadway 2026-08-15 21:38:16 +08:00
parent 0f48b1499d
commit 9009404536
11 changed files with 588 additions and 19 deletions

View file

@ -2,7 +2,7 @@ use std::fs;
use serde::{Deserialize, Serialize};
use crate::config::{state_dir, state_path};
use crate::config::{state_dir, state_path, Config};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct State {
@ -32,3 +32,22 @@ impl State {
fs::write(state_path(), text).map_err(|e| format!("writing state: {e}"))
}
}
/// Persist `name` as the active profile if it exists in `cfg`. Shared by the
/// CLI `profile set` path and `bread.command.crumbs.set_profile` so they
/// cannot drift. Does not run [`crate::flow::run`] — the CLI applies
/// afterwards unless `--no-apply`, and the watch daemon picks the new
/// profile up on its next tick.
pub fn set_profile(cfg: &Config, name: &str) -> Result<(), String> {
if !cfg.profiles.contains_key(name) {
let avail: Vec<&String> = cfg.profiles.keys().collect();
return Err(format!("unknown profile '{name}'. Available: {avail:?}"));
}
State {
profile: name.to_string(),
updated: crate::util::timestamp(),
}
.save()?;
crate::notify::log(&format!("profile set -> {name}"));
Ok(())
}