← Files Compound EngineeringARCHIVED FILE
skills/ce-pov/scripts/cross-model-pov.sh
47.2 KB · Oct 4, 2026 · 12:33 UTC
#!/usr/bin/env bash
# cross-model-pov.sh
#
# Runs one pre-sanctioned different-model route in a read-only, least-privilege
# process and writes its POV as JSON into the run dir.
# Every peer receives the canonical POV persona, schema, and a caller-prepared
# subject payload. The peer also receives the caller-declared repository read
# scope; private prompt/result scratch stays outside that repository.
#
# Independence is by PROVIDER, not CLI brand. A provider is reached by a ROUTE:
# its dedicated CLI, or (for the fixed grok-cursor / composer routes) cursor-agent. All
# peer runs on ONE model at HIGH reasoning (composer's
# -fast tier is its ceiling, an accepted exception).
#
# Usage:
# cross-model-pov.sh <host-serving-family> <fixed-route> <subject-payload> <run-dir>
#
# <host-serving-family>
# the peer-key of the host's OWN serving family, attested by
# the calling skill (it knows its harness). A peer-key, never
# a provider name: openai->codex, anthropic->claude,
# xai->grok, cursor/composer->composer.
# Used only to verify independence. `unknown` is allowed for an
# explicitly named peer, but its receipt remains unverified;
# automatic discovery must exclude it before calling this worker.
# <fixed-route> one host-resolved and pre-sanctioned route: codex, claude,
# grok-cli, grok-cursor, cursor, or composer. A route failure
# returns no artifact; only the host may disclose and retry a
# different recipient.
# <subject-payload> framed question plus any conversation-only subject material.
# Point to repository files instead of copying their contents;
# the peer grounds itself from the shared working tree.
# <run-dir> existing private dir outside the repository; output ->
# <run-dir>/pov-<target>.json, where <target> is the resolved
# <fixed-route> target (grok-cli/grok-cursor both collapse to
# grok) -- NOT the <host-serving-family> key.
#
# Test/introspection mode (no model call, no side effects):
# cross-model-pov.sh --emit-adapter <route>
# prints the exact argv the given route would run (route in:
# codex | claude | grok-cli | grok-cursor | cursor | composer). Both this mode and the
# live run build their argv from adapter_argv(), so the U7 route-safety test
# asserts on the same command string the peer actually runs.
#
# Self-locates its sibling reference files via BASH_SOURCE (NOT the CWD, which is
# the user's project on every host). The agent passes the values above.
#
# NON-BLOCKING BY DESIGN: every failure logs to stderr and exits 0 without an
# output file. The cross-model pass is additive and must never fail the POV;
# the caller detects success purely by the presence of the output file(s).
#
# DATA-EGRESS NOTE: this embeds the prepared subject payload into an external
# model CLI prompt. The caller must disclose its content scope and actual provider
# before launch; route receipts let it reconcile the fixed target afterward.
set -uo pipefail
# Survive SIGHUP when the orchestrator backgrounds this script and the parent
# shell exits (common on Cursor/Codex Bash tools). Without this, a detached
# codex process group can still write raw `-o` JSON while this script dies
# before normalize — leaving fold-in files without route/model receipts.
trap '' HUP
# Filled while a peer process group is live; TERM/INT handler (installed after
# reap() is defined) reaps it so an orchestrator kill cannot leave orphans.
ACTIVE_PEER_PID=""
PEER_WORKDIR=""
PROMPT_FILE=""
PEERLOG=""
PEERERR=""
RAW_OUT=""
RUN_SUCCEEDED=false
cleanup_private_scratch() {
[ -n "${PEER_WORKDIR:-}" ] && rm -rf "$PEER_WORKDIR"
PEER_WORKDIR=""
}
log() { printf '[cross-model-pov] %s\n' "$*" >&2; }
skip() { log "$*"; exit 0; } # non-blocking: announce reason, exit clean, no output
# --- model + reasoning per provider ----------------------------------------
# ONE model at HIGH reasoning per provider. Concrete IDs are the CURRENT instance of the tier principle
# and the single maintenance point when model families change.
M_CODEX="gpt-5.6-sol" # codex CLI (-c model_reasoning_effort="high")
M_CLAUDE="claude-opus-5" # claude CLI, Opus 5 (--effort high)
M_GROK="grok-4.6" # grok CLI (--effort high)
M_GROK_CURSOR="cursor-grok-4.6-high" # cursor-agent grok route (reasoning baked into id)
M_COMPOSER="composer-2.5-fast" # cursor-agent composer (no high tier; -fast is the ceiling)
# --- model-identity receipt (R7/R8) -----------------------------------------
# "Which model ran" is a claim that needs a serving-side receipt. Only the
# claude CLI reports one today: its JSON envelope carries a modelUsage object
# keyed by the full dated id that actually served the run. Match requested vs
# actual by expected family prefix, delimited on "-": the served id must equal
# the prefix or continue it with "-" (alias or undated id -> dated id counts
# as a match; a longer sibling such as claude-opus-50-* does not; never
# substring). Every other route records the literal
# "unverified" — never a fallback to the requested value. Keep this block byte-identical across
# ce-code-review and ce-doc-review (kernel parity).
expected_model_prefix() { # <requested-alias-or-id> -> expected served-id family prefix
case "$1" in
fable) printf 'claude-fable' ;;
opus) printf 'claude-opus' ;;
sonnet) printf 'claude-sonnet' ;;
haiku) printf 'claude-haiku' ;;
claude-*) printf '%s' "$1" ;;
esac
}
route_model() { # <route> -> the M_* constant that route requests
local target
target="$(route_target "$1")"
if [ -n "${CROSS_MODEL_MODEL_OVERRIDE:-}" ] &&
[ "${CROSS_MODEL_MODEL_OVERRIDE_TARGET:-}" = "$target" ] &&
[ "$target" != "cursor" ]; then
printf '%s' "$CROSS_MODEL_MODEL_OVERRIDE"
return 0
fi
case "$1" in
codex) printf '%s' "$M_CODEX" ;;
claude) printf '%s' "$M_CLAUDE" ;;
grok-cli) printf '%s' "$M_GROK" ;;
grok-cursor) printf '%s' "$M_GROK_CURSOR" ;;
cursor) printf 'auto' ;;
composer) printf '%s' "$M_COMPOSER" ;;
opencode) printf 'auto' ;;
esac
}
route_target() {
case "$1" in
codex|claude|cursor|composer) printf '%s' "$1" ;;
grok-cli|grok-cursor) printf 'grok' ;;
opencode) printf 'opencode' ;;
esac
}
route_harness() {
case "$1" in
codex) printf 'codex' ;;
claude) printf 'claude' ;;
grok-cli) printf 'grok' ;;
grok-cursor|cursor|composer) printf 'cursor-agent' ;;
opencode) printf 'opencode' ;;
esac
}
target_serving_family() {
case "$1" in
codex|claude|grok|composer) printf '%s' "$1" ;;
cursor) printf 'unknown' ;;
opencode) printf 'unknown' ;;
esac
}
MODEL_ACTUAL="unverified"
extract_model_receipt() { # <route>; reads the envelope in $PEERLOG, sets MODEL_ACTUAL
MODEL_ACTUAL="unverified"
[ "$1" = "claude" ] || return 0
local requested actual prefix matched envelope
requested="$(route_model claude)"
prefix="$(expected_model_prefix "$requested")"
# stream-json is NDJSON: modelUsage lives on the terminal type=result event
# (same pattern as elevation-dispatch). Buffered --output-format json is one
# object — whole-file jq still works when no result event exists.
envelope="$(grep -a '"type":"result"' "$PEERLOG" 2>/dev/null | tail -1 || true)"
# jq `keys` is sorted, so keys[0] is the alphabetically-first model, not
# necessarily the one that served the run (a multi-key envelope can also carry
# an auxiliary model's usage). Prefer a key matching the requested family's
# expected prefix; fall back to the first key only when none matches, and warn
# only then. A missing/unparseable envelope stays "unverified" (never the
# requested value).
matched=""
if [ -n "$prefix" ]; then
# first modelUsage key equal to, or delimited under, the expected prefix
# (jq-native, no external `head`: the route sandbox may not carry coreutils
# on PATH).
if [ -n "$envelope" ]; then
matched="$(printf '%s' "$envelope" | jq -r --arg p "$prefix" 'first((.modelUsage // {} | keys[] | select(. == $p or startswith($p + "-")))) // empty' 2>/dev/null)"
else
matched="$(jq -r --arg p "$prefix" 'first((.modelUsage // {} | keys[] | select(. == $p or startswith($p + "-")))) // empty' "$PEERLOG" 2>/dev/null)"
fi
fi
if [ -n "$matched" ]; then
MODEL_ACTUAL="$matched"
return 0
fi
if [ -n "$envelope" ]; then
actual="$(printf '%s' "$envelope" | jq -r '.modelUsage // empty | keys[0] // empty' 2>/dev/null)"
else
actual="$(jq -r '.modelUsage // empty | keys[0] // empty' "$PEERLOG" 2>/dev/null)"
fi
if [ -z "$actual" ]; then
log "model receipt absent/unparseable on claude route; recording unverified"
return 0
fi
MODEL_ACTUAL="$actual"
log "WARNING: model mismatch - requested $requested, backend served $actual; reconcile must surface this"
}
# --- adapter argv (single source of truth for route flags) -----------------
# Emits the CLI + flags one token per line. Read-only, no-prompt, least-privilege
# (web-only on claude/grok; read-only residual on codex/cursor-agent), and
# high-reasoning. PEER_WORKDIR / RAW_OUT / PROMPT_FILE / SCHEMA_REF are
# resolved by the caller (placeholders in --emit-adapter mode); PEER_WORKDIR is the
# per-peer empty cwd/workspace, kept separate from the shared fold-in dir RUN_DIR.
# Peer routes write to RAW_OUT only; the final fold-in file (OUT) is published after normalize so an orphaned
# peer process cannot leave an un-normalized return. NEVER emit: codex without
# `-s read-only`; grok `--always-approve` / `--permission-mode bypassPermissions`;
# cursor-agent `-f` / `--force` / `--yolo`.
adapter_argv() {
case "$1" in
codex)
printf '%s\0' codex --search exec - -C "$READ_ROOT" --skip-git-repo-check -s read-only \
-o "$RAW_OUT" -m "$(route_model codex)" -c 'model_reasoning_effort="high"' -c 'hide_agent_reasoning=false'
;;
claude)
# Keep project auto-discovery disabled while allowing only repository reads
# and bounded public web checks. Mutating tools, Bash, MCP, and subagents are
# absent from the allowlist.
# stream-json + --verbose for PEERLOG idle (#1270); schema still composes.
printf '%s\0' claude -p --model "$(route_model claude)" --effort high --permission-mode dontAsk \
--safe-mode --disable-slash-commands --tools Read,Glob,Grep,WebSearch,WebFetch \
--max-turns 15 --no-session-persistence --json-schema "$SCHEMA_REF" \
--output-format stream-json --verbose
;;
grok-cli)
# Schema forces buffered json — hard-only, no PEERLOG idle (#1270).
# --verbatim: without it grok offloads a large prompt to a session file and
# sends only a preview, spending scarce turns to re-read what it was given.
printf '%s\0' grok --prompt-file "$PROMPT_FILE" --verbatim --model "$(route_model grok-cli)" --effort high \
--cwd "$READ_ROOT" --permission-mode dontAsk \
--deny Edit --deny Write --deny Bash --deny Task --deny 'mcp__*' \
--no-subagents --max-turns 15 \
--json-schema "$SCHEMA_REF" --output-format json
;;
grok-cursor)
printf '%s\0' cursor-agent -p --model "$(route_model grok-cursor)" --mode ask --trust \
--sandbox enabled --workspace "$READ_ROOT" --output-format stream-json
;;
cursor)
printf '%s\0' cursor-agent -p --mode ask --trust \
--sandbox enabled --workspace "$READ_ROOT" --output-format stream-json
;;
composer)
printf '%s\0' cursor-agent -p --model "$(route_model composer)" --mode ask --trust \
--sandbox enabled --workspace "$READ_ROOT" --output-format stream-json
;;
opencode)
printf '%s\0' env 'OPENCODE_DISABLE_PROJECT_CONFIG=1' \
'OPENCODE_CONFIG_CONTENT={"permission":{"edit":"deny","bash":"deny","webfetch":"deny","task":"deny"}}' \
opencode run --dir "$READ_ROOT" --format json --file "$PROMPT_FILE"
printf '%s\0' "Follow the attached brief. Return only schema-shaped JSON."
_oc_model="$(route_model opencode)"
[ "$_oc_model" = "auto" ] || [ -z "$_oc_model" ] || printf '%s\0' --model "$_oc_model"
;;
*) return 1 ;;
esac
}
# The host may replace a stale concrete model only within the fixed route's
# target family. Values are passed as one argv token; they never enter eval.
# A codex id may carry the serving provider's own namespace (openai.gpt-...)
# when the CLI routes through a non-default model_provider.
apply_model_override() {
local route="$1" override="${CROSS_MODEL_MODEL_OVERRIDE:-}" override_target="${CROSS_MODEL_MODEL_OVERRIDE_TARGET:-}" target
[ -n "$override" ] || { [ -z "$override_target" ]; return; }
target="$(route_target "$route")" || return 1
[ "$override_target" = "$target" ] || return 1
[ "$target" != "cursor" ] || return 1
case "$route:$override" in
codex:gpt-*|codex:o[0-9]*|codex:*[./]gpt-*|codex:*[./]o[0-9]* ) ;;
claude:fable|claude:opus|claude:sonnet|claude:haiku|claude:claude-* ) ;;
grok-cli:grok-* ) ;;
grok-cursor:cursor-grok-* ) ;;
composer:composer-* ) ;;
opencode:*/* ) ;;
*) return 1 ;;
esac
}
# --- --emit-adapter <route>: print the argv, no model call, no side effects --
if [ "${1:-}" = "--emit-adapter" ]; then
PEER_WORKDIR="<peer-workdir>"
READ_ROOT="<read-root>"
RAW_OUT="<peer-workdir>/pov-<provider>.raw.json"
PROMPT_FILE="<prompt-file>"; SCHEMA_REF="<schema>"
route="${2:-}"
apply_model_override "$route" 2>/dev/null || { echo "model override '${CROSS_MODEL_MODEL_OVERRIDE:-}' not compatible with route '$route'" >&2; exit 2; }
# adapter_argv emits NUL-delimited argv (can't be captured in a shell var), so
# validate the route first, then render for humans with NUL -> space.
adapter_argv "$route" >/dev/null 2>&1 || { echo "unknown route '$route' (want codex|claude|grok-cli|grok-cursor|cursor|composer|opencode)" >&2; exit 2; }
adapter_argv "$route" | tr '\0' ' '; echo
exit 0
fi
HOST_PROVIDER="${1:-unknown}"
HOST_HARNESS="${CROSS_MODEL_HOST_HARNESS:-unknown}"
FIXED_ROUTE="${2:-}"
PAYLOAD_PATH="${3:-}"
RUN_DIR="${4:-}"
# --- validate inputs -------------------------------------------------------
[ -n "$PAYLOAD_PATH" ] && [ -f "$PAYLOAD_PATH" ] || skip "subject payload '${PAYLOAD_PATH:-<empty>}' not readable on disk; skipping"
READ_ROOT="${CROSS_MODEL_READ_ROOT:-$(pwd -P)}"
[ -d "$READ_ROOT" ] || skip "declared repository/read root '$READ_ROOT' is not a directory"
READ_ROOT="$(cd "$READ_ROOT" && pwd -P)" || skip "cannot resolve repository/read root '$READ_ROOT'"
if [ -n "${CROSS_MODEL_REPO_ROOT:-}" ]; then
REPO_ROOT="$CROSS_MODEL_REPO_ROOT"
elif command -v git >/dev/null 2>&1 && _git_root="$(git -C "$READ_ROOT" rev-parse --show-toplevel 2>/dev/null)"; then
REPO_ROOT="$_git_root"
else
REPO_ROOT="$(pwd -P)"
fi
[ -d "$REPO_ROOT" ] || skip "declared repository root '$REPO_ROOT' is not a directory"
REPO_ROOT="$(cd "$REPO_ROOT" && pwd -P)" || skip "cannot resolve repository root '$REPO_ROOT'"
case "$READ_ROOT/" in "$REPO_ROOT/"*) ;; *) skip "read root '$READ_ROOT' is outside repository root '$REPO_ROOT'" ;; esac
[ -n "$RUN_DIR" ] || skip "run-dir not given; skipping"
if [ -d "$RUN_DIR" ]; then
RUN_DIR_RESOLVED="$(cd "$RUN_DIR" && pwd -P)" || skip "cannot resolve run-dir '$RUN_DIR'"
else
RUN_PARENT="$(dirname "$RUN_DIR")"
RUN_BASENAME="$(basename "$RUN_DIR")"
[ -d "$RUN_PARENT" ] || skip "run-dir parent '$RUN_PARENT' is not a directory"
RUN_PARENT="$(cd "$RUN_PARENT" && pwd -P)" || skip "cannot resolve run-dir parent '$RUN_PARENT'"
RUN_DIR_RESOLVED="$RUN_PARENT/$RUN_BASENAME"
fi
case "$RUN_DIR_RESOLVED/" in "$REPO_ROOT/"*) skip "run-dir must be outside the repository" ;; esac
[ -d "$RUN_DIR_RESOLVED" ] || skip "run-dir '$RUN_DIR' must already exist"
RUN_DIR="$RUN_DIR_RESOLVED"
chmod 700 "$RUN_DIR" 2>/dev/null || skip "run-dir '$RUN_DIR' could not be made private"
command -v jq >/dev/null 2>&1 || skip "jq not installed; skipping"
INCLUDE_PATHS="${CROSS_MODEL_INCLUDE_PATHS:-}"
EXCLUDE_PATHS="${CROSS_MODEL_EXCLUDE_PATHS:-}"
case "$HOST_PROVIDER" in
codex|claude|grok|composer|unknown) ;;
*) skip "host serving family '$HOST_PROVIDER' invalid (want codex|claude|grok|composer|unknown)" ;;
esac
case "$HOST_HARNESS" in
codex|claude|grok|cursor|opencode|unknown) ;;
*) skip "host harness '$HOST_HARNESS' invalid (want codex|claude|grok|cursor|opencode|unknown)" ;;
esac
case "$FIXED_ROUTE" in
codex|claude|grok-cli|grok-cursor|cursor|composer|opencode) ;;
*) skip "unknown fixed route '${FIXED_ROUTE:-<empty>}'; host must resolve one route before egress" ;;
esac
TARGET="$(route_target "$FIXED_ROUTE")" || skip "unknown fixed route '${FIXED_ROUTE:-<empty>}'; host must resolve one route before egress"
apply_model_override "$FIXED_ROUTE" || skip "model override '${CROSS_MODEL_MODEL_OVERRIDE:-}' not compatible with route '$FIXED_ROUTE'"
# --- self-locate skill root + canonical sibling files ----------------------
SKILL_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" || skip "cannot resolve skill root; skipping"
PERSONA="$SKILL_ROOT/references/agents/pov-peer.md"
SCHEMA="$SKILL_ROOT/references/pov-schema.json"
[ -f "$PERSONA" ] || skip "persona brief not found at $PERSONA; skipping"
[ -f "$SCHEMA" ] || skip "POV schema not found at $SCHEMA; skipping"
SCHEMA_CONTENT="$(cat "$SCHEMA")" || skip "cannot read POV schema; skipping"
SCHEMA_REF="$SCHEMA_CONTENT" # adapter_argv references SCHEMA_REF for --json-schema routes
# --- validate the host-resolved fixed route and egress allowlist -------------
ALLOW="${CROSS_MODEL_PEERS:-}" # optional egress allowlist (R19)
in_csv() { case ",$2," in *",$1,"*) return 0 ;; *) return 1 ;; esac; }
# Require a usable POV, not merely valid JSON. Error envelopes and incomplete
# objects fail the fixed route and return control to the host without publishing
# a cross-check artifact.
pov_shaped() { # <file>: schema-shaped POV (finality is a separate gate)
[ -s "$1" ] && jq -e \
'(.voice|type)=="string" and (.voice|length)>0 and (.position|type)=="string" and (.position|length)>0 and (.reasoning|type)=="string" and (.reasoning|length)>0 and (.evidence|type)=="array" and all(.evidence[]; type=="string" and length>0) and (.external_check=="ran" or .external_check=="unavailable") and (.mode=="independent" or .mode=="skeptic") and (.movement=="initial" or .movement=="moved" or .movement=="held")' \
"$1" >/dev/null 2>&1
}
out_missing_or_invalid() { ! pov_shaped "$RAW_OUT"; }
# A usable position is a settled answer to the framed question. The peer
# declares that itself through the schema's required `final` boolean: a
# schema-shaped artifact whose `final` is not true is non-final (a placeholder
# emitted before the peer finished inspecting -- observed on grok-cli in the
# #1402 panel, where the model returned its final schema object on turn one)
# and must not be published as a peer voice. Finality lives in the owned output
# contract, never in a phrase list over model prose.
out_final() { [ -s "$RAW_OUT" ] && jq -e '.final == true' "$RAW_OUT" >/dev/null 2>&1; }
# Backward-compatible matrix: legacy `composer` continues to sanction Cursor as
# the Grok intermediary, while the distinct Cursor-default target requires the
# new `cursor` key. Composer itself remains sanctioned by `composer`.
route_allowlisted() {
[ -z "$ALLOW" ] && return 0
case "$1" in
codex|claude|grok-cli) in_csv "$(route_target "$1")" "$ALLOW" ;;
cursor) in_csv cursor "$ALLOW" ;;
composer) in_csv composer "$ALLOW" ;;
grok-cursor)
in_csv grok "$ALLOW" && { in_csv cursor "$ALLOW" || in_csv composer "$ALLOW"; }
;;
opencode) in_csv opencode "$ALLOW" ;;
*) return 1 ;;
esac
}
# Soft size gate: peer prompt embeds the full subject payload. Over-budget payloads skip
# cleanly (R11) rather than collapsing silently inside the provider context window.
MAX_PAYLOAD_CHARS="${CROSS_MODEL_MAX_PAYLOAD_CHARS:-200000}"
case "$MAX_PAYLOAD_CHARS" in ''|*[!0-9]*) MAX_PAYLOAD_CHARS=200000 ;; esac
PAYLOAD_CHARS="$(wc -c <"$PAYLOAD_PATH" | tr -d '[:space:]')"
if [ "$PAYLOAD_CHARS" -gt "$MAX_PAYLOAD_CHARS" ]; then
skip "subject payload is ${PAYLOAD_CHARS} bytes (limit ${MAX_PAYLOAD_CHARS}); skipping cross-model pass rather than truncating"
fi
# The Codex desktop app (Codex.app, or ChatGPT.app since the July 2026 merger)
# ships `codex` at Contents/Resources without linking it onto PATH (#1272).
# Append, never prepend, so a PATH-installed CLI stays authoritative.
# CROSS_MODEL_CODEX_APP_DIRS (colon-separated) overrides the probed dirs.
if ! command -v codex >/dev/null 2>&1; then
OLDIFS="$IFS"; IFS=':'
for d in ${CROSS_MODEL_CODEX_APP_DIRS-"${HOME:-}/Applications/ChatGPT.app/Contents/Resources:/Applications/ChatGPT.app/Contents/Resources:${HOME:-}/Applications/Codex.app/Contents/Resources:/Applications/Codex.app/Contents/Resources"}; do
if [ -n "$d" ] && [ -x "$d/codex" ]; then PATH="${PATH:+$PATH:}$d"; export PATH; break; fi
done
IFS="$OLDIFS"
fi
route_available() {
case "$1" in
codex) command -v codex >/dev/null 2>&1 ;;
claude) command -v claude >/dev/null 2>&1 ;;
grok-cli) command -v grok >/dev/null 2>&1 ;;
grok-cursor|cursor|composer) command -v cursor-agent >/dev/null 2>&1 ;;
opencode) command -v opencode >/dev/null 2>&1 ;;
*) return 1 ;;
esac
}
route_allowlisted "$FIXED_ROUTE" || skip "fixed route '$FIXED_ROUTE' is not fully sanctioned by CROSS_MODEL_PEERS; skipping before egress"
route_available "$FIXED_ROUTE" || skip "fixed route '$FIXED_ROUTE' is unavailable; host must disclose and choose any retry"
log "fixed cross-model POV route: target=$TARGET route=$FIXED_ROUTE (host $HOST_PROVIDER excluded)"
# --- compose the peer prompt from the canonical persona (single source) ----
# The payload is prepared by ce-pov and embeds the framed question plus any
# conversation-only subject material needed for this round. Repository evidence
# stays in the shared working tree for the peer to inspect directly.
SCRATCH_PARENT="${CROSS_MODEL_SCRATCH_PARENT:-${TMPDIR:-/tmp}}"
[ -d "$SCRATCH_PARENT" ] || mkdir -p "$SCRATCH_PARENT" 2>/dev/null || skip "private scratch parent '$SCRATCH_PARENT' unavailable"
SCRATCH_PARENT="$(cd "$SCRATCH_PARENT" && pwd -P)" || skip "cannot resolve private scratch parent"
case "$SCRATCH_PARENT/" in "$REPO_ROOT/"*) skip "private scratch parent must be outside the repository" ;; esac
if ! PEER_WORKDIR="$(mktemp -d "$SCRATCH_PARENT/xmodel-pov-peer-XXXXXX")"; then
skip "provider $TARGET workspace isolation unavailable; skipping provider"
fi
chmod 700 "$PEER_WORKDIR" 2>/dev/null || { cleanup_private_scratch; skip "cannot make peer scratch private"; }
PROMPT_FILE="$PEER_WORKDIR/prompt.md"
PEERLOG="$PEER_WORKDIR/stdout.log"
# Peer stderr goes to its own file, NOT merged into PEERLOG: PEERLOG must stay
# clean stdout for the POV brace-match and the receipt jq-parse. An
# auth/quota/rate-limit message often lands on stderr, so capture it separately
# and surface it in the skip evidence (grok's 402 is on stdout, others on stderr).
PEERERR="$PEER_WORKDIR/stderr.log"
RAW_OUT="$PEER_WORKDIR/pov-$TARGET.raw.json"
: > "$PROMPT_FILE"; : > "$PEERLOG"; : > "$PEERERR"
chmod 600 "$PROMPT_FILE" "$PEERLOG" "$PEERERR" 2>/dev/null || { cleanup_private_scratch; skip "cannot make peer scratch files private"; }
trap 'cleanup_private_scratch' EXIT
{
cat "$PERSONA"
printf '\n\n---\n\n'
printf 'This is an authorized, read-only point-of-view cross-check on the maintainer\047s own project.\n'
printf 'Return ONE JSON object and nothing else (no prose, no code fence) matching this schema:\n\n'
printf '%s' "$SCHEMA_CONTENT"
printf '\n\nSet the top-level "voice" field to "peer" (it will be namespaced to the provider on fold-in).\n'
printf '\n<repository-read-scope enforcement="cooperative-unless-adapter-supported">\n'
printf 'root: %s\nincludes: %s\nexcludes: %s\n' "$READ_ROOT" "${INCLUDE_PATHS:-<all>}" "${EXCLUDE_PATHS:-<none>}"
printf '</repository-read-scope>\n'
printf '\n<subject-payload>\n'
cat "$PAYLOAD_PATH"
printf '\n</subject-payload>\n'
} > "$PROMPT_FILE"
# --- run machinery: idle-timeout for streaming peers, hard-only for grok-cli --
# On idle-guarded routes the idle cap is the liveness guard and HARD_SECS only
# backstops a peer that stays productive past any useful budget. Claude and
# cursor-agent stream (`stream-json`) so run_timeout_cmd polls PEERLOG (#1270).
# grok-cli keeps --json-schema (buffered) and stays hard-only on
# UNGUARDED_HARD_SECS. This skill's default HARD_SECS stays at 600s because its
# codex route runs the lower sol/high tier -- ce-code-review and ce-doc-review
# run luna/xhigh and default higher. `CROSS_MODEL_HARD_SECS` is shared across
# all three, and the orchestrator's aggregate deadline derives from it (see
# references/cross-model-panel.md), so a raised knob raises both windows.
IDLE_SECS="${CROSS_MODEL_IDLE_SECS:-180}"
HARD_SECS="${CROSS_MODEL_HARD_SECS:-600}"
UNGUARDED_HARD_SECS="${CROSS_MODEL_HARD_SECS:-600}"
RETRY_MIN_SECS="${CROSS_MODEL_RETRY_MIN_SECS:-60}" # least window worth spending on a non-final retry
TO_BIN="$(command -v gtimeout || command -v timeout || true)"
# Reap a backgrounded job's whole process group: TERM, then KILL after a grace.
# True while $1 is a live (non-zombie) process. kill -0 succeeds on zombies
# until wait reaps them, so idle polls must not treat zombies as still running.
# macOS/BSD often report defunct state as "Z+" (not bare "Z").
# Match peer-job-runner._pid_running: empty state after ps means not alive
# (avoids zombie spin). Fall back to kill -0 only when ps itself is missing.
peer_alive() {
local st
kill -0 "$1" 2>/dev/null || return 1
if ! command -v ps >/dev/null 2>&1; then
return 0
fi
st="$(ps -o state= -p "$1" 2>/dev/null | tr -d ' \n')"
[ -n "$st" ] || return 1
[ "${st#Z}" = "$st" ]
}
reap() {
# Signal the process group and grace-poll without wait(). The caller alone
# wait()s the leader so RUN_SUCCEEDED reflects the real exit status — a second
# wait here would fail after we already reaped and mark healthy exits as
# timed-out (#1270 Bugbot). No background KILL timer: orphaned timers can
# hit recycled PIDs under bun --parallel.
local pid="$1" grp
if kill -TERM -- -"$pid" 2>/dev/null; then grp=1; else kill -TERM "$pid" 2>/dev/null || true; grp=0; fi
for _ in 1 2 3 4 5; do
if ! peer_alive "$pid"; then
# Leader exited/zombied — sweep any group survivors; caller wait()s.
[ "$grp" = 1 ] && kill -KILL -- -"$pid" 2>/dev/null || true
return 0
fi
sleep 1
done
if [ "$grp" = 1 ]; then kill -KILL -- -"$pid" 2>/dev/null; else kill -KILL "$pid" 2>/dev/null; fi
}
# TERM/INT: reap the live peer group, then exit cleanly (HUP remains ignored).
on_term() {
if [ -n "${_HEARTBEAT_PID:-}" ]; then
stop_heartbeat
fi
if [ -n "${ACTIVE_PEER_PID:-}" ]; then
log "received TERM/INT; reaping peer process group $ACTIVE_PEER_PID"
_term_peer="$ACTIVE_PEER_PID"
reap "$_term_peer" 2>/dev/null || true
# reap only signals the group; wait reaps the leader so it cannot orphan.
wait "$_term_peer" 2>/dev/null || true
ACTIVE_PEER_PID=""
fi
exit 0
}
trap 'on_term' TERM INT
# Build the CMD array for a route (bash 3.2-safe: no mapfile).
build_cmd() {
CMD=()
# NUL-delimited so a token containing newlines (the pretty-printed --json-schema
# value) stays ONE argv element instead of splitting across lines.
while IFS= read -r -d '' tok; do CMD+=("$tok"); done < <(adapter_argv "$1")
}
# --- liveness heartbeat -----------------------------------------------------
# The peer CLI streams into $PEERLOG (private), so nothing reaches this script's
# own stdout/stderr during a long model call. An outer supervisor that watches
# THIS process's output for liveness (the peer-job runner's out.log byte-growth
# idle window) would mistake a healthy multi-minute run for a wedge. A background
# writer emits one stderr line every CROSS_MODEL_HEARTBEAT_SECS (default 60s) so
# that liveness is visible; it is torn down as soon as the foreground wait returns,
# so it adds no latency to a fast run. Keep this block byte-identical across
# the peer worker scripts (lifecycle parity).
_HEARTBEAT_PID=""
start_heartbeat() {
local every="${CROSS_MODEL_HEARTBEAT_SECS:-60}" parent_pid="$$"
# Floor to 1s: a non-numeric or 0 value would make `sleep` return instantly and
# spin the loop, flooding out.log into the runner's byte cap.
case "$every" in ''|*[!0-9]*) every=60 ;; esac; [ "$every" -lt 1 ] && every=1
_HEARTBEAT_READY=0
trap '_HEARTBEAT_READY=1' USR1
# Callers restore set +m after launching the peer, so without this the
# heartbeat inherits the worker pgid and kill -- -PID cannot reach the sleep.
local prev_m; case "$-" in *m*) prev_m=1;; *) prev_m=0;; esac
set -m
( local t0 n sleeper=""
trap 'kill "${sleeper:-}" 2>/dev/null || true; exit 0' TERM INT
kill -USR1 "$parent_pid"
t0="$(date +%s)"
while kill -0 "$parent_pid" 2>/dev/null; do
sleep "$every" & sleeper=$!
wait "$sleeper" 2>/dev/null || exit 0
sleeper=""
kill -0 "$parent_pid" 2>/dev/null || break
n="$(date +%s)"; log "peer alive ($(( n - t0 ))s elapsed)"
done ) &
_HEARTBEAT_PID=$!
[ "$prev_m" = 0 ] && set +m
while [ "$_HEARTBEAT_READY" != 1 ] && kill -0 "$_HEARTBEAT_PID" 2>/dev/null; do sleep 0.01 || true; done
trap - USR1
}
stop_heartbeat() {
if [ -n "$_HEARTBEAT_PID" ]; then
# Leader-only TERM is deferred until the inner `wait $sleeper` returns, so
# the default 60s interval would block this wait. Signal the process group.
kill -- -"$_HEARTBEAT_PID" 2>/dev/null || kill "$_HEARTBEAT_PID" 2>/dev/null || true
wait "$_HEARTBEAT_PID" 2>/dev/null || true
fi
_HEARTBEAT_PID=""
}
run_codex_cmd() { # CMD already built for the codex route; streams to PEERLOG, writes -o RAW_OUT
RUN_SUCCEEDED=false
local prev; case "$-" in *m*) prev=1;; *) prev=0;; esac
set -m
"${CMD[@]}" < "$PROMPT_FILE" > "$PEERLOG" 2>&1 &
local pid=$!
ACTIVE_PEER_PID="$pid"
[ "$prev" = 0 ] && set +m
start_heartbeat
local start last=-1 lastchg now size
start="$(date +%s)"; lastchg="$start"
while peer_alive "$pid"; do
now="$(date +%s)"; size="$(wc -c <"$PEERLOG" 2>/dev/null || echo 0)"
[ "$size" != "$last" ] && { last="$size"; lastchg="$now"; }
if [ $(( now - lastchg )) -ge "$IDLE_SECS" ]; then
log "codex output idle ${IDLE_SECS}s; reaping peer process group"; reap "$pid"; break
fi
if [ $(( now - start )) -ge "$HARD_SECS" ]; then
log "codex exceeded hard cap ${HARD_SECS}s; reaping peer process group"; reap "$pid"; break
fi
# 1s slices so a finished peer is noticed promptly (was sleep-5-first, which
# added up to 5s after every short stub / healthy exit).
sleep 1
done
if wait "$pid" 2>/dev/null; then RUN_SUCCEEDED=true
else log "peer exited non-zero or timed out"; fi
# Sweep any survivor the provider left in its OWN process group. `set -m` puts
# the provider in a separate pgid, and on a clean worker exit the runner's
# final sweep only kills the worker's pgid while a group-orphan reparents off
# the worker's process tree -- so it must be reaped here, where the pgid is
# known. reap() returns immediately when the group is already empty.
reap "$pid" 2>/dev/null || true
stop_heartbeat
ACTIVE_PEER_PID=""
}
run_timeout_cmd() {
# $1 = stdin file ("" -> /dev/null). $2 = hard cap secs. $3 = "idle" | "no-idle".
RUN_SUCCEEDED=false
# Run from the declared read root. Private prompt/output paths are absolute and
# remain outside the repository; route adapters separately carry the same root.
local stdin_file="${1:-}"; [ -n "$stdin_file" ] || stdin_file=/dev/null
local hard_cap="${2:-$HARD_SECS}"
local idle_mode="${3:-idle}"
local prev; case "$-" in *m*) prev=1;; *) prev=0;; esac
set -m
if [ "$idle_mode" = "idle" ]; then
( cd "$READ_ROOT" && exec "${CMD[@]}" ) < "$stdin_file" > "$PEERLOG" 2>"$PEERERR" &
elif [ -n "$TO_BIN" ]; then
( cd "$READ_ROOT" && exec "$TO_BIN" -k 10 "$hard_cap" "${CMD[@]}" ) < "$stdin_file" > "$PEERLOG" 2>"$PEERERR" &
else
( cd "$READ_ROOT" && exec perl -e 'alarm shift; exec @ARGV' "$hard_cap" "${CMD[@]}" ) < "$stdin_file" > "$PEERLOG" 2>"$PEERERR" &
fi
local pid=$!
ACTIVE_PEER_PID="$pid"
[ "$prev" = 0 ] && set +m
start_heartbeat
if [ "$idle_mode" = "idle" ]; then
local start last=-1 lastchg now size
start="$(date +%s)"; lastchg="$start"
while peer_alive "$pid"; do
now="$(date +%s)"; size="$(wc -c <"$PEERLOG" 2>/dev/null || echo 0)"
[ "$size" != "$last" ] && { last="$size"; lastchg="$now"; }
if [ $(( now - lastchg )) -ge "$IDLE_SECS" ]; then
log "peer output idle ${IDLE_SECS}s; reaping peer process group"; reap "$pid"; break
fi
if [ $(( now - start )) -ge "$hard_cap" ]; then
log "peer exceeded hard cap ${hard_cap}s; reaping peer process group"; reap "$pid"; break
fi
sleep 1
done
fi
if wait "$pid" 2>/dev/null; then RUN_SUCCEEDED=true
else log "peer exited non-zero or timed out"; fi
reap "$pid" 2>/dev/null || true # sweep survivors in the provider's own group (see run_codex_cmd)
stop_heartbeat
ACTIVE_PEER_PID=""
}
# Recover a POV object from raw stdout or from a string nested in a CLI envelope.
recover_pov_json() { # <logfile> <outfile>
# Probe execution, not just PATH presence — Windows Store's python3 stub
# satisfies `command -v` then exits nonzero (see resolve-python convention).
local py
py="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"
[ -n "$py" ] || return 1
"$py" - "$1" "$2" <<'PY' 2>/dev/null
import sys, json
txt = open(sys.argv[1], encoding="utf-8", errors="replace").read()
best = None
best_score = -1
decoder = json.JSONDecoder()
def shaped(d):
# Mirror of pov_shaped() in the shell: the same field types and enums,
# so ranking cannot promote a fully keyed but invalid draft.
return (
isinstance(d.get("voice"), str) and d["voice"] != ""
and isinstance(d.get("position"), str) and d["position"] != ""
and isinstance(d.get("reasoning"), str) and d["reasoning"] != ""
and isinstance(d.get("evidence"), list)
and all(isinstance(e, str) and e != "" for e in d["evidence"])
and d.get("external_check") in ("ran", "unavailable")
and d.get("mode") in ("independent", "skeptic")
and d.get("movement") in ("initial", "moved", "held")
)
def score(d):
# Prefer a schema-shaped final POV over a shaped non-final one over any
# dict that merely carries a position; ties go to the later candidate.
if shaped(d) and d.get("final") is True:
return 2
if shaped(d):
return 1
return 0
def inspect(value):
global best, best_score
if isinstance(value, dict):
if "position" in value:
sc = score(value)
if sc >= best_score:
best, best_score = value, sc
for child in value.values():
inspect(child)
elif isinstance(value, list):
for child in value:
inspect(child)
elif isinstance(value, str):
for i, ch in enumerate(value):
if ch not in "{[":
continue
try:
child, _ = decoder.raw_decode(value, i)
inspect(child)
except Exception:
pass
inspect(txt)
if best is not None: open(sys.argv[2], "w").write(json.dumps(best))
PY
[ -s "$2" ]
}
# Parse a schema-shaped object out of a headless CLI JSON envelope (claude/grok/cursor).
# The published candidate is the highest-scoring POV anywhere in the envelope --
# schema-shaped and final, then shaped, then any position-bearing object -- with
# ties to the later candidate. A structured field (structured_output /
# structuredOutput / result) is one candidate among those, not an authority:
# grok >= 1.0.4 names it structuredOutput and its text can carry a first-turn
# placeholder beside the settled object, a bare stub beside a shaped answer,
# or a bare {"final":true} beside the real POV. Take the structured field first
# only as a shortcut when it already scores top; otherwise the scored scan
# over the whole envelope decides.
pov_score() { # <file> -> 2 shaped+final, 1 shaped, 0 otherwise
if pov_shaped "$1"; then
if jq -e '.final == true' "$1" >/dev/null 2>&1; then echo 2; else echo 1; fi
else echo 0; fi
}
parse_structured() { # <logfile> <outfile>
local picked=false
# Buffered single-object envelopes (grok-cli json, test stubs).
if jq -e '.structured_output // .structuredOutput' "$1" > "$2" 2>/dev/null; then picked=true
elif jq -r '.result // empty' "$1" 2>/dev/null | jq -e '.' > "$2" 2>/dev/null; then picked=true
else
# stream-json NDJSON: last type=result event (elevation-dispatch pattern).
local event
event="$(grep -a '"type":"result"' "$1" 2>/dev/null | tail -1 || true)"
if [ -n "$event" ]; then
if printf '%s' "$event" | jq -e '.structured_output // .structuredOutput' > "$2" 2>/dev/null; then picked=true
elif printf '%s' "$event" | jq -r '.result // empty' 2>/dev/null | jq -e '.' > "$2" 2>/dev/null; then picked=true
fi
fi
fi
if [ "$picked" = true ] && [ "$(pov_score "$2")" = 2 ]; then return 0; fi
local scan="$2.scan"
if recover_pov_json "$1" "$scan"; then
if [ "$picked" != true ] || [ "$(pov_score "$scan")" -ge "$(pov_score "$2")" ]; then
mv "$scan" "$2"; return 0
fi
fi
rm -f "$scan"
[ "$picked" = true ]
}
parse_opencode_events() { # <logfile> <outfile>
local text tmp
text="$(jq -rs '[.[] | select(.type=="text") | (.part.text // empty)] | join("")' "$1" 2>/dev/null)" || text=""
[ -n "$text" ] || return 1
printf '%s' "$text" | jq -e '.' > "$2" 2>/dev/null && return 0
tmp="$(mktemp "${TMPDIR:-/tmp}/ce-opencode-text-XXXXXX")" || return 1
printf '%s' "$text" > "$tmp"
recover_pov_json "$tmp" "$2"
local st=$?
rm -f "$tmp"
return "$st"
}
bounded_failure_evidence() { # <logfile>; prefer structured diagnostics, then bounded head+tail
local path="$1" human ancillary evidence
human="$(jq -r '
[
(.result? | select(type == "string" and length > 0)),
(.message? | select(type == "string" and length > 0)),
(.error?.message? | select(type == "string" and length > 0))
] | unique | join(" | ")
' "$path" 2>/dev/null)"
ancillary="$(jq -r '
[
(if .api_error_status? != null then "api_error_status=\(.api_error_status)" else empty end),
(.terminal_reason? | select(type == "string" and length > 0) | "terminal_reason=" + .)
] | unique | join(" | ")
' "$path" 2>/dev/null)"
# Ancillary fields describe the exit but are not the diagnostic itself. If
# no recognized human-readable field exists, retain bounded raw output so a
# CLI's newer or provider-specific error field is still visible.
[ -n "$human" ] && evidence="$human" || evidence="$(cat "$path")"
[ -n "$ancillary" ] && evidence="${evidence:+$evidence | }$ancillary"
evidence="${evidence//$'\n'/ }"
if [ "${#evidence}" -gt 300 ]; then
evidence="${evidence:0:147} ... ${evidence: -147}"
fi
printf '%s' "$evidence"
}
# Run one route for a provider; leaves a schema-shaped (pre-normalization) $RAW_OUT on success.
attempt_route() { # <provider> <route>
local provider="$1" route="$2" note
: > "$PEERLOG"; : > "$PEERERR"; rm -f "$RAW_OUT" "$OUT"
build_cmd "$route"
case "$route" in
codex) note="$(route_model codex) (effort high)" ;;
claude) note="$(route_model claude) (effort high)" ;;
grok-cli) note="$(route_model grok-cli) (effort high)" ;;
grok-cursor) note="$(route_model grok-cursor)" ;;
cursor) note="auto (serving model unverified)" ;;
composer) note="$(route_model composer)" ;;
opencode) note="auto (serving model unverified)" ;;
esac
log "peer run: provider=$provider route=$route model=$note POV read-only least-privilege (idle ${IDLE_SECS}s / hard ${HARD_SECS}s; grok-cli hard-only ${UNGUARDED_HARD_SECS}s)"
case "$route" in
codex)
run_codex_cmd
if [ "$RUN_SUCCEEDED" = true ] && out_missing_or_invalid; then
recover_pov_json "$PEERLOG" "$RAW_OUT" && log "recovered codex JSON from stdout (-o file unavailable)"
fi
;;
grok-cli) run_timeout_cmd "" "$UNGUARDED_HARD_SECS" no-idle
[ "$RUN_SUCCEEDED" = true ] && parse_structured "$PEERLOG" "$RAW_OUT" ;; # grok reads --prompt-file
claude) run_timeout_cmd "$PROMPT_FILE" "$HARD_SECS" idle
[ "$RUN_SUCCEEDED" = true ] && parse_structured "$PEERLOG" "$RAW_OUT" ;; # claude -p reads stdin
grok-cursor|cursor|composer)
# cursor-agent reads the prompt from stdin (verified). Use stdin, NOT a
# positional argv token: the composed prompt (persona + schema + template +
# full subject payload, up to CROSS_MODEL_MAX_PAYLOAD_CHARS) can exceed ARG_MAX and fail
# the exec with E2BIG on low-limit hosts, whereas stdin has no size limit.
run_timeout_cmd "$PROMPT_FILE" "$HARD_SECS" idle
[ "$RUN_SUCCEEDED" = true ] && parse_structured "$PEERLOG" "$RAW_OUT" ;;
opencode) run_timeout_cmd "" "$HARD_SECS" idle
[ "$RUN_SUCCEEDED" = true ] && parse_opencode_events "$PEERLOG" "$RAW_OUT" ;;
esac
if [ "$RUN_SUCCEEDED" != true ]; then
rm -f "$RAW_OUT"
return 0
fi
# Extract the served-model receipt from the envelope while $PEERLOG still
# holds it — normalization below only sees the schema-extracted RAW_OUT.
extract_model_receipt "$route"
}
# Run the one fixed route. Any failure returns control to the host without
# trying a different target, provider, or intermediary.
run_fixed_route() {
local provider="$TARGET"
OUT="$RUN_DIR/pov-$provider.json"
ACTUAL_ROUTE="$FIXED_ROUTE"
ROUTE_STARTED_AT="$(date +%s)"
attempt_route "$provider" "$FIXED_ROUTE"
# One bounded retry on the same route, target, model, and scope; the only
# change is a final-answer instruction. The retry gets only what is left of
# this worker's HARD_SECS window so both attempts stay inside the panel's
# aggregate deadline (cross-model-panel.md: CROSS_MODEL_HARD_SECS + 10s);
# too little left means no retry. A second non-final position drops the
# voice with skip evidence -- no route hopping.
nonfinal_position=""
if [ "$RUN_SUCCEEDED" = true ] && ! out_missing_or_invalid && ! out_final; then
position="$(jq -r '.position' "$RAW_OUT" 2>/dev/null)"
remaining=$(( HARD_SECS - ( $(date +%s) - ROUTE_STARTED_AT ) ))
if [ "$remaining" -lt "$RETRY_MIN_SECS" ]; then
log "peer returned a non-final position (\"${position:0:120}\") with ${remaining}s of the ${HARD_SECS}s window left; not retrying"
nonfinal_position="$position"
rm -f "$RAW_OUT"
else
log "peer returned a non-final position (\"${position:0:120}\"); retrying once on the same route with a final-answer requirement (${remaining}s left)"
printf '\n\nYour previous response set final to false. This response is the final one: inspect the subject and shared working tree now, then return the settled position with its evidence and final set to true.\n' >> "$PROMPT_FILE"
HARD_SECS="$remaining"; UNGUARDED_HARD_SECS="$remaining"
attempt_route "$provider" "$FIXED_ROUTE"
if [ "$RUN_SUCCEEDED" = true ] && ! out_missing_or_invalid && ! out_final; then
nonfinal_position="$(jq -r '.position' "$RAW_OUT" 2>/dev/null)"
rm -f "$RAW_OUT"
fi
fi
fi
# --- normalize + validate against the peer POV contract ------------------
# Force voice = peer-<provider>, preserve the POV fields, and add route/model
# receipts from the route that actually ran. The peer never self-attributes an
# unverifiable serving model.
# Publish ONLY the normalized OUT into RUN_DIR. RAW_OUT lives in the per-peer
# workspace and is never a fold-in artifact — if this script dies before normalize
# (orphaned launch), synthesis finds no .json in RUN_DIR.
rm -f "$OUT"
if [ -s "$RAW_OUT" ]; then
_norm="$PEER_WORKDIR/normalized.json"
case "$ACTUAL_ROUTE:$MODEL_ACTUAL" in
cursor:*) serving_family="unknown" ;;
composer:unverified|grok-cursor:unverified) serving_family="unknown" ;;
*) serving_family="$(target_serving_family "$provider")" ;;
esac
independence=false
[ "$HOST_PROVIDER" != "unknown" ] && [ "$serving_family" != "unknown" ] && [ "$HOST_PROVIDER" != "$serving_family" ] && independence=true
if jq --arg v "peer-$provider" --arg route "$ACTUAL_ROUTE" \
--arg target "$provider" --arg harness "$(route_harness "$ACTUAL_ROUTE")" \
--arg family "$serving_family" \
--arg mreq "$(route_model "$ACTUAL_ROUTE")" --arg mact "$MODEL_ACTUAL" \
--argjson independent "$independence" \
'if ((.voice|type)=="string" and (.voice|length)>0 and (.position|type)=="string" and (.position|length)>0 and (.reasoning|type)=="string" and (.reasoning|length)>0 and (.evidence|type)=="array" and all(.evidence[]; type=="string" and length>0) and (.external_check=="ran" or .external_check=="unavailable") and (.mode=="independent" or .mode=="skeptic") and (.movement=="initial" or .movement=="moved" or .movement=="held") and .final==true)
then { voice: $v,
cross_model_route: $route,
cross_model_target: $target,
cross_model_harness: $harness,
serving_family: $family,
model_requested: $mreq,
model_actual: $mact,
independence_verified: $independent,
position: .position,
reasoning: .reasoning,
evidence: .evidence,
external_check: .external_check,
mode: .mode,
movement: .movement,
final: true }
else empty end' \
"$RAW_OUT" > "$_norm" 2>/dev/null; then
mv "$_norm" "$OUT"
chmod 600 "$OUT" 2>/dev/null || { rm -f "$OUT"; log "could not make result artifact private"; }
else
rm -f "$_norm"
fi
rm -f "$RAW_OUT"
fi
if [ -s "$OUT" ] && jq -e \
'(.voice|type)=="string" and (.position|type)=="string" and (.position|length)>0 and (.reasoning|type)=="string" and (.reasoning|length)>0 and (.evidence|type)=="array" and all(.evidence[]; type=="string" and length>0) and (.external_check=="ran" or .external_check=="unavailable") and (.mode=="independent" or .mode=="skeptic") and (.movement=="initial" or .movement=="moved" or .movement=="held") and (.independence_verified|type)=="boolean"' \
"$OUT" >/dev/null 2>&1; then
log "wrote peer POV to $OUT (voice peer-$provider)"
else
log "provider $provider produced no usable schema-shaped output; skipping fold-in"
[ -n "$nonfinal_position" ] && log " peer skip evidence: non-final position: ${nonfinal_position:0:200}"
# Surface bounded, actionable peer evidence so the orchestrator can
# reason about WHY it was skipped (quota/usage-limit exhaustion vs an ordinary
# empty review) and, in a repeated-pass session, deprioritize an exhausted
# route. Prefer structured CLI error fields before the bounded raw fallback;
# a useful `.result` can appear near the start of a long JSON envelope. Surface
# BOTH streams -- the error can be on stdout (grok's 402) or stderr
# (claude/cursor auth/quota).
if [ -s "$PEERLOG" ]; then
_pt="$(bounded_failure_evidence "$PEERLOG")"
log " peer skip evidence: $_pt"
fi
if [ -s "$PEERERR" ]; then
_pe="$(bounded_failure_evidence "$PEERERR")"
log " peer skip evidence (stderr): $_pe"
fi
rm -f "$OUT" "$RAW_OUT"
fi
cleanup_private_scratch
}
run_fixed_route
exit 0
SHA-256: 7fecdc7f73daf7143967af004d2ee23af7b5121097dbbf13580e4f6a24ed2f8e