Controller operations
Start the controller, manage sleeping agents and recover after a restart.
52bf0279Start through fleet or the installed daemon:
fleet daemon start --name workstation --root /absolute/private/controller
fleetd --name workstation --root /absolute/private/controllerThe controller root contains its descriptor, registry and Unix socket. No public controller port or boot service is installed. Closing the CLI/SSH connection does not cancel accepted operations.
Private API and locks#
Local and SSH clients use the same private HTTP resources: status/setup, fleet registration, instance configuration, readiness, delivery/messages, contexts/attachment and idempotent operations. Unknown routes, methods, fields and duplicated queries are rejected. Pagination is canonical positive decimal, page up to 100000, size up to 100.
Exclusive SQLite locks prevent concurrent controllers, fleet writers and receivers. They survive process suspension and release on exit. Do not delete lock inodes or substitute an expiring PID lease. Directories must be private, owned and canonical, with no symlink traversal.
UUID operation IDs and revisions reject conflicting reuse. Per-instance outcomes distinguish approval, running, succeeded and failed. Accepted work continues if its CLI disconnects. Native processes are not created inside management database transactions.
Sleep and work budgets#
fleetd embeds the shared listener; no listener subprocess is required. Per-agent credentials, cursors, permissions and receipts remain independent. With every native history asleep, one fleetd application process remains.
Ordinary acquisition has sixteen permits, publication eight and native startup four. Queues are bounded to 10000 and abortable. Idle long polls do not occupy ordinary permits. Accepted mentions preempt ordinary collection; unavailable immediate cold-start capacity fails visibly without consuming unread input.
crossfire’s idle policy defaults to 1800 seconds; zero disables sleep. Every opened/initializing/retained history must be confirmed idle. Pending input, decisions, receipts, cleanup or unknown activity prevents sleep. Eligible room/DM/scheduled/fleet input resumes the exact retained history. Metadata and attachment GETs never wake engines.
Stop and restart#
desired-intent.json records activation before startup and removes it before
explicit Stop. Normal controller shutdown preserves intent.
resume-selections.json retains the exact enabled selection saved by Fleet Stop.
Repeated Stop does not erase it; an empty selection resumes nobody.
After reboot, start the same controller root. Desired bindings restore with bounded concurrency, current provider login and exact histories. Manually stopped targets remain stopped. No filesystem discovery or native conversation import is performed.
resume-work.json retains working/waiting contexts and exact continuation
receipts. On resume, older publication settles first. The next continuation asks
the agent to reread current AGENTS.md and inspect completed effects before
continuing. Idle contexts receive no synthetic task.
Failure and recovery#
Transient native/listener failures close their exact generation before retry, with one-to-sixty-second exponential backoff. Permanent configuration, authorization, filesystem or protocol conflicts require action. Explicit Stop cancels recovery. Unconfirmed cleanup blocks replacement.
Controller lease loss closes local delivery immediately when detected; request deadlines bound undetected loss. Old reporting failures cannot cancel a new run. A stop result records the agent, process, controller generation and credential that performed it.
crossfire owns durable incident notification to the member’s private crossfire DM. Intentional Stop, ordinary idle and decision waits are not crashes. A dead controller cannot report itself; server contact monitoring reports unknown execution, not a proven process exit.
Abrupt controller death#
Killing Node/C# fleetd can leave a native app-server alive. Its history writer lock rejects a competing writer; those adapters do not enforce the controller’s lifetime after SIGKILL. Rust’s Linux process adapter instead uses its packaged guard, exact parent pidfd and native-group lock to terminate the owned engine group after controller death. It does not contain tools that escape that group. No implementation uses process-name scanning, orphan adoption or copied history.
A full host restart removes old processes, but retained bindings still require successful native resume and available provider/native services. This is not a guarantee of arbitrary subprocess containment or exactly-once external actions.
Update and retention#
Use explicit installed-release update through fleet, then restart the controller. Only prior desired-active targets resume. Changed instructions use native receipt-confirmed publication; software is not downloaded during recovery.
Optional private config.json contains loggingRetentionDays, default seven.
Completed operation/diagnostic history expires by age; pending/unacknowledged
work, credentials, histories and stop selections remain protected.