Skip to content

feat(remote): status tells the truth about the engine; sync start brings it back - #564

Merged
fujibee merged 9 commits into
integration/remotefrom
feat/remote-status-liveness
Jul 31, 2026
Merged

feat(remote): status tells the truth about the engine; sync start brings it back#564
fujibee merged 9 commits into
integration/remotefrom
feat/remote-status-liveness

Conversation

@fujibee

@fujibee fujibee commented Jul 30, 2026

Copy link
Copy Markdown
Owner

The run-2 dogfood found status reporting connected while no sync engine existed — sends quietly piled up locally behind a green-looking status. The binding was the only thing checked; nothing verified a live engine.

remote.sh status now reports engine liveness alongside the binding, in both human and --json output:

  • running — pidfile PID is alive AND its cmdline is this team's engine (PID-reuse cannot fake it)
  • stopped — no pidfile
  • stale — pidfile points at a dead or foreign process

JSON adds engine_state and engine_pid only; existing fields and exit semantics are unchanged — status observes, it does not fail because the engine is down.

remote.sh sync start <team> is the public way back: starts from stopped or stale, no-ops with the PID when verifiably running, refuses an inactive binding, and never signals a foreign PID — a stale pidfile is replaced, not killed. The stopped-status hint points here. Root SKILL.md and all nine type templates follow.

Regressions run the round trip both ways: stopped → start → running, and dead/foreign-stale → start → running with the foreign process untouched.

PR opened on the author's behalf — their sandbox blocks GitHub access.

fujibee added 9 commits July 30, 2026 06:50
Remote status now distinguishes verified running engines, stopped engines,
and stale pidfile ownership. JSON callers receive additive engine state
and PID fields.

Add a public sync start command so stopped or stale engines can recover
without invoking internal scripts. Starting is idempotent for a verified
engine and never signals a foreign process behind a recycled PID.

Document the command across agent surfaces and cover stop, restart, stale
ownership, inactive bindings, and PID reuse.
Stop a pidfile owner only after its command line proves that it is the
engine for this team. A recycled PID that belongs to another process is
now left untouched while stale ownership is removed.

Hold the team lifecycle lock across sync-start validation, spawn, and
command-line readiness. Concurrent starts now converge on one verified
engine instead of racing two daemons into the same slot.
A spawned engine can remain alive without completing its capability handshake. Treat readiness as an explicit condition, and retain ownership until the failed child is confirmed dead.

Recheck command ownership before each signal, wait after TERM, escalate to KILL, and preserve the pidfile if cleanup cannot be proven. The regression fixture ignores TERM so the failure path must perform the full cleanup before releasing the team lock.
A shared team log can contain capability events from an older engine, so a log offset alone cannot prove that the newly spawned process completed startup. Pass a fresh nonce into the engine and require its capability event to echo that nonce.

Match the readiness deadline to the engine's network startup timeout, and make the TERM-resistant regression prove that the recorded child PID is gone before ownership is released.
A grep -q handshake can close a shared-log pipeline before upstream writers finish, turning a valid nonce match into a pipefail failure. Scan the complete log range in one awk process and decide only at EOF.

Exercise the boundary with a matching capability record followed by hundreds of records from another process generation.
A small trailing log can fit entirely in a platform pipe buffer, allowing the former grep -q pipeline to escape SIGPIPE by timing. Keep normal fixtures small, but add a dedicated handshake case with more than eight MiB of later capability records.

The volume exceeds common Linux and macOS pipe capacities while remaining redirected to the existing test log.
Log volume alone does not prove the old pipeline fails if readiness observes the matching line before the producer finishes. Keep the engine argv mismatched until the fixture atomically marks the complete multi-megabyte log durable.

Generate the trailing records in one awk process so the barrier publishes well inside the production startup budget.
…mote-status-liveness

# Conflicts:
#	scripts/remote.sh
…mote-status-liveness

# Conflicts:
#	scripts/remote.sh
@fujibee
fujibee merged commit 0290d2a into integration/remote Jul 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant