Skip to content

Latest commit

 

History

History
113 lines (82 loc) · 6.78 KB

File metadata and controls

113 lines (82 loc) · 6.78 KB

Durable Process Jobs

Clankers exposes durable background work through the agent process tool. Use it for long-running builds, test suites, servers, and watchers instead of shell-level &, nohup, or disown.

Backends

The process tool accepts a backend field on start, list, poll, log, wait, kill, restart, adopt, and gc actions:

Backend Use when Notes
native You want the built-in local process registry. Default backend. Tracks child processes, incremental logs, stdin, completion state, native restart, native GC, and daemon restart reconciliation.
pueue You want queueing/group concurrency through pueue. Set group and label on starts when useful. Existing pueue tasks can be adopted with pueue_task_id or backend_ref: "pueue:<id>".
systemd You want transient systemd units and host-level resource controls. Existing units can be adopted with systemd_unit or backend_ref: "systemd:<unit>". NixOS deployments can configure unitPrefix, resource limits, working directory, writable paths, and kill grace.

Example tool payloads:

{ "action": "start", "backend": "native", "command": "cargo nextest run", "notify_on_complete": true }
{ "action": "start", "backend": "pueue", "group": "clankers", "label": "slow-check", "command": "nix flake check" }
{ "action": "start", "backend": "systemd", "label": "daemon-smoke", "program": "bash", "args": ["-lc", "./scripts/verify.sh"] }

Receipts and availability errors

Every backend operation returns a typed receipt shape with operation, id, backend, status, backend_ref, log_refs, and a bounded human summary when those fields apply. Unsupported or unavailable backends fail explicitly instead of silently falling back: for example, a missing pueue binary/daemon or unavailable systemd runner is reported as a backend availability error, while invalid profile/backend policy is reported before backend dispatch.

Native restart stops the current Clankers-owned process group when it is still running, relaunches the original shell/direct-exec start request, preserves the stable Clankers process id, and updates the backend PID reference. Reconciled metadata-only records that no longer have a live process handle still fail closed instead of guessing a restart target.

Notifications

notify_on_complete: true emits one notification when the job reaches a terminal state. Use this for builds, test suites, deploys, and other finite jobs.

watch_patterns is for rare readiness signals from long-lived jobs, such as Application startup complete. Matches are rate-limited and repeated noisy matches are suppressed. Do not use watch_patterns for end-of-run markers on finite jobs; prefer notify_on_complete.

Retention and garbage collection

Completed process/job records and retained logs are garbage-collected by policy. The gc/garbage_collect action accepts optional overrides:

{ "action": "gc", "max_age_days": 14, "max_records": 1000, "max_log_bytes": 1073741824 }

List operations also apply the default retention policy before projecting results, so expired terminal records do not remain visible indefinitely. Passing backend: "native" to gc limits explicit cleanup to native process records; active native jobs are skipped and reported in the typed receipt.

NixOS service configuration

The NixOS module enables durable process management under services.clankers-daemon.processManagement:

{
  services.clankers-daemon = {
    enable = true;
    processManagement = {
      enable = true;
      defaultBackend = "native";
      retention = {
        maxAgeDays = 14;
        maxRecords = 1000;
        maxLogBytes = 1073741824;
      };
      pueue = {
        enable = true;
        groups.clankers = 4;
      };
      systemd = {
        enable = true;
        unitPrefix = "clankers-job";
        runtimeMaxSec = 3600;
      };
    };
  };
}

The module creates the process-job registry and log directories below the daemon stateDir by default and can manage a dedicated pueue service when the pueue backend is enabled.

Project job profiles

The process-job-profile-kit is the copyable brick for backend-neutral process-job manifests. Project-defined profiles parse into backend-neutral StartProcessJobRequest values before any backend dispatch. A profile manifest is versioned with schema_version: 1 and each profile must set exactly one of command or program; args is valid only with program.

Manifest discovery is deterministic and explicit: product shells collect global, workspace, and explicit manifest sources, then ProjectProcessJobProfiles::resolve_from_sources selects the highest-precedence source for the requested profile (explicit > workspace > global). Duplicate profile names at the same precedence fail closed instead of selecting by filesystem order.

Policy controls the default backend, allowed backends, maximum timeout/memory/CPU/log bounds, allowed environment-variable prefixes, allowed working-directory prefixes, and allowed writable-path prefixes. Secret-like environment keys such as APP_TOKEN, APP_SECRET, or APP_KEY fail closed before backend dispatch. Writable paths outside policy fail closed before backend dispatch.

Reusable behavior lives in ProjectProcessJobProfiles, ProjectProcessJobProfileManifestSource, ProjectProcessJobProfilePolicy, ProjectProcessJobProfileValidationError, StartProcessJobRequest, ProcessJobIdentityEnvelope, and ProcessJobRedactionPolicy. Product-owned behavior remains outside the brick: selecting a daemon/session, reading manifest files from disk, spawning native/pueue/systemd jobs, persisting receipts/logs, and notifying users. Resolving a profile is pure: it validates policy and returns a start request plus source/policy evidence, but does not spawn a process, contact pueue/systemd, or write storage.

Safe profile identity metadata is copied into the resolved start request under profile, identity.profile.schema_version, identity.profile.source, and identity.profile.policy. Those keys are eligible for BLAKE3 identity envelopes and receipt/projection surfaces; raw environment values and backend locators are not.

Profile JSON shape:

{
  "schema_version": 1,
  "profiles": {
    "quick-check": {
      "backend": "native",
      "command": "cargo check --tests",
      "cwd": "/home/example/project",
      "writable_paths": ["/home/example/project/target"],
      "notification_policy": { "notify_on_complete": true },
      "metadata": { "purpose": "developer-smoke" }
    }
  }
}

Profiles are pure configuration: resolving them validates policy and produces a start request; it does not spawn a process, contact pueue/systemd, or write storage by itself. The focused drift rail is scripts/check-process-job-profile-kit.rs.