Proposal: Durable Tool Execution and Background Jobs v1
Status: Proposed Baseline: Meerkatdda5f2b2e; MobKit PR #301 at c2920a8a
Scope: Meerkat platform, MobKit gateway/SDKs, and downstream host-callback consumers such as HomeCore
Decision
Meerkat should support three first-class tool execution modes:- Fast: bounded synchronous completion.
- Streaming: synchronous completion with contractual progress and inactivity detection.
- Detached: a short durable submission followed by execution outside the agent turn.
shell(background: true) is asynchronous but volatile, so it does not satisfy the new definition.
The platform will introduce a feature-owned durable job authority. It will reuse the existing runtime completion-feed wake path, but it will not use runtime operations, WorkGraph, Schedule, or MobKit callbacks as the canonical execution store.
For HomeCore, the key outcome is:
A security scan is accepted durably within the MobKit callback deadline, runs outside the callback and agent turn, appears as healthy detached activity, re-resolves credentials at execution time, and becomesWorkerLost/NeedsAttentionrather than being blindly replayed after an unrecoverable restart.
1. Current state
Meerkat already has useful pieces:- Detached operations do not become turn barriers.
- Background shell returns a receipt promptly.
- Terminal background operations enter a monotonic completion feed.
- Idle keep-alive sessions are re-woken through the runtime-owned continuation path.
- WorkGraph provides durable commitments, dependencies, claims, and evidence.
- Schedule provides durable occurrence planning and redelivery.
- The rebased storage arc provides shared SQLite mechanics, realm path authority, schema ledgers, maintenance fencing, provider seams, and fail-closed durability.
JobManageris in-memory.- Runtime recovery explicitly discards non-terminal operations in
from_recovered. WorkItemhas no executable specification, attempts, fencing, checkpoint, result, or delivery state.- Schedule runnables are awaited in-process and do not own restart-safe execution.
- MobKit callback tools currently synchronously await
callback/call_tool.
shell_job_status, even though the recovered process has no matching JobManager record.
2. Goals
The design must provide:- Durable-before-receipt job submission.
- No provider turn or gateway callback held for the duration of detached work.
- Restart behavior defined per runner: adopt, resume, replay safely, or declare loss.
- Fenced worker attempts and renewable leases.
- Durable, bounded progress, artifacts, results, and cancellation.
- Replay-safe completion delivery through the existing runtime wake path.
- Stable submission identity across crash retries and completion-triggered agent retries.
- Execution-time credential resolution from the current authorized profile.
- Operator-visible distinction between healthy detached waiting and a wedged provider/callback.
- Optional WorkGraph and Schedule composition without making either executable.
- First-class participation in the new Meerkat/MobKit storage-provider architecture.
- Durable agent-authored monitors that can emit any number of conversation notifications without terminalizing the underlying job.
- Keeping an arbitrary Unix process alive across machine loss.
- Exactly-once external side effects without target-system cooperation.
- Treating streaming as a substitute for detached work.
- Making every detached job a WorkGraph item.
- Preserving an agent/provider turn for hours.
3. The actual timeout hierarchy
There is no single platform-wide tool timeout. The effective deadline is the narrowest applicable layer.
Therefore:
- A direct Meerkat tool may have up to its resolved core/tool deadline. SDK/builder paths that compose
ToolDispatcherhave an actual 30-second dispatcher contributor by default, so raising the outer 600-secondToolsConfigdeadline does not raise that narrower layer unless the host overrides the dispatcher timeout explicitly. The built-in shell timeout andToolDispatchertimeout are distinct enforced layers, even though both defaults currently come from the sameToolTimeoutPolicy. - A MobKit host-callback Fast tool must complete within the 120-second public contract. The 125/130-second layers are cancellation and transport margins, not extra user work time.
- Raising
ToolsConfigcannot make a MobKit callback run longer. - Detached submission must itself fit comfortably inside Fast. Proposed default submission deadline: 10 seconds, bounded above by the applicable Fast deadline.
4. Tool execution contract
4.1 Internal declaration
Add a core-owned internalToolExecutionContract to ToolCatalogEntry, not initially to provider-facing ToolDef.
Conceptually:
ExecutionPolicyGatedDispatcher, filtered dispatchers, composite dispatchers, MCP adapters, and MobKit callback dispatchers—must forward the complete execution-contract surface.
4.2 Pre-dispatch resolution
Static metadata alone is insufficient. The runtime needs:- Exact execution mode.
- Applicable deadline chain.
- Runner identity and version.
- Restart classification.
- Idempotency scope.
- Credential-context references.
- Output and progress policies.
WaitPolicy::Detached remains a post-dispatch barrier classification. It is not the declaration mechanism.
4.3 MobKit registration
MobKit’s callback-built tool specification currently carries only name, description, and input schema. Extend its private host/gateway contract with execution metadata:callback/call_tool and the 120/125/130-second hierarchy.
Detached callback tools do not execute their long work inside callback/call_tool.
5. Durable job authority
Introduce a feature-ownedmeerkat-jobs crate and a catalog-generated DetachedJobMachine.
5.1 Canonical job state
A durable job owns:JobId- Realm and origin session/member
- Interaction lineage and submission key
- Tool and runner identity/version
- Canonical argument/specification hash
- Credential-context references
- Restart classification
- Lifecycle phase
- Attempt counter
- Current worker and fenced lease
- Heartbeat and checkpoint references
- Progress cursor and artifact references
- Cancellation state
- Typed terminal result
- Completion-delivery outbox state
WorkerLost and NeedsAttention must be explicit typed outcomes, not error strings.
5.2 Machine inputs
The generated authority should own transitions such as:5.3 Attempts and fencing
Every attempt receives:- Unique attempt ID.
- Monotonically increasing fence token.
- Finite renewable lease.
- Worker identity.
- Heartbeat deadline.
DetachedJobMachine. Schedule, workers, callbacks, and WorkGraph must not introduce independent retry loops.
6. Persistence and storage-provider integration
The storage-unification work changes the correct integration point. Meerkat’sRealmStoreSet should gain:
jobs should become a required fail-closed durability domain alongside sessions, runtime, schedule, WorkGraph, blobs, and artifacts.
The built-in disk implementation should use:
- A canonical
jobs.sqlite3path owned byStorageLayout/RealmPaths. meerkat-sqlite’s Primary profile.- Schema-domain migrations.
- Per-operation maintenance guards.
- Doctor/migrate/prune participation.
- Store-conformance tests.
OperationGuard is only an offline-maintenance fence. It must not be confused with job-attempt fencing.
MobKit PR #301 composition
PR #301 introduces aMobKitStorageProvider that wraps the Meerkat RealmStorageProvider and supplies one composite backend.
Therefore:
- The job store belongs in the Meerkat-level provider set.
- A MobKit composite provider supplies it through
meerkat_provider(). - Do not add a second MobKit-owned semantic job store.
- PR #301’s storage census should include the inherited Meerkat
jobsdurability slot. - MobKit’s doctor/migration layer should inspect the canonical job database through the composed layout.
- External providers must supply the job store or fail startup/Detached admission typed.
7. Worker and restart semantics
Each runner declares one restart class:Adoptable
The actual work is owned by an external durable system with a stable handle. After restart, the worker reconnects and resumes observation.Checkpoint-resumable
The runner commits checkpoints and resumes a later attempt from the last accepted checkpoint.Replayable
The work is safe to run again under its stable idempotency key.Non-resumable
The work cannot be safely continued or replayed automatically. Worker loss producesWorkerLost/NeedsAttention.
HomeCore security scans should initially be Non-resumable:
- A rebooted scan is not silently replayed.
- The operator or agent can explicitly start a new scan.
- A future scan implementation may become Adoptable or Checkpoint-resumable without changing platform semantics.
For HomeCore v1, a detached scan running inside the co-deployed Python host
survives a gateway-only restart only when the host process and reconnectable
attempt handle remain alive. A routine upgrade that stops both host and gateway
loses a plain in-process Non-resumable scan. Surviving that topology requires a
future Adoptable implementation backed by an externally supervised process
with a stable handle, or an honest Checkpoint-resumable/Replayable runner; Phase
4 does not provide that property automatically.
Exactly-once side effects are only possible when the runner and external target honor an idempotency protocol.
8. MobKit detached host callbacks
Detached host tools need a separate asynchronous callback protocol.8.1 Submission
When the agent selects a Detached callback tool:- The gateway resolves the execution plan.
- It submits the job to
DetachedJobMachine. - The job specification commits durably.
- The gateway returns a
JobReceiptto the agent. - No long-running Python/TypeScript callback is open.
8.2 Host execution protocol
The gateway’s job worker asks the host to accept an attempt through a short callback, conceptually:job_id, attempt_id, and the current fence.
On reconnection, the gateway and host reconcile active attempts. The machine, not either side’s in-memory task map, decides whether an attempt is adoptable, resumable, replayable, or lost.
9. Credential handling
A durable job must never contain resolved secrets. The job stores only typed references such as:- Owning realm/profile.
- Required credential scopes.
- Auth binding names or profile-local binding references.
- Policy/config generation for audit.
- Non-secret runner configuration.
- Re-evaluate current authorization and tool policy.
- Resolve credentials from the current owning profile.
- Acquire the necessary credential lease.
- Execute using ephemeral secret material.
- Drop the material when the attempt ends.
BlockedCredentials or NeedsAttention. It must not fall back to ambient environment variables or stale serialized material.
For HomeCore, a network scan therefore re-resolves UniFi credentials from the network profile when the attempt actually starts.
10. Submission idempotency
session_id + provider tool-call ID is insufficient: a completion-triggered agent continuation may produce a new tool-call ID.
Introduce a runtime-minted durable ExecutionIntentId and an interaction lineage that survives continuation wakeups.
The canonical submission key should include:
JobId.
Required behavior:
- Crash after durable commit but before receipt: retry returns the original receipt.
- Replayed dispatch of the same tool call: returns the original receipt.
- Re-woken agent re-deriving the same scan within the same interaction lineage: returns the existing receipt.
- A genuinely new user request has a new interaction lineage and may create a new job.
- Tools needing stronger domain idempotency can provide a semantic key such as
security-scan:<target>:<policy-revision>:<intent>.
JobId, delivery identity, and interaction lineage rather than only a generic reason string. The full result remains in durable job/feed storage.
11. Completion and wake delivery
Job terminalization and runtime delivery cannot assume a cross-database atomic transaction. Use a job-owned outbox:- Commit the terminal result and an outbox entry atomically in the job store.
- A projector submits the entry through a runtime-owned durable delivery inbox; it must not write the in-memory completion feed directly.
- Runtime authority commits the stable delivery idempotency key before publishing the completion-feed projection.
- A duplicate projector submission therefore reuses the original runtime delivery/feed sequence rather than producing a second application.
- Only after the runtime durable insert succeeds may the projector record acknowledgement in the job store.
- Failed or unacknowledged delivery remains retryable.
- Runtime cursor logic prevents duplicate agent application.
Succeeded. Failed,
Cancelled, WorkerLost, and NeedsAttention commit their typed terminal
outbox entry atomically with terminal state. A configured agent subscription
therefore receives the failure/loss outcome through ordinary durable delivery
and its canonical comms HandlingMode; health/status is an additional operator
projection, not a substitute for telling the responsible agent that its work
was lost. Reopen or projector retry must neither suppress that terminal event
nor apply it twice.
The runtime inbox and its catalog-generated job/runtime delivery composition
ship with the Phase 2 foundation. The current operation completion feed is a
read-only, operation-specific projection and is not by itself a durable ingress
contract for jobs.
The existing runtime continues to own:
- Completion-feed consumption.
- Quiescence checks.
- Continuation injection.
- Agent wakeup.
- Typed transcript notice creation.
11.1 Non-terminal monitor notifications
A durable job may produce notification outbox entries before it terminalizes. Applying one of these entries wakes/notifies a subscribed session, but does not change the job phase, stop its worker, close its lease, or imply success. A monitor may therefore notify zero, one, or many times and continue running until it exits, explicitly completes, is cancelled, or reaches a typed failure. Each notification owns:- Stable
JobId, notification ID, attempt ID, and fence. - A job-monotonic notification sequence.
- A runner-provided idempotency key when the observed condition has a stable
identity, such as
github-release:meerkat-mobkit:v0.8.3. - Safe title/body data and optional artifact references.
- The interaction lineage and durable notification subscriptions to which it may be delivered.
- Delivery, acknowledgement, retry, and suppression state.
await_job. A conversation can
subscribe to monitor notifications without parking an agent turn, and a
monitor can continue after delivering a notification. Unsubscribing a
conversation does not cancel the job unless explicitly requested.
Every subscription declares a delivery kind:
record: retain the observation and advance its durable checkpoint without delivering ordinary work to a conversation.notification: apply a durable user-visible notification without opening a provider/agent turn. The notification remains available to later conversation context; it merely does not request immediate inference.event: inject ordinary content-bearing work through the existing runtime/comms ingress using the canonicalHandlingMode.
event delivery reuses the comms nomenclature and semantics exactly:
HandlingMode::Steerrequests injection at the earliest admissible cooperative boundary while remaining ordinary work, not an out-of-band control-plane command.HandlingMode::Queueleaves the current run untouched and delivers at the outer-loop/next-turn boundary.
Steer is the default handling mode for monitor events because a condition
selected for agent judgment is normally intended to affect current work.
Callers choose Queue explicitly when the event is important but must not
perturb the active run. The durable inbox retains either mode until its
runtime-owned admissible boundary; monitor code must not implement a separate
steer/queue fallback or scheduling path.
This preserves the design boundary between predicate detection and judgment.
Release/version changes, HTTP conditions, file changes, and numeric thresholds
can normally remain turn-free. Camera triage, ambiguous household events, and
other judgment-bearing decisions use the monitor only as the cheap predicate
and then select event delivery with the appropriate HandlingMode; the
monitor primitive must not replace the reasoning turn.
Monitor events use the existing comms content and rendering vocabulary,
including ContentInput, RenderMetadata, and RenderClass::ExternalEvent,
rather than defining parallel message, urgency, or presentation fields.
11.2 Agent-authored script monitors
Expose a first-class monitor runner/tool that lets an agent supply a custom script or command plus an explicit output protocol. It returns a durableJobId immediately and never keeps a provider turn or host callback open.
Two stdout protocols are required:
framed_jsonl(default): a line such as{"type":"notify","key":"release:v0.8.3","message":"..."}requests a durable notification. Ordinary stdout remains bounded diagnostic/progress output. Frames also supportcheckpoint,progress, and explicitcomplete; anotifyframe is non-terminal unless it separately requests completion.lines: every complete stdout line requests a notification. This provides the direct shell-monitor power of “print a line to ping the conversation,” but is opt-in because accidental noisy output can otherwise flood delivery.
- A Replayable monitor receives its stable submission key and latest durable checkpoint on every attempt and must tolerate polling the same condition again.
- A Checkpoint-resumable monitor resumes from the latest accepted checkpoint.
- An Adoptable monitor reconnects to an external durable watcher.
- A script that keeps essential deduplication state only in process memory is
Non-resumable and becomes
WorkerLost/NeedsAttentionafter worker loss.
rel_last. Recovery rehydrates
the latest committed checkpoint and current attempt authority; merely
reopening the runtime must not advance the fence or make a valid monitor
impossible to resume.
Scripts execute under an explicit sandbox/capability policy. Credentials are
resolved from authorized profile references on each attempt and are never
embedded in the job specification, checkpoint, event frames, logs, or
notification payloads.
The unrestricted script runner is a high-trust capability distinct from
broadly grantable first-class predicates. Durable background execution,
arbitrary shell, network/file access, and notification delivery form a powerful
combination and must be gated fail-closed through the ordinary execution
profile/capability policy.
11.3 Trigger authority and steady-state cost
First-class watches do not create an independent timer subsystem or one sleeping runtime task/thread per watch. Time-based evaluation composes the existing Schedule authority:12. Parking and observability
Detached launch and durable waiting are separate operations.12.1 Default behavior
A detached tool returns a receipt. The agent may continue working or end the turn. The job runs independently and completion notification remains enabled.12.2 Explicit awaiting
An explicitawait_job(job_id) records that the session/member is intentionally waiting for the job. It does not keep a provider call open.
The per-session wait binding belongs to MeerkatMachine; job completion belongs to DetachedJobMachine. A generated composition defines the handoff.
12.3 Member status
Do not addAwaitingDetached to MobMemberStatus; that enum describes member lifecycle.
Add a separate execution-activity projection:
idle or running; detached_jobs.active still exposes the job.
This distinguishes:
- Healthy parked work:
awaiting_detached, valid job, current worker lease or queued state. - Provider wedge:
calling_providerbeyond its watchdog/deadline. - Callback wedge: Fast callback beyond 120/125/130 seconds.
- Worker fault: expired job lease, missing runner, or blocked delivery.
12.4 Health surfaces
Awaiting a detached job is healthy and must not degrade liveness/readiness. MobKit should preserve probe compatibility:GET /healthzwith ordinary text negotiation continues returning200 ok.GET /healthzwithAccept: application/jsonreturns structured job/activity health.mobkit/status,mobkit/capabilities, runtime health, and console projections expose the full model.
- Job store unavailable.
- No eligible worker for a due job.
- Stale lease or heartbeat.
- Persistent completion-delivery backlog.
- Cancellation that cannot be acknowledged.
- Credentials blocked beyond policy threshold.
13. WorkGraph and Schedule composition
WorkGraph
WorkGraph remains the commitment authority:- A job may link to a
WorkItem. - Job progress can project references.
- Terminal artifacts can become evidence.
- WorkGraph closure follows its completion policy.
Schedule
Schedule owns when a submission becomes due. AHostRunnable used for long work should instead:
- Derive a stable submission key from
occurrence_id. - Submit or ensure the durable job.
- Return immediately after durable acceptance.
14. Public job surface
Expose a domain-handle API consistently through CLI, RPC/REST, MCP where appropriate, and MobKit SDKs:JobId, runner display name, status, progress, timestamps, restart class, and safe result summaries.
Worker IDs, raw fence tokens, secret references, and sensitive canonical arguments remain internal.
monitors/start is a convenience surface over durable job submission, not a
second lifecycle authority. It accepts the script/command, output protocol,
restart declaration, checkpoint policy, notification subscription, resource
limits, and optional terminal condition. jobs/cancel, jobs/get, and the
ordinary job health/status surfaces remain authoritative.
Likewise, a “watch registry” is a query/projection over durable jobs and their
subscriptions, not another mutable authority. Console/RPC views may expose
active watches, last committed observation, last notification, next scheduled
evaluation, source health, and delivery backlog without owning lifecycle state.
15. Immediate containment before the full system lands
Before durable execution ships:- Stop recovered shell completion notices from suggesting
shell_job_statuswhen no matching record exists. - State explicitly that current shell background jobs are process-local and volatile.
- Document the full timeout hierarchy, including MobKit’s 120/125/130-second callback tier.
- Add diagnostics that report the effective deadline and its winning owner.
- Refuse to describe current
background: trueas restart-surviving.
16. Delivery sequence
Phase 0 — Truth and containment
- Fix misleading recovered shell status guidance.
- Document timeout hierarchy.
- Add effective-deadline diagnostics.
- Inventory every dispatcher/wrapper and callback registration path.
Phase 1 — Execution contracts
- Add
ToolExecutionContract. - Add pre-dispatch plan resolution.
- Preserve provider-facing
ToolDef. - Extend MobKit callback tool registration metadata.
- Ratchet wrapper forwarding and mixed-batch behavior.
Phase 2 — Durable job foundation
- Add
DetachedJobMachine. - Add
meerkat-jobs. - Add
DetachedJobStoreto the Meerkat storage-provider set. - Integrate SQLite mechanics, path authority, doctor/migrate, and conformance.
- Add fenced attempts, leases, cancellation, progress, results, and terminal outbox.
- Generalize the job outbox and runtime inbox for idempotent non-terminal notification deliveries as well as terminal completion.
- Add the runtime-owned durable delivery inbox and generated job/runtime outbox-delivery composition before publishing job completions to the existing wake path.
- Add core status and health projections.
Phase 3 — Built-in shell migration
- Move background shell onto the durable job service.
- Split or resolve foreground versus detached shell behavior.
- Remove
JobManageras semantic authority. - Implement Adoptable/Replayable/Non-resumable classifications honestly.
- Add the agent-authored monitor runner/tool with framed JSONL and opt-in line-as-notification stdout protocols.
- Add first-class predicate watches composed through Schedule or durable push/event adapters; do not add a parallel timer/registry authority.
- Make notification emission non-terminal so a monitor can notify repeatedly while continuing to run.
- Add durable monitor checkpoints, subscriptions, cancellation, output bounds, flood/backpressure handling, and secret-redaction tests.
- Add
record,notification, andeventdelivery kinds. Event delivery reuses commsHandlingMode::{Steer, Queue}withSteeras the monitor default, so predicate evaluation consumes a provider turn only when ordinary agent work is explicitly requested. - Add fail-closed capability tiers separating broadly grantable predicates from unrestricted durable script execution.
Phase 4 — MobKit and HomeCore callbacks
- Implement async detached callback protocol.
- Add Python and TypeScript SDK support.
- Add execution-time profile credential resolution.
- Add stable interaction-lineage idempotency.
- Add
member_status,healthz, status, capabilities, and console projections. - Update PR #301’s provider census, doctor/migrate, and conformance coverage for the inherited jobs domain.
Phase 5 — Streaming tools
- Add typed progress sink and cancellation token to dispatch context.
- Reuse the newly landed LLM inactivity-watchdog pattern conceptually.
- Require declared Streaming implementations to provide liveness; fail registration closed if they cannot.
- Reset inactivity only on accepted progress frames.
- Retain a hard absolute ceiling.
Phase 6 — WorkGraph and Schedule composition
- Add typed job references and terminal evidence composition.
- Make scheduled long work enqueue jobs.
- Add explicit durable
await_jobcomposition.
17. Acceptance gates
The implementation is complete only when all of these hold:- Fast MobKit callbacks are documented and tested at 120-second public, 125-second host, and 130-second wire tiers.
- A detached submit commits before returning a receipt.
- A crash after commit but before receipt returns the same
JobIdon retry. - A completion-triggered agent retry cannot launch a second HomeCore scan for the same interaction intent.
- No provider turn or callback remains open while a detached job runs.
- A stale worker cannot report progress or terminalize after a newer fence.
- A non-resumable scan becomes
WorkerLost/NeedsAttentionafter worker loss and is never automatically replayed. - An adoptable or checkpointed runner resumes according to its declared contract.
- Credentials are re-resolved on every attempt and no secret bytes appear in job storage, logs, events, or artifacts.
- Terminal result plus outbox survives a crash before runtime-feed delivery.
- Duplicate outbox/feed delivery produces one agent-visible application.
member_statusdistinguishes awaiting-detached from provider/callback execution.healthzremains healthy while jobs are legitimately queued/running/awaited and degrades on stale workers or delivery failure.- Detached execution works with WorkGraph disabled.
- External storage providers must supply the jobs domain or fail closed.
- Schedule redelivery ensures one job per occurrence.
- Graceful shutdown stops claiming new work and reconciles leases without waiting for long jobs.
- Every dispatcher wrapper preserves execution contracts and resolution.
- Public
ToolDefserialization remains unchanged unless a separately versioned public contract explicitly adds execution metadata. - Machine schema, alphabet, composition, storage-conformance, and generated wire-schema ratchets remain green.
- Crash/reopen recovery rehydrates the latest committed attempt and fence without advancing either; an adoptable or checkpoint-resumable worker can resume from persisted authority, while a genuinely older writer is still rejected after an explicit later claim advances the fence.
- An agent-authored monitor script can emit a durable notification, continue running, emit a later notification, and terminalize only on its declared exit/completion policy or cancellation.
framed_jsonlnotification, progress, checkpoint, and completion frames are distinguished typed; a notification frame alone never completes the job.- Opt-in line mode turns each stdout line into a notification while stderr and bounded diagnostics cannot block the notification stream.
- Crash after notification outbox commit but before runtime delivery retries the notification, and crash after runtime inbox commit but before job acknowledgement does not create a duplicate conversation application.
- Monitor restart receives the latest committed checkpoint without advancing the attempt fence merely because the process/runtime reopened.
- Notification idempotency suppresses a replayed observation but still permits a later distinct observation from the same continuing monitor.
- Flood/rate-limit behavior is bounded, typed, observable, and recoverable; it neither silently drops events nor silently terminates the monitor.
- Cancelling or unsubscribing has distinct semantics: cancellation stops the durable job through machine authority, while unsubscribe only stops future delivery to that subscription.
- A
notificationpredicate crossing produces a durable user-visible notification without opening a provider turn;eventdelivery requests ordinary agent work only after the predicate has requested judgment. - Monitor event delivery uses the canonical comms
HandlingModeunchanged:Steertargets the earliest admissible cooperative boundary,Queuepreserves the current run for outer-loop/next-turn handling, andSteeris the explicit monitor default. - First-class time-based watches are driven by the existing Schedule authority, and push-capable sources use durable source cursors; no second timer or mutable watch-registry authority is introduced.
- Polling enforces minimum intervals, bounded concurrency, jitter, backoff, and per-source budgets, and exposes its steady-state load and failures through typed health.
- Native and host/domain sources advertise durability from their real dependency and restart contract. A host-dependent callback watcher cannot claim the same availability as a replayable stable-HTTP predicate.
- A restart test commits a baseline observation, kills the gateway during a later evaluation, reopens without advancing the fence, resumes from the committed checkpoint without re-notifying the baseline, emits exactly one notification for each of two later distinct observations, and continues monitoring afterward.
- Unavailable host-dependent sources degrade visibly and retry according to policy without losing the watch, fabricating progress, or spending an agent turn merely to rediscover source unavailability.
- The active-watch console/RPC registry is derived from durable jobs, checkpoints, subscriptions, Schedule state, and health; it cannot mutate lifecycle outside the job and Schedule authorities.
Failed,Cancelled,WorkerLost, andNeedsAttentionterminalize with the same atomic typed outbox protocol asSucceeded; a configured agent subscription receives the failure/loss exactly once according to its canonical commsHandlingMode, rather than discovering it only through health polling.- Restart acceptance covers the topology matrix explicitly: gateway-only
restart can reconcile an Adoptable worker with a stable live handle;
co-restarting a gateway and in-process Non-resumable worker produces
WorkerLost; and co-restart continuation is claimed only for an actual externally Adoptable, Checkpoint-resumable, or safely Replayable runner.
