Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
44ef355
fix(automations-ui): readable summary cards and NEXT RUN value
italic-jinxin Jun 15, 2026
a8c9e01
fix(automations-ui): surface delivery save errors and gate Slack hint
italic-jinxin Jun 15, 2026
97de732
fix(automations-ui): label sub-hourly cron schedules
italic-jinxin Jun 15, 2026
5a3c797
fix(automations-ui): space the run-row action button icons
italic-jinxin Jun 15, 2026
7e9044e
fix(automations-ui): consistent summary counts and next-run
italic-jinxin Jun 15, 2026
c4f317e
test(automations): lock the panel UI fixes into the served bundle
italic-jinxin Jun 15, 2026
5c6c0db
feat(automations): surface scheduler-off state and run it by default …
italic-jinxin Jun 15, 2026
19081de
Merge branch 'main' into fix/reborn-automations-ux
italic-jinxin Jun 15, 2026
bad26e4
fix(i18n): add automations.delivery.saveFailed to every locale pack
italic-jinxin Jun 15, 2026
cb8d767
Merge branch 'fix/reborn-automations-ux' into fix/reborn-automations-…
italic-jinxin Jun 15, 2026
7ddf6cf
fix(automations-ui): clear stale Saved flash before a new delivery write
italic-jinxin Jun 15, 2026
56073af
fix(automations): harden next-run filter and lock scheduler_enabled o…
italic-jinxin Jun 15, 2026
5c6aed0
fix(i18n): add automations.schedulerOff keys to every locale pack
italic-jinxin Jun 15, 2026
f93c097
i18n(automations): translate schedulerOff strings in all locale packs
italic-jinxin Jun 15, 2026
1fd3335
i18n(automations): translate delivery.saveFailed in all locale packs
italic-jinxin Jun 15, 2026
343c376
Merge branch 'fix/reborn-automations-ux' into fix/reborn-automations-…
italic-jinxin Jun 15, 2026
1087a2a
Localize automation summary counts
think-in-universe Jun 15, 2026
afa7f0c
Remove duplicate automation summary locale keys
think-in-universe Jun 15, 2026
173f00a
Merge remote-tracking branch 'origin/main' into review-pr-4920
think-in-universe Jun 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion crates/ironclaw_product_workflow/src/reborn_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,16 @@ pub trait AutomationProductFacade: Send + Sync {
request: AutomationListRequest,
) -> Result<Vec<RebornAutomationInfo>, RebornServicesError>;

/// Whether the background trigger poller (scheduler) is running.
///
/// Surfaced to the browser so the panel can warn that listed automations
/// will not fire while scheduling is off. Defaults to `true` so a facade
/// that does not know its scheduler state never produces a false "off"
/// notice; the production facade overrides this with the real value.
fn scheduler_enabled(&self) -> bool {
true
}

/// Looks up the stored trigger-thread scope for a given `thread_id`.
///
/// Scans the caller-scoped triggers for one whose run history contains
Expand Down Expand Up @@ -2170,11 +2180,15 @@ impl RebornServicesApi for RebornServices {
};
let limit = clamp_automation_list_limit(request.limit);
let run_limit = clamp_automation_run_limit(request.run_limit);
let scheduler_enabled = self.automation_facade.scheduler_enabled();
let automations = self
.automation_facade
.list_automations(caller, AutomationListRequest { limit, run_limit })
.await?;
Ok(RebornListAutomationsResponse { automations })
Ok(RebornListAutomationsResponse {
automations,
scheduler_enabled,
})
}

async fn list_connectable_channels(
Expand Down
10 changes: 10 additions & 0 deletions crates/ironclaw_product_workflow/src/reborn_services/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,16 @@ pub struct RebornListThreadsResponse {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RebornListAutomationsResponse {
pub automations: Vec<RebornAutomationInfo>,
/// Whether the background trigger poller (scheduler) is running. When
/// `false`, listed schedule automations will never actually fire, and the
/// browser surfaces a "scheduling is off" notice. Defaults to `true` on the
/// wire so an older payload without the field is not misreported as off.
#[serde(default = "default_scheduler_enabled")]
pub scheduler_enabled: bool,
}

fn default_scheduler_enabled() -> bool {
true
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down
34 changes: 34 additions & 0 deletions crates/ironclaw_product_workflow/tests/reborn_services_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,7 @@ impl AutomationProductFacade for RecordingAutomationFacade {
#[derive(Clone)]
struct StaticAutomationFacade {
output: Vec<RebornAutomationInfo>,
scheduler_enabled: bool,
/// Scopes returned by `resolve_run_thread_scope`, keyed by the queried
/// thread id so tests prove the lookup contract rather than accepting a
/// cached scope for any request.
Expand All @@ -870,11 +871,17 @@ impl StaticAutomationFacade {
fn new(output: Vec<RebornAutomationInfo>) -> Self {
Self {
output,
scheduler_enabled: true,
resolve_scopes: HashMap::new(),
resolve_calls: Arc::new(Mutex::new(Vec::new())),
}
}

fn with_scheduler_enabled(mut self, scheduler_enabled: bool) -> Self {
self.scheduler_enabled = scheduler_enabled;
self
}

fn with_resolve_scope_for_thread(
mut self,
thread_id: ThreadId,
Expand All @@ -891,6 +898,10 @@ impl StaticAutomationFacade {

#[async_trait]
impl AutomationProductFacade for StaticAutomationFacade {
fn scheduler_enabled(&self) -> bool {
self.scheduler_enabled
}

async fn list_automations(
&self,
_caller: ProductAgentBoundCaller,
Expand Down Expand Up @@ -6559,6 +6570,29 @@ async fn list_automations_returns_empty_list() {
.expect("list automations");

assert!(listed.automations.is_empty());
// Default facade reports the scheduler as running.
assert!(listed.scheduler_enabled);
}

#[tokio::test]
async fn list_automations_surfaces_disabled_scheduler() {
// Regression: when the trigger poller is off, the response must report
// scheduler_enabled=false so the browser can warn that listed automations
// will not fire. Previously the wire response had no such signal.
let services = RebornServices::new(
Arc::new(InMemorySessionThreadService::default()),
Arc::new(FakeTurnCoordinator::default()),
)
.with_automation_product_facade(Arc::new(
StaticAutomationFacade::new(Vec::new()).with_scheduler_enabled(false),
));

let listed = services
.list_automations(caller(), WebUiListAutomationsRequest::default())
.await
.expect("list automations");

assert!(!listed.scheduler_enabled);
}

#[tokio::test]
Expand Down
1 change: 1 addition & 0 deletions crates/ironclaw_reborn_cli/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ pub(crate) fn build_runtime_input_with_options(
.with_runner_settings(runner_settings(runtime_services.config_file.as_ref())?)
.with_trigger_poller_settings(trigger_poller_settings(
runtime_services.config_file.as_ref(),
caller,
)?)
.with_poll_settings(PollSettings {
interval: Duration::from_millis(200),
Expand Down
Loading
Loading