feat(remote): status tells the truth about the engine; sync start brings it back - #564
Merged
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The run-2 dogfood found
statusreportingconnectedwhile 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 statusnow reports engine liveness alongside the binding, in both human and--jsonoutput:JSON adds
engine_stateandengine_pidonly; 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.