Skip to main content
0.0.x

Background child health

The exported @netscript/plugin/health contract describes the background child that performs durable work. Its health listener runs under the service identity, independently of an open phone, browser, or owner session. CLI and MCP diagnostics read this same contract through the shared plugin health aggregate.

The exported state union contains: starting, ready, degraded, crash-looping, stopped, failed.

ChildHealthState

Closed background child lifecycle vocabulary.

  • starting: Bootstrap is in progress; the child cannot accept durable work yet.
  • ready: Listeners are running, the registry is loaded, and dependencies are ready.
  • degraded: Listeners lack registry or dependency readiness, or a restart is underway.
  • crash-looping: The restart threshold is latched; brief successful starts stay unhealthy.
  • stopped: Clean shutdown completed; processing has stopped.
  • failed: A fatal bootstrap or listener failure prevents processing.

Example:

import type { ChildHealthState } from '@netscript/plugin/health';
const state: ChildHealthState = 'starting';

ChildHealthSnapshot

Bounded JSON health payload for one background child.

registryReady confirms the generated definitions loaded and validated. dependencyReady confirms startup checks succeeded and no listener failure is active. restartCount is cumulative for this child instance. lastFatalError contains only a fixed redacted message and an epoch timestamp; the raw exception and stack never leave the process.

Example:

import type { ChildHealthSnapshot } from '@netscript/plugin/health';
const health: ChildHealthSnapshot = {
  state: 'starting',
  registryReady: false,
  dependencyReady: false,
  restartCount: 0,
  lastFatalError: null,
};

ChildFatalError

Public incident metadata; the original message and stack are deliberately withheld.

Example:

import type { ChildFatalError } from '@netscript/plugin/health';
const incident: ChildFatalError = {
  message: 'Background child failed (details redacted).',
  timestamp: 0,
};

CHILD_CRASH_LOOP_THRESHOLD

Restarts at or above the threshold within the window latch crash-looping.

Recovery requires a full window of uninterrupted running with registry and dependencies ready. A restart or fatal failure resets that running window; a brief ready interval cannot hide a storm.

Example:

import { CHILD_CRASH_LOOP_THRESHOLD } from '@netscript/plugin/health';
console.log(CHILD_CRASH_LOOP_THRESHOLD.restarts); // 3

The current threshold is 3 restarts within 60 seconds. The window includes its boundary. Only ready with both readiness flags true returns HTTP 200 from /health; other states return HTTP 503. A healthy API with a stopped or crash-looping child yields degraded in plugin doctor and MCP health. A child-only plugin with a dead child is unhealthy.

Authoring and migration in 0.0.8

declareHealthChecks and its unused HealthCheckSpec, SagasHealthCheckSpec, and TriggersHealthCheckSpec types were removed. Remove those overrides and type imports from custom Aspire contributions. Keep resource contribution and environment declarations.

The author scaffold declares the API's doctor.healthEndpoint in adapter metadata. The generated AppHost uses the service's HealthCheckPath appsettings value, defaulting to /health. The AppHost generator probes enabled Deno background entries with RequiresKv: true at /health, regardless of their resource name or entrypoint spelling. Custom children that declare this capability must serve the shared payload. Service health paths remain metadata-driven.

See Author a plugin for the two-tier scaffold. Dashboard panel rendering and installed-consumer failure experiments are separate acceptance work.