diff --git a/bin/backends/herdr.sh b/bin/backends/herdr.sh index 4045912885..f9264e7e59 100644 --- a/bin/backends/herdr.sh +++ b/bin/backends/herdr.sh @@ -2653,16 +2653,11 @@ fm_backend_herdr_expected_label_matches() { # [expected-label] # launch-grade fm_backend_herdr_server_ensure used to spawn new crewmates. # # Reading a pane or sending keys to it does not care how the server was -# launched - the pane already exists and the server is up. It only needs the -# server to be running and adapter-owned (this HOME's own certificate names the -# live pid), which fm_backend_herdr_server_adapter_owned proves without the -# closed-shell launch certification. This is what keeps peek/steer working when -# FirstMate itself runs INSIDE the herdr session it manages (HERDR_ENV=1): that -# server was not launched through the crewmate adapter's own closed-shell path, so -# closed_shell_environment_ready is false and the full ensure would try to -# restart+recertify - impossible while the session is occupied by live crewmates and -# FirstMate itself. The SPAWN path deliberately keeps the strict ensure so a new -# crewmate still launches only in a certified closed-shell server. +# launched - the pane already exists and the server is up. Native-agent +# production servers therefore need only report running, matching +# fm_backend_herdr_server_ensure after the native cutover. The explicit legacy +# certificate lab retains its adapter-ownership proof so that retired lifecycle +# remains testable without constraining ordinary read/steer. fm_backend_herdr_server_reachable_for_readsteer() { # local session=$1 running if fm_backend_herdr_test_hooks_enabled \ @@ -2672,6 +2667,9 @@ fm_backend_herdr_server_reachable_for_readsteer() { # running=$(fm_backend_herdr_cli "$session" status --json 2>/dev/null \ | fm_backend_herdr_control_jq -r '.server.running // false' 2>/dev/null) [ "$running" = true ] || return 1 + if ! fm_backend_herdr_server_certificate_required; then + return 0 + fi fm_backend_herdr_server_adapter_owned "$session" } @@ -3269,9 +3267,14 @@ fm_backend_herdr_events_capable() { # case "$protocol" in ''|*[!0-9]*) return 1 ;; esac [ "$protocol" -ge "$FM_BACKEND_HERDR_MIN_EVENTS_PROTOCOL" ] || return 1 schema=$(fm_backend_herdr_scrubbed_exec "$herdr_bin" api schema --json 2>/dev/null) || return 1 - printf '%s' "$schema" | fm_backend_herdr_control_grep -Fq 'events.subscribe' || return 1 - printf '%s' "$schema" | fm_backend_herdr_control_grep -Fq 'pane.agent_status_changed' || return 1 - return 0 + # Parse once and consume the complete schema. Early-exit grep -q pipelines + # close their input as soon as a match is found, which makes the upstream + # printf hit EPIPE and turns a real capability into a false negative whenever + # the caller inherits pipefail. + printf '%s' "$schema" | fm_backend_herdr_control_jq -e ' + any(.. | scalars; . == "events.subscribe") + and any(.. | scalars; . == "pane.agent_status_changed") + ' >/dev/null 2>&1 } # fm_backend_herdr_normalize_event: THE single normalize point (report section 5 diff --git a/bin/fm-ff-lib.sh b/bin/fm-ff-lib.sh index ae290020ca..3759d6ab4f 100644 --- a/bin/fm-ff-lib.sh +++ b/bin/fm-ff-lib.sh @@ -54,9 +54,16 @@ default_branch() { # section 8) still yields the true default-branch tip instead of propagating a # stray feature branch to the fleet. Echoes the commit SHA, or returns 1. primary_head_commit() { - local root=$1 default + local root=$1 default ref default=$(default_branch "$root") || return 1 - git -C "$root" rev-parse --verify --quiet "refs/heads/$default^{commit}" 2>/dev/null || return 1 + ref="refs/heads/$default" + if ! git -C "$root" show-ref --verify --quiet "$ref"; then + # CI-style and isolated worktree checkouts may intentionally omit the local + # default ref. Follow the resolved remote default instead of a detached PR + # merge commit or feature HEAD. + ref="refs/remotes/origin/$default" + fi + git -C "$root" rev-parse --verify --quiet "$ref^{commit}" 2>/dev/null || return 1 } resolve_path() { diff --git a/bin/fm-home-seed.sh b/bin/fm-home-seed.sh index eac1c90072..eb93b25e5f 100755 --- a/bin/fm-home-seed.sh +++ b/bin/fm-home-seed.sh @@ -55,6 +55,8 @@ CHECKOUT_LOCK_ROOT=$(fm_checkout_lock_root "$CHECKOUT_STATE_BASE") . "$SCRIPT_DIR/fm-account-routing-lib.sh" # shellcheck source=bin/fm-gate-refuse-lib.sh . "$SCRIPT_DIR/fm-gate-refuse-lib.sh" +# shellcheck source=bin/fm-tangle-lib.sh +. "$SCRIPT_DIR/fm-tangle-lib.sh" fm_refuse_if_gate_agent usage() { @@ -431,7 +433,7 @@ acquire_treehouse_home() { } ensure_home() { - local id=$1 requested=$2 home + local id=$1 requested=$2 home default default_ref default_tip source_origin if [ "$requested" = "-" ]; then home=$(acquire_treehouse_home "$id") verify_firstmate_home "$home" @@ -444,7 +446,25 @@ ensure_home() { [ -d "$home" ] || { echo "error: $home exists and is not a directory" >&2; return 1; } else mkdir -p "$(dirname "$home")" - git clone --quiet "$FM_ROOT" "$home" + default=$(fm_default_branch "$FM_ROOT") || { + echo "error: cannot determine the active firstmate home's default branch" >&2 + return 1 + } + default_ref="refs/remotes/origin/$default" + if ! git -C "$FM_ROOT" show-ref --verify --quiet "$default_ref"; then + default_ref="refs/heads/$default" + fi + default_tip=$(git -C "$FM_ROOT" rev-parse --verify "$default_ref^{commit}") || { + echo "error: cannot resolve the active firstmate home's default branch tip" >&2 + return 1 + } + git clone --quiet --no-checkout "$FM_ROOT" "$home" + git -C "$home" checkout --quiet -B "$default" "$default_tip" + git -C "$home" remote set-head origin "$default" + source_origin=$(git -C "$FM_ROOT" remote get-url origin 2>/dev/null || true) + if [ -n "$source_origin" ]; then + git -C "$home" remote set-url origin "$source_origin" + fi fi verify_firstmate_home "$home" } diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index cec185d8bb..dbc16ef7bd 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -177,6 +177,16 @@ spawn_managed_endpoint_state() { #