From b3991a5843f0fbb7cfdc77138a98af4332519478 Mon Sep 17 00:00:00 2001 From: Jonathan <64296013+Joncallim@users.noreply.github.com> Date: Wed, 2 Sep 2026 22:34:28 +0800 Subject: [PATCH] feat: surface cron collection state --- apps/web/src/lib/demoData.ts | 3 ++- apps/web/src/lib/model.test.ts | 9 +++++---- apps/web/src/lib/testProviderStates.ts | 3 ++- apps/web/src/screens/Runtime.tsx | 3 ++- apps/web/src/screens/runtime-provider-states.test.tsx | 6 ++++-- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/web/src/lib/demoData.ts b/apps/web/src/lib/demoData.ts index e148b5a3..365b57ad 100644 --- a/apps/web/src/lib/demoData.ts +++ b/apps/web/src/lib/demoData.ts @@ -234,9 +234,10 @@ const demoRuntimeMap: RuntimeMap = { providerStates: [ { slot: "network_infrastructure", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" }, { slot: "host_scoped", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" }, + { slot: "cron", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" }, + { slot: "systemd", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" }, { slot: "python_processes", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" }, { slot: "native_processes", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" }, - { slot: "systemd", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" }, { slot: "project_npm", state: "unavailable", lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, consecutiveFailureCount: 0, dataRevision: null, statusReason: "initial" } ], nodes: [ diff --git a/apps/web/src/lib/model.test.ts b/apps/web/src/lib/model.test.ts index ac10a8c6..c6e29a41 100644 --- a/apps/web/src/lib/model.test.ts +++ b/apps/web/src/lib/model.test.ts @@ -65,10 +65,11 @@ describe("runtime collection evidence", () => { const providerStates: RuntimeMap["providerStates"] = [ { ...testProviderStates[0], state: "fresh", lastAttemptMs: 1, lastSuccessMs: 2, lastDurationMs: 1, dataRevision: "test-provider-1", statusReason: null }, { ...testProviderStates[1], state: "stale", lastAttemptMs: 1, lastSuccessMs: 2, lastDurationMs: 1, consecutiveFailureCount: 1, dataRevision: "test-provider-2", statusReason: "collection_failed" }, - { ...testProviderStates[2], state: "collecting", lastAttemptMs: 3, statusReason: "refreshing" }, - { ...testProviderStates[3], state: "timed_out", lastAttemptMs: 3, lastSuccessMs: 2, lastDurationMs: 1, consecutiveFailureCount: 1, dataRevision: "test-provider-4", statusReason: "collection_timed_out" }, - { ...testProviderStates[4], state: "disabled", statusReason: "disabled" }, - { ...testProviderStates[5], state: "disabled", statusReason: "disabled" } + { ...testProviderStates[2], state: "fresh", lastAttemptMs: 1, lastSuccessMs: 2, lastDurationMs: 1, dataRevision: "test-provider-3", statusReason: null }, + { ...testProviderStates[3], state: "collecting", lastAttemptMs: 3, statusReason: "refreshing" }, + { ...testProviderStates[4], state: "timed_out", lastAttemptMs: 3, lastSuccessMs: 2, lastDurationMs: 1, consecutiveFailureCount: 1, dataRevision: "test-provider-5", statusReason: "collection_timed_out" }, + { ...testProviderStates[5], state: "disabled", statusReason: "disabled" }, + { ...testProviderStates[6], state: "disabled", statusReason: "disabled" } ]; const model = buildModel(snapshot([]), { ...emptyRuntime, providerStates }); diff --git a/apps/web/src/lib/testProviderStates.ts b/apps/web/src/lib/testProviderStates.ts index b909a5b3..cc295239 100644 --- a/apps/web/src/lib/testProviderStates.ts +++ b/apps/web/src/lib/testProviderStates.ts @@ -8,8 +8,9 @@ function unavailableProviderState(slot: ProviderSlot): ProviderState { } /** Complete fixed-slot state used by browser-only fixtures. */ -export const testProviderStates: [ProviderState, ProviderState, ProviderState, ProviderState, ProviderState, ProviderState] = [ +export const testProviderStates: [ProviderState, ProviderState, ProviderState, ProviderState, ProviderState, ProviderState, ProviderState] = [ unavailableProviderState("network_infrastructure"), unavailableProviderState("host_scoped"), + unavailableProviderState("cron"), unavailableProviderState("systemd"), unavailableProviderState("python_processes"), unavailableProviderState("native_processes"), unavailableProviderState("project_npm") diff --git a/apps/web/src/screens/Runtime.tsx b/apps/web/src/screens/Runtime.tsx index 842a435d..b68099d4 100644 --- a/apps/web/src/screens/Runtime.tsx +++ b/apps/web/src/screens/Runtime.tsx @@ -49,6 +49,7 @@ const LAYER_LABEL: Record = { const PROVIDER_SLOT_LABEL: Record = { network_infrastructure: "Network infrastructure", host_scoped: "Host-scoped services", + cron: "Cron schedule declarations", systemd: "systemd services", python_processes: "Python processes", native_processes: "Native processes", @@ -298,7 +299,7 @@ export default function RuntimeScreen() {
    diff --git a/apps/web/src/screens/runtime-provider-states.test.tsx b/apps/web/src/screens/runtime-provider-states.test.tsx index 96580803..3acbe114 100644 --- a/apps/web/src/screens/runtime-provider-states.test.tsx +++ b/apps/web/src/screens/runtime-provider-states.test.tsx @@ -21,6 +21,7 @@ const runtime: RuntimeMap = { providerStates: [ collectionState("network_infrastructure", "fresh"), collectionState("host_scoped", "stale", { consecutiveFailureCount: 1, statusReason: "collection_failed" }), + collectionState("cron", "fresh"), collectionState("systemd", "collecting", { lastSuccessMs: null, lastDurationMs: null, dataRevision: null, statusReason: "refreshing" }), collectionState("python_processes", "timed_out", { consecutiveFailureCount: 1, statusReason: "collection_timed_out" }), collectionState("native_processes", "disabled", { lastAttemptMs: null, lastSuccessMs: null, lastDurationMs: null, dataRevision: null, statusReason: "disabled" }), @@ -45,10 +46,11 @@ describe("Runtime collection evidence", () => { const html = render(); expect(html).toContain("Collection evidence"); - expect(html).toContain("Collection state only — it does not describe service health"); - expect(html.match(/class="provider-state-row /g)).toHaveLength(6); + expect(html).toContain("Collection state only — it does not describe service health or cron execution"); + expect(html.match(/class="provider-state-row /g)).toHaveLength(7); expect(html).toContain("Network infrastructure"); expect(html).toContain("Host-scoped services"); + expect(html).toContain("Cron schedule declarations"); expect(html).toContain("systemd services"); expect(html).toContain("Python processes"); expect(html).toContain("Native processes");