mirror of
https://github.com/EveryInc/compound-engineering-plugin.git
synced 2026-10-24 15:15:20 +02:00
1003 lines
40 KiB
Bash
Executable File
1003 lines
40 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Run one pre-sanctioned, write-capable implementation route in a controller-
|
|
# supplied detached workspace. The adapter never creates worktrees, changes
|
|
# recipients, integrates output, or retries through another route.
|
|
#
|
|
# Usage:
|
|
# cross-model-work.sh <authorization-json> <workspace> <unit-packet> <expected-packet-sha256> <result-dir>
|
|
#
|
|
# Routes: codex | claude | grok-cli | cursor | composer | grok-cursor | opencode
|
|
# Output: <result-dir>/implementation-result.json and redacted adapter.log
|
|
# Exit: 0 host-resolvable terminal result, 1 failed/schema-invalid, 2 unavailable
|
|
#
|
|
# Introspection (no model call):
|
|
# cross-model-work.sh --emit-adapter <route>
|
|
|
|
set -uo pipefail
|
|
umask 077
|
|
|
|
# Prefer the runner-exported interpreter (sys.executable via CE_PEER_PYTHON),
|
|
# else probe execution — Windows Store's python3 stub satisfies `command -v`
|
|
# then exits nonzero (see resolve-python convention / #1247).
|
|
PY="${CE_PEER_PYTHON:-}"
|
|
if [ -z "$PY" ]; then
|
|
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)"
|
|
fi
|
|
[ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; }
|
|
|
|
M_GROK_CURSOR="grok-4.7-xhigh"
|
|
M_COMPOSER="composer-2.5-fast"
|
|
|
|
log() { printf '[cross-model-work] %s\n' "$*" >&2; }
|
|
|
|
route_target() {
|
|
case "$1" in
|
|
codex|claude|cursor|composer) printf '%s' "$1" ;;
|
|
grok-cli|grok-cursor) printf 'grok' ;;
|
|
opencode) printf 'opencode' ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
route_harness() {
|
|
case "$1" in
|
|
codex) printf 'codex' ;;
|
|
claude) printf 'claude' ;;
|
|
grok-cli) printf 'grok' ;;
|
|
cursor|composer|grok-cursor) printf 'cursor-agent' ;;
|
|
opencode) printf 'opencode' ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
route_model() {
|
|
local route="$1" target override="${CE_WORK_MODEL_OVERRIDE:-}"
|
|
if [ -n "${MODEL_REQUESTED:-}" ]; then
|
|
printf '%s' "$MODEL_REQUESTED"
|
|
return
|
|
fi
|
|
target="$(route_target "$route")" || return 1
|
|
if [ -n "$override" ] && [ "${CE_WORK_MODEL_OVERRIDE_TARGET:-}" = "$target" ]; then
|
|
printf '%s' "$override"
|
|
return
|
|
fi
|
|
case "$route" in
|
|
codex|claude|grok-cli|cursor) printf 'auto' ;;
|
|
grok-cursor) printf '%s' "$M_GROK_CURSOR" ;;
|
|
composer) printf '%s' "$M_COMPOSER" ;;
|
|
opencode) printf 'auto' ;;
|
|
esac
|
|
}
|
|
|
|
validate_model_override() {
|
|
local route="$1" override="${CE_WORK_MODEL_OVERRIDE:-}" override_target="${CE_WORK_MODEL_OVERRIDE_TARGET:-}" target override_lower
|
|
[ -n "$override" ] || { [ -z "$override_target" ]; return; }
|
|
case "$override_target" in
|
|
codex|claude|grok|cursor|composer|opencode) ;;
|
|
*) return 1 ;;
|
|
esac
|
|
target="$(route_target "$route")" || return 1
|
|
[ "$override_target" = "$target" ] || return 0
|
|
if [ "$route" = cursor ]; then
|
|
case "$override" in
|
|
[A-Za-z0-9]*)
|
|
case "$override" in *[!A-Za-z0-9._:/-]*) return 1 ;; esac
|
|
override_lower="$(printf '%s' "$override" | tr '[:upper:]' '[:lower:]')"
|
|
case "$override_lower" in composer|composer-*|grok|grok-*|cursor-grok-*) return 1 ;; esac
|
|
return 0
|
|
;;
|
|
*) return 1 ;;
|
|
esac
|
|
fi
|
|
case "$route:$override" in
|
|
codex:gpt-*|codex:o[0-9]*|claude:fable|claude:opus|claude:sonnet|claude:haiku|claude:claude-*|grok-cli:grok-*|grok-cursor:cursor-grok-*|grok-cursor:grok-4.7-*|composer:composer-*|opencode:*/*) ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
validate_effort_override() {
|
|
# Reject a tier the selected route cannot honor instead of forwarding it to a
|
|
# CLI that will fail the attempt after controller authorization. Routes with
|
|
# no effort knob (cursor, composer, grok-cursor) reject any override.
|
|
# Levels checked 2026-09-19 against claude and grok CLI help and codex 0.155.0's
|
|
# model list; codex levels vary per model, so a listed level can still fail
|
|
# after launch on a model that lacks it.
|
|
local route="$1" effort="${EFFORT_REQUESTED:-}"
|
|
[ -n "$effort" ] || return 0
|
|
case "$route:$effort" in
|
|
claude:low|claude:medium|claude:high|claude:xhigh|claude:max) ;;
|
|
codex:low|codex:medium|codex:high|codex:xhigh|codex:max|codex:ultra) ;;
|
|
grok-cli:low|grok-cli:medium|grok-cli:high|grok-cli:xhigh) ;;
|
|
opencode:none|opencode:minimal|opencode:low|opencode:medium|opencode:high|opencode:xhigh|opencode:max|opencode:default) ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
adapter_argv() {
|
|
case "$1" in
|
|
codex)
|
|
# --ignore-user-config drops the user's model_reasoning_effort, so pin the
|
|
# editorial tier explicitly. Claude stays high; native Grok defaults to xhigh.
|
|
# EFFORT_REQUESTED retunes all three effort-taking routes. Production
|
|
# starts take it only from the controller authorization; the ambient
|
|
# CROSS_MODEL_EFFORT_OVERRIDE feeds it in --emit-adapter mode alone.
|
|
printf '%s\0' codex exec --ignore-user-config --ignore-rules --ephemeral \
|
|
-s workspace-write -C "$WORKSPACE" --json -o "$RAW_RESULT" \
|
|
-c model_reasoning_effort="${EFFORT_REQUESTED:-high}"
|
|
[ "$(route_model codex)" = auto ] || printf '%s\0' -m "$(route_model codex)"
|
|
printf '%s\0' -
|
|
;;
|
|
claude)
|
|
local claude_model
|
|
claude_model="$(route_model claude)"
|
|
printf '%s\0' claude -p --safe-mode --no-session-persistence \
|
|
--permission-mode bypassPermissions --tools Read,Write,Edit,Bash \
|
|
--allowed-tools 'Bash(*)' \
|
|
--effort "${EFFORT_REQUESTED:-high}" --output-format stream-json --verbose
|
|
[ "$claude_model" = auto ] || printf '%s\0' --model "$claude_model"
|
|
;;
|
|
grok-cli)
|
|
local grok_model
|
|
grok_model="$(route_model grok-cli)"
|
|
printf '%s\0' grok --prompt-file "$PROMPT_FILE" --cwd "$WORKSPACE" \
|
|
--effort "${EFFORT_REQUESTED:-xhigh}" --permission-mode acceptEdits \
|
|
--tools Read,Write,Edit --disable-web-search --no-memory --no-subagents \
|
|
--no-plan --max-turns 50 --output-format streaming-json --verbatim
|
|
[ "$grok_model" = auto ] || printf '%s\0' --model "$grok_model"
|
|
;;
|
|
cursor)
|
|
local cursor_model
|
|
cursor_model="$(route_model cursor)"
|
|
printf '%s\0' cursor-agent -p --output-format stream-json --stream-partial-output \
|
|
--force --sandbox enabled --trust --workspace "$WORKSPACE"
|
|
[ "$cursor_model" = auto ] || printf '%s\0' --model "$cursor_model"
|
|
;;
|
|
composer)
|
|
printf '%s\0' cursor-agent -p --output-format stream-json --stream-partial-output \
|
|
--force --sandbox enabled --trust --workspace "$WORKSPACE" --model "$(route_model composer)"
|
|
;;
|
|
grok-cursor)
|
|
printf '%s\0' cursor-agent -p --output-format stream-json --stream-partial-output \
|
|
--force --sandbox enabled --trust --workspace "$WORKSPACE" --model "$(route_model grok-cursor)"
|
|
;;
|
|
opencode)
|
|
printf '%s\0' opencode run --dir "$WORKSPACE" --format json --auto \
|
|
"Follow the attached unit packet. Return only the implementation result JSON." --file "$PROMPT_FILE"
|
|
[ "$(route_model opencode)" = auto ] || printf '%s\0' --model "$(route_model opencode)"
|
|
# OpenCode carries effort through --variant, same as the review adapters.
|
|
[ -z "${EFFORT_REQUESTED:-}" ] || printf '%s\0' --variant "$EFFORT_REQUESTED"
|
|
;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
if [ "${1:-}" = "--emit-adapter" ]; then
|
|
WORKSPACE="<workspace>"
|
|
PROMPT_FILE="<prompt-file>"
|
|
RAW_RESULT="<raw-result>"
|
|
ROUTE="${2:-}"
|
|
EFFORT_REQUESTED="${CROSS_MODEL_EFFORT_OVERRIDE:-}"
|
|
validate_model_override "$ROUTE" || {
|
|
printf "model override '%s' not compatible with route '%s'\n" "${CE_WORK_MODEL_OVERRIDE:-}" "$ROUTE" >&2
|
|
exit 2
|
|
}
|
|
validate_effort_override "$ROUTE" || {
|
|
printf "effort override '%s' not compatible with route '%s'\n" "$EFFORT_REQUESTED" "$ROUTE" >&2
|
|
exit 2
|
|
}
|
|
adapter_argv "$ROUTE" >/dev/null 2>&1 || { printf "unknown route '%s'\n" "$ROUTE" >&2; exit 2; }
|
|
adapter_argv "$ROUTE" | tr '\0' ' '
|
|
printf '\n'
|
|
exit 0
|
|
fi
|
|
|
|
AUTHORIZATION="${1:-}"
|
|
WORKSPACE="${2:-}"
|
|
PACKET="${3:-}"
|
|
EXPECTED_PACKET_DIGEST="${4:-}"
|
|
RESULT_DIR="${5:-}"
|
|
[[ "$EXPECTED_PACKET_DIGEST" =~ ^[0-9a-f]{64}$ ]] || { log "expected packet digest must be lowercase SHA-256"; exit 2; }
|
|
[ -n "$AUTHORIZATION" ] || { log "controller authorization JSON path is required"; exit 2; }
|
|
[ -d "$WORKSPACE" ] || { log "workspace '$WORKSPACE' is not a directory"; exit 2; }
|
|
[ -f "$PACKET" ] && [ ! -L "$PACKET" ] || { log "unit packet '$PACKET' is not a regular non-link file"; exit 2; }
|
|
[ -d "$RESULT_DIR" ] && [ ! -L "$RESULT_DIR" ] || { log "result dir '$RESULT_DIR' is not a directory"; exit 2; }
|
|
|
|
DISPATCH_AUTHORIZATION="$AUTHORIZATION"
|
|
DISPATCH_WORKSPACE="$WORKSPACE"
|
|
DISPATCH_PACKET="$PACKET"
|
|
DISPATCH_RESULT_DIR="$RESULT_DIR"
|
|
|
|
MAX_PACKET_BYTES="${CE_WORK_MAX_PACKET_BYTES:-200000}"
|
|
case "$MAX_PACKET_BYTES" in ''|*[!0-9]*) MAX_PACKET_BYTES=200000 ;; esac
|
|
|
|
SKILL_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" || exit 2
|
|
PERSONA="$SKILL_ROOT/references/agents/implementation-worker.md"
|
|
SCHEMA="$SKILL_ROOT/references/implementation-result-schema.json"
|
|
[ -f "$PERSONA" ] && [ -f "$SCHEMA" ] || { log "worker persona or result schema missing"; exit 2; }
|
|
|
|
SCRATCH="$(mktemp -d "${TMPDIR:-/tmp}/ce-work-adapter-XXXXXX")" || exit 2
|
|
chmod 700 "$SCRATCH"
|
|
PROMPT_FILE="$SCRATCH/prompt.md"
|
|
RAW_STDOUT="$SCRATCH/stdout.log"
|
|
RAW_STDERR="$SCRATCH/stderr.log"
|
|
RAW_RESULT="$SCRATCH/result.raw"
|
|
RAW_LIMIT_MARKER="$SCRATCH/raw-output-limit"
|
|
PACKET_SNAPSHOT="$SCRATCH/unit-packet"
|
|
AUTH_VALUES="$SCRATCH/authorization-values"
|
|
RESULT_FILE="$RESULT_DIR/implementation-result.json"
|
|
LOG_FILE="$RESULT_DIR/adapter.log"
|
|
LOG_RETAINED=0
|
|
trap 'rm -rf "$SCRATCH"' EXIT
|
|
|
|
# The controller's create-exclusive authorization artifact is the production
|
|
# dispatch capability. Read it once through a no-follow descriptor, validate
|
|
# its exact route/model/packet contract, and derive every dispatch identity
|
|
# field from those bytes before constructing a prompt or invoking a model CLI.
|
|
"$PY" - "$AUTHORIZATION" "$EXPECTED_PACKET_DIGEST" "$AUTH_VALUES" <<'PY'
|
|
import json, os, re, stat, sys
|
|
|
|
source, expected_packet_digest, output = sys.argv[1:]
|
|
required = {
|
|
"schema_version", "run_id", "unit_id", "attempt_id", "route", "target", "harness",
|
|
"intermediaries", "model_requested", "restriction_posture",
|
|
"restrictions", "activity_posture", "packet_digest",
|
|
}
|
|
contracts = {
|
|
"codex": ("codex", "codex", [], "adapter-enforced"),
|
|
"claude": ("claude", "claude", [], "cooperative"),
|
|
"grok-cli": ("grok", "grok", [], "cooperative"),
|
|
"cursor": ("cursor", "cursor-agent", [], "adapter-enforced"),
|
|
"composer": ("composer", "cursor-agent", ["cursor"], "adapter-enforced"),
|
|
"grok-cursor": ("grok", "cursor-agent", ["cursor"], "adapter-enforced"),
|
|
"opencode": ("opencode", "opencode", [], "cooperative"),
|
|
}
|
|
|
|
def fail(message):
|
|
raise ValueError(message)
|
|
|
|
def model_allowed(route, model):
|
|
if not isinstance(model, str) or not model or "\n" in model or "\r" in model:
|
|
return False
|
|
if route == "codex":
|
|
return model == "auto" or bool(re.fullmatch(r"(?:gpt-[A-Za-z0-9._-]+|o[0-9][A-Za-z0-9._-]*)", model))
|
|
if route == "claude":
|
|
return model in {"auto", "fable", "opus", "sonnet", "haiku"} or bool(re.fullmatch(r"claude-[A-Za-z0-9._-]+", model))
|
|
if route == "grok-cli":
|
|
return model == "auto" or bool(re.fullmatch(r"grok-[A-Za-z0-9._-]+", model))
|
|
if route == "cursor":
|
|
if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._:/-]*", model):
|
|
return False
|
|
lowered = model.lower()
|
|
return not (lowered in {"composer", "grok"} or lowered.startswith(("composer-", "grok-", "cursor-grok-")))
|
|
if route == "composer":
|
|
return bool(re.fullmatch(r"composer-[A-Za-z0-9._-]+", model))
|
|
if route == "grok-cursor":
|
|
return bool(re.fullmatch(r"(?:cursor-grok-[A-Za-z0-9._-]+|grok-4\.7-[A-Za-z0-9._-]+)", model))
|
|
if route == "opencode":
|
|
return model == "auto" or bool(re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]*/[A-Za-z0-9._-]+", model))
|
|
return False
|
|
|
|
try:
|
|
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
|
|
fd = os.open(os.path.abspath(source), flags)
|
|
try:
|
|
before = os.fstat(fd)
|
|
if not stat.S_ISREG(before.st_mode):
|
|
fail("authorization is not a regular file")
|
|
geteuid = getattr(os, "geteuid", None)
|
|
if geteuid is not None and before.st_uid != geteuid():
|
|
fail("authorization is not owned by the current user")
|
|
if stat.S_IMODE(before.st_mode) != 0o600:
|
|
fail("authorization mode is not 0600")
|
|
if before.st_size > 64 * 1024:
|
|
fail("authorization exceeds 65536 bytes")
|
|
chunks, total = [], 0
|
|
while True:
|
|
part = os.read(fd, min(65536, 65537 - total))
|
|
if not part:
|
|
break
|
|
chunks.append(part)
|
|
total += len(part)
|
|
if total > 65536:
|
|
fail("authorization grew past 65536 bytes")
|
|
after = os.fstat(fd)
|
|
if (before.st_dev, before.st_ino, before.st_size, before.st_mtime_ns, before.st_ctime_ns) != (
|
|
after.st_dev, after.st_ino, after.st_size, after.st_mtime_ns, after.st_ctime_ns
|
|
):
|
|
fail("authorization changed while being read")
|
|
finally:
|
|
os.close(fd)
|
|
try:
|
|
value = json.loads(b"".join(chunks))
|
|
except (ValueError, UnicodeDecodeError) as exc:
|
|
fail(f"authorization is malformed JSON: {exc}")
|
|
if not isinstance(value, dict) or set(value) - {"effort_requested"} != required:
|
|
fail("authorization keys do not match the exact controller schema")
|
|
if type(value["schema_version"]) is not int or value["schema_version"] != 1:
|
|
fail("authorization schema_version must be 1")
|
|
for key in ("run_id", "unit_id", "attempt_id"):
|
|
if not isinstance(value[key], str) or not re.fullmatch(r"[A-Za-z0-9._-]{1,128}", value[key]) or not value[key].strip("."):
|
|
fail(f"authorization {key} is unsafe")
|
|
route = value["route"]
|
|
if route not in contracts:
|
|
fail("authorization route is unsupported")
|
|
target, harness, intermediaries, posture = contracts[route]
|
|
if (value["target"], value["harness"], value["intermediaries"], value["restriction_posture"]) != (target, harness, intermediaries, posture):
|
|
fail("authorization route identity or restriction posture is inconsistent")
|
|
if value["activity_posture"] not in {"incremental", "hard-only"}:
|
|
fail("authorization activity_posture is invalid")
|
|
restrictions = value["restrictions"]
|
|
if not isinstance(restrictions, list) or not all(isinstance(item, str) for item in restrictions):
|
|
fail("authorization restrictions must be a string list")
|
|
if not model_allowed(route, value["model_requested"]):
|
|
fail("authorization model is incompatible with the fixed route")
|
|
effort = value.get("effort_requested", "")
|
|
if "effort_requested" in value and (not isinstance(effort, str) or not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_-]{0,31}", effort)):
|
|
fail("authorization effort_requested is not a short plain token")
|
|
packet_digest = value["packet_digest"]
|
|
if not isinstance(packet_digest, str) or not re.fullmatch(r"[0-9a-f]{64}", packet_digest):
|
|
fail("authorization packet_digest is not lowercase SHA-256")
|
|
if packet_digest != expected_packet_digest:
|
|
fail("authorization packet digest does not match dispatch")
|
|
authorization_digest = __import__("hashlib").sha256(b"".join(chunks)).hexdigest()
|
|
fields = (
|
|
authorization_digest, value["run_id"], value["unit_id"], value["attempt_id"],
|
|
route, target, harness, value["model_requested"], value["activity_posture"], posture, effort,
|
|
)
|
|
out = os.open(output, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
|
try:
|
|
os.write(out, b"\0".join(item.encode() for item in fields) + b"\0")
|
|
finally:
|
|
os.close(out)
|
|
except (OSError, ValueError) as exc:
|
|
print(f"controller authorization rejected: {exc}", file=sys.stderr)
|
|
raise SystemExit(2)
|
|
PY
|
|
AUTH_EXIT=$?
|
|
[ "$AUTH_EXIT" -eq 0 ] || { log "controller authorization rejected"; exit 2; }
|
|
|
|
AUTH_FIELDS=()
|
|
while IFS= read -r -d '' field; do AUTH_FIELDS+=("$field"); done < "$AUTH_VALUES"
|
|
[ "${#AUTH_FIELDS[@]}" -eq 11 ] || { log "controller authorization projection is incomplete"; exit 2; }
|
|
OBSERVED_AUTH_DIGEST="${AUTH_FIELDS[0]}"
|
|
RUN_ID="${AUTH_FIELDS[1]}"
|
|
UNIT_ID="${AUTH_FIELDS[2]}"
|
|
ATTEMPT_ID="${AUTH_FIELDS[3]}"
|
|
ROUTE="${AUTH_FIELDS[4]}"
|
|
AUTH_TARGET="${AUTH_FIELDS[5]}"
|
|
AUTH_HARNESS="${AUTH_FIELDS[6]}"
|
|
MODEL_REQUESTED="${AUTH_FIELDS[7]}"
|
|
ACTIVITY_POSTURE="${AUTH_FIELDS[8]}"
|
|
RESTRICTION_POSTURE="${AUTH_FIELDS[9]}"
|
|
EFFORT_REQUESTED="${AUTH_FIELDS[10]}"
|
|
RUNNER_JOB_ID="${CE_PEER_JOB_ID:-}"
|
|
[[ "$RUNNER_JOB_ID" =~ ^[A-Za-z0-9._-]{1,128}$ && "$RUNNER_JOB_ID" =~ [A-Za-z0-9_-] ]] || {
|
|
log "runner job identity is missing or unsafe"
|
|
exit 2
|
|
}
|
|
|
|
# A valid JSON file is not itself dispatch authority. Prove the exact no-follow
|
|
# snapshot and every raw controller-returned path back to the controller before
|
|
# prompt construction. Only its AUTHORIZED status permits external egress.
|
|
CONTROLLER="$SKILL_ROOT/scripts/unit-workspace.py"
|
|
AUTH_RESPONSE="$("$PY" "$CONTROLLER" authorize-dispatch \
|
|
--authorization "$DISPATCH_AUTHORIZATION" \
|
|
--authorization-digest "$OBSERVED_AUTH_DIGEST" \
|
|
--workspace "$DISPATCH_WORKSPACE" \
|
|
--packet "$DISPATCH_PACKET" \
|
|
--packet-digest "$EXPECTED_PACKET_DIGEST" \
|
|
--result-dir "$DISPATCH_RESULT_DIR" \
|
|
--run-id "$RUN_ID" --unit-id "$UNIT_ID" --attempt-id "$ATTEMPT_ID" --job-id "$RUNNER_JOB_ID" 2>&1)"
|
|
CONTROLLER_EXIT=$?
|
|
AUTH_STATUS="${AUTH_RESPONSE%%$'\n'*}"
|
|
if [ "$CONTROLLER_EXIT" -ne 0 ] || [ "$AUTH_STATUS" != "AUTHORIZED" ]; then
|
|
[ -n "$AUTH_RESPONSE" ] && printf '%s\n' "$AUTH_RESPONSE" >&2
|
|
log "controller dispatch authorization failed"
|
|
exit 2
|
|
fi
|
|
|
|
# Canonicalize operational paths only after the handshake. The controller
|
|
# compares the raw paths it returned, including platform compatibility symlinks.
|
|
WORKSPACE="$(cd "$WORKSPACE" && pwd -P)" || exit 2
|
|
PACKET="$(cd "$(dirname "$PACKET")" && pwd -P)/$(basename "$PACKET")" || exit 2
|
|
RESULT_DIR="$(cd "$RESULT_DIR" && pwd -P)" || exit 2
|
|
case "$RESULT_DIR/" in "$WORKSPACE/"*) log "result dir must be outside the worker workspace"; exit 2 ;; esac
|
|
case "$PACKET" in "$WORKSPACE"/*) log "unit packet must be outside the worker workspace"; exit 2 ;; esac
|
|
git -C "$WORKSPACE" rev-parse --is-inside-work-tree >/dev/null 2>&1 || { log "workspace is not a Git worktree"; exit 2; }
|
|
chmod 700 "$RESULT_DIR" 2>/dev/null || { log "result dir could not be made private"; exit 2; }
|
|
RESULT_DIR_IDENTITY="$("$PY" - "$RESULT_DIR" <<'PY'
|
|
import os, stat, sys
|
|
|
|
path = sys.argv[1]
|
|
flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0) | getattr(os, "O_NOFOLLOW", 0)
|
|
fd = os.open(path, flags)
|
|
try:
|
|
info = os.fstat(fd)
|
|
if not stat.S_ISDIR(info.st_mode):
|
|
raise OSError("result dir is not a directory")
|
|
print(f"{info.st_dev}:{info.st_ino}")
|
|
finally:
|
|
os.close(fd)
|
|
PY
|
|
)" || { log "result dir identity could not be captured"; exit 2; }
|
|
|
|
write_adapter_log() {
|
|
"$PY" -c '
|
|
import os, stat, sys
|
|
|
|
path, expected = sys.argv[1:]
|
|
dir_flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0) | getattr(os, "O_NOFOLLOW", 0)
|
|
try:
|
|
dir_fd = os.open(path, dir_flags)
|
|
try:
|
|
directory = os.fstat(dir_fd)
|
|
if not stat.S_ISDIR(directory.st_mode):
|
|
raise OSError("result dir is not a directory")
|
|
if f"{directory.st_dev}:{directory.st_ino}" != expected:
|
|
raise OSError("result dir identity changed during route")
|
|
file_flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_NOFOLLOW", 0)
|
|
log_fd = os.open("adapter.log", file_flags, 0o600, dir_fd=dir_fd)
|
|
try:
|
|
target = os.fstat(log_fd)
|
|
if not stat.S_ISREG(target.st_mode):
|
|
raise OSError("adapter log is not a regular file")
|
|
os.fchmod(log_fd, 0o600)
|
|
while True:
|
|
chunk = sys.stdin.buffer.read(65536)
|
|
if not chunk:
|
|
break
|
|
view = memoryview(chunk)
|
|
while view:
|
|
view = view[os.write(log_fd, view):]
|
|
finally:
|
|
os.close(log_fd)
|
|
finally:
|
|
os.close(dir_fd)
|
|
except OSError as error:
|
|
print(f"adapter log retention refused: {error}", file=sys.stderr)
|
|
raise SystemExit(2)
|
|
' "$RESULT_DIR" "$RESULT_DIR_IDENTITY"
|
|
}
|
|
|
|
write_result_receipt() {
|
|
"$PY" -c '
|
|
import os, secrets, stat, sys
|
|
|
|
path, expected = sys.argv[1:]
|
|
dir_flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0) | getattr(os, "O_NOFOLLOW", 0)
|
|
dir_fd = None
|
|
receipt_fd = None
|
|
tmp_name = None
|
|
try:
|
|
data = sys.stdin.buffer.read()
|
|
dir_fd = os.open(path, dir_flags)
|
|
directory = os.fstat(dir_fd)
|
|
if not stat.S_ISDIR(directory.st_mode):
|
|
raise OSError("result dir is not a directory")
|
|
if f"{directory.st_dev}:{directory.st_ino}" != expected:
|
|
raise OSError("result dir identity changed during route")
|
|
file_flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_NOFOLLOW", 0)
|
|
for _ in range(128):
|
|
candidate = f".result-{os.getpid()}-{secrets.token_hex(8)}"
|
|
try:
|
|
receipt_fd = os.open(candidate, file_flags, 0o600, dir_fd=dir_fd)
|
|
tmp_name = candidate
|
|
break
|
|
except FileExistsError:
|
|
continue
|
|
if receipt_fd is None:
|
|
raise OSError("could not reserve a result receipt temporary file")
|
|
target = os.fstat(receipt_fd)
|
|
if not stat.S_ISREG(target.st_mode):
|
|
raise OSError("result receipt temporary file is not regular")
|
|
os.fchmod(receipt_fd, 0o600)
|
|
view = memoryview(data)
|
|
while view:
|
|
view = view[os.write(receipt_fd, view):]
|
|
os.close(receipt_fd)
|
|
receipt_fd = None
|
|
os.replace(
|
|
tmp_name,
|
|
"implementation-result.json",
|
|
src_dir_fd=dir_fd,
|
|
dst_dir_fd=dir_fd,
|
|
)
|
|
tmp_name = None
|
|
except OSError as error:
|
|
print(f"result receipt publication refused: {error}", file=sys.stderr)
|
|
raise SystemExit(2)
|
|
finally:
|
|
if receipt_fd is not None:
|
|
os.close(receipt_fd)
|
|
if tmp_name is not None and dir_fd is not None:
|
|
try:
|
|
os.unlink(tmp_name, dir_fd=dir_fd)
|
|
except OSError:
|
|
pass
|
|
if dir_fd is not None:
|
|
os.close(dir_fd)
|
|
' "$RESULT_DIR" "$RESULT_DIR_IDENTITY"
|
|
}
|
|
|
|
# Read the packet once through a no-follow descriptor, hash those exact bytes,
|
|
# and build the prompt from the private snapshot. The controller-provided
|
|
# digest is therefore bound to the content that actually crosses the route.
|
|
OBSERVED_PACKET_DIGEST="$("$PY" - "$PACKET" "$PACKET_SNAPSHOT" "$MAX_PACKET_BYTES" <<'PY'
|
|
import hashlib, os, stat, sys
|
|
|
|
source, snapshot, raw_cap = sys.argv[1:]
|
|
cap = int(raw_cap)
|
|
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
|
|
fd = os.open(source, flags)
|
|
try:
|
|
info = os.fstat(fd)
|
|
if not stat.S_ISREG(info.st_mode):
|
|
raise OSError("unit packet is not a regular file")
|
|
chunks, total = [], 0
|
|
while True:
|
|
chunk = os.read(fd, min(65536, cap + 1 - total))
|
|
if not chunk:
|
|
break
|
|
chunks.append(chunk)
|
|
total += len(chunk)
|
|
if total > cap:
|
|
raise OSError(f"unit packet exceeds {cap} bytes")
|
|
finally:
|
|
os.close(fd)
|
|
data = b"".join(chunks)
|
|
out = os.open(snapshot, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
|
try:
|
|
view = memoryview(data)
|
|
while view:
|
|
written = os.write(out, view)
|
|
view = view[written:]
|
|
finally:
|
|
os.close(out)
|
|
print(hashlib.sha256(data).hexdigest())
|
|
PY
|
|
)" || { log "unit packet could not be snapshotted safely"; exit 2; }
|
|
[ "$OBSERVED_PACKET_DIGEST" = "$EXPECTED_PACKET_DIGEST" ] || {
|
|
log "unit packet digest mismatch (expected $EXPECTED_PACKET_DIGEST, observed $OBSERVED_PACKET_DIGEST)"
|
|
exit 2
|
|
}
|
|
|
|
redact_stream() {
|
|
CE_WORK_REDACT_FILE="${CE_WORK_REDACT_FILE:-}" "$PY" -c '
|
|
import os, sys
|
|
p = os.environ.get("CE_WORK_REDACT_FILE", "")
|
|
if p:
|
|
try:
|
|
values = sorted(
|
|
{v for v in open(p, "rb").read().splitlines() if v},
|
|
key=lambda value: (-len(value), value),
|
|
)
|
|
except OSError:
|
|
values = []
|
|
else:
|
|
values = []
|
|
|
|
def emit(data):
|
|
while data:
|
|
written = os.write(sys.stdout.fileno(), data)
|
|
data = data[written:]
|
|
|
|
pending = b""
|
|
max_value_bytes = max((len(value) for value in values), default=1)
|
|
try:
|
|
if not values:
|
|
while True:
|
|
chunk = os.read(sys.stdin.fileno(), 65536)
|
|
if not chunk:
|
|
break
|
|
emit(chunk)
|
|
sys.exit(0)
|
|
|
|
while True:
|
|
chunk = os.read(sys.stdin.fileno(), 65536)
|
|
if not chunk:
|
|
break
|
|
pending += chunk
|
|
offset = 0
|
|
output = bytearray()
|
|
while len(pending) - offset >= max_value_bytes:
|
|
match = next((value for value in values if pending.startswith(value, offset)), None)
|
|
if match is not None:
|
|
output.extend(b"[REDACTED]")
|
|
offset += len(match)
|
|
else:
|
|
output.append(pending[offset])
|
|
offset += 1
|
|
emit(bytes(output))
|
|
pending = pending[offset:]
|
|
offset = 0
|
|
output = bytearray()
|
|
while offset < len(pending):
|
|
match = next((value for value in values if pending.startswith(value, offset)), None)
|
|
if match is not None:
|
|
output.extend(b"[REDACTED]")
|
|
offset += len(match)
|
|
else:
|
|
output.append(pending[offset])
|
|
offset += 1
|
|
emit(bytes(output))
|
|
except BrokenPipeError:
|
|
os._exit(0)
|
|
'
|
|
}
|
|
|
|
cap_stream() {
|
|
"$PY" -c '
|
|
import os, sys
|
|
|
|
remaining = int(sys.argv[1])
|
|
while True:
|
|
chunk = os.read(sys.stdin.fileno(), 65536)
|
|
if not chunk:
|
|
break
|
|
if remaining:
|
|
retained = chunk[:remaining]
|
|
while retained:
|
|
written = os.write(sys.stdout.fileno(), retained)
|
|
retained = retained[written:]
|
|
remaining -= min(len(chunk), remaining)
|
|
' "$MAX_RAW_BYTES"
|
|
}
|
|
|
|
{
|
|
cat "$PERSONA"
|
|
if [ "$ROUTE" = codex ]; then
|
|
printf '\n\nSocket binds, OS permission checks, peer credentials, and similar capability probes are host-owned. Preserve the host command and observed result; do not treat a sandbox EPERM as proof the host lacks the capability.\n'
|
|
fi
|
|
printf '\n\nThe required final-result JSON schema is:\n\n'
|
|
cat "$SCHEMA"
|
|
printf '\n\n--- BOUNDED IMPLEMENTATION UNIT PACKET ---\n\n'
|
|
redact_stream < "$PACKET_SNAPSHOT"
|
|
} > "$PROMPT_FILE"
|
|
chmod 600 "$PROMPT_FILE"
|
|
|
|
TARGET="$AUTH_TARGET"
|
|
HARNESS="$AUTH_HARNESS"
|
|
|
|
publish_unavailable() {
|
|
local reason="$1"
|
|
local terminal_status="${2:-unavailable}"
|
|
local actual_route="${3:-}"
|
|
if [ "$LOG_RETAINED" -ne 1 ]; then
|
|
printf '%s\n' "$reason" | redact_stream | write_adapter_log || {
|
|
log "result dir or adapter log identity changed during route"
|
|
exit 2
|
|
}
|
|
LOG_RETAINED=1
|
|
fi
|
|
"$PY" - "$ROUTE" "$TARGET" "$HARNESS" "$MODEL_REQUESTED" "$EXPECTED_PACKET_DIGEST" "$LOG_FILE" "$reason" "$ACTIVITY_POSTURE" "$RESTRICTION_POSTURE" "$terminal_status" "$actual_route" "$EFFORT_REQUESTED" <<'PY' | write_result_receipt
|
|
import json, sys
|
|
route, target, harness, requested, packet_digest, log, reason, activity, restriction, terminal_status, actual_route, effort = sys.argv[1:]
|
|
value = {
|
|
"schema_version": 1, "terminal_status": terminal_status,
|
|
"summary": "External route failed after launch" if terminal_status == "failed" else "External route unavailable",
|
|
"changed_files": [], "evidence": [], "scope_expansion": None,
|
|
"requested_route": route, "actual_route": actual_route or None, "target": target, "harness": harness,
|
|
"intermediaries": ["cursor"] if route in ("composer", "grok-cursor") else [],
|
|
"model_requested": requested, "model_actual": "unverified", "model_receipt_status": "unverified",
|
|
"effort_requested": effort or None,
|
|
"packet_digest": packet_digest,
|
|
"activity_posture": activity, "restriction_posture": restriction,
|
|
"failure_reason": reason, "raw_log": log,
|
|
}
|
|
json.dump(value, sys.stdout, indent=2)
|
|
sys.stdout.write("\n")
|
|
PY
|
|
}
|
|
|
|
if [ "${CE_WORK_REQUIRE_ENFORCED_CONFINEMENT:-}" = "1" ]; then
|
|
case "$ROUTE" in
|
|
claude|grok-cli)
|
|
publish_unavailable "route offers cooperative workspace restriction, not required enforceable confinement" || exit 2
|
|
exit 2
|
|
;;
|
|
opencode)
|
|
publish_unavailable "route offers cooperative workspace restriction, not required enforceable confinement" || exit 2
|
|
exit 2
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
case "$ROUTE" in
|
|
codex) BINARY=codex ;;
|
|
claude) BINARY=claude ;;
|
|
grok-cli) BINARY=grok ;;
|
|
cursor|composer|grok-cursor) BINARY=cursor-agent ;;
|
|
opencode) BINARY=opencode ;;
|
|
esac
|
|
# 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
|
|
if ! command -v "$BINARY" >/dev/null 2>&1; then
|
|
publish_unavailable "fixed route executable '$BINARY' is unavailable" || exit 2
|
|
exit 2
|
|
fi
|
|
|
|
validate_effort_override "$ROUTE" || {
|
|
publish_unavailable "effort override '$EFFORT_REQUESTED' not compatible with route '$ROUTE'" || exit 2
|
|
exit 2
|
|
}
|
|
|
|
ARGS=()
|
|
while IFS= read -r -d '' token; do ARGS+=("$token"); done < <(adapter_argv "$ROUTE")
|
|
|
|
MIN_ENV=(env -i "PATH=$PATH" "PYTHONDONTWRITEBYTECODE=1")
|
|
[ -n "${HOME:-}" ] && MIN_ENV+=("HOME=$HOME")
|
|
[ -n "${USER:-}" ] && MIN_ENV+=("USER=$USER")
|
|
[ -n "${TMPDIR:-}" ] && MIN_ENV+=("TMPDIR=$TMPDIR")
|
|
[ -n "${LANG:-}" ] && MIN_ENV+=("LANG=$LANG")
|
|
[ -n "${LC_ALL:-}" ] && MIN_ENV+=("LC_ALL=$LC_ALL")
|
|
[ -n "${XDG_CONFIG_HOME:-}" ] && MIN_ENV+=("XDG_CONFIG_HOME=$XDG_CONFIG_HOME")
|
|
# Preserve route-specific config-directory pointers so existing CLI-native login
|
|
# remains reachable. Credential-bearing API-key variables are intentionally not
|
|
# forwarded; the worker gets paths to the CLI's own auth store, not secrets.
|
|
case "$ROUTE" in
|
|
codex) [ -n "${CODEX_HOME:-}" ] && MIN_ENV+=("CODEX_HOME=$CODEX_HOME") ;;
|
|
claude) [ -n "${CLAUDE_CONFIG_DIR:-}" ] && MIN_ENV+=("CLAUDE_CONFIG_DIR=$CLAUDE_CONFIG_DIR") ;;
|
|
grok-cli) [ -n "${GROK_CONFIG_HOME:-}" ] && MIN_ENV+=("GROK_CONFIG_HOME=$GROK_CONFIG_HOME") ;;
|
|
opencode)
|
|
[ -n "${OPENCODE_CONFIG_DIR:-}" ] && MIN_ENV+=("OPENCODE_CONFIG_DIR=$OPENCODE_CONFIG_DIR")
|
|
[ -n "${OPENCODE_CONFIG:-}" ] && MIN_ENV+=("OPENCODE_CONFIG=$OPENCODE_CONFIG")
|
|
;;
|
|
cursor|composer|grok-cursor)
|
|
[ -n "${CURSOR_CONFIG_DIR:-}" ] && MIN_ENV+=("CURSOR_CONFIG_DIR=$CURSOR_CONFIG_DIR")
|
|
;;
|
|
esac
|
|
|
|
# Cursor reports a human display label in its init receipt, not necessarily the
|
|
# model key passed on argv. Capture the current catalog label before dispatch so
|
|
# receipt comparison can follow CLI vocabulary drift without weakening the pin.
|
|
# The catalog probe uses the same minimal environment as the worker because it
|
|
# reaches the same authenticated CLI surface before dispatch.
|
|
MODEL_DISPLAY_HINT=""
|
|
if [ "$MODEL_REQUESTED" != auto ]; then
|
|
case "$ROUTE" in
|
|
cursor|composer|grok-cursor)
|
|
MODEL_DISPLAY_HINT="$({ "${MIN_ENV[@]}" "$BINARY" --list-models 2>/dev/null || true; } | awk -F ' - ' -v key="$MODEL_REQUESTED" '$1 == key { sub(/^[^ ]+ - /, ""); print; exit }')"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
ACTIVITY_POLL_SECS="${CE_WORK_ACTIVITY_POLL_SECS:-15}"
|
|
case "$ACTIVITY_POLL_SECS" in ''|*[!0-9]*) ACTIVITY_POLL_SECS=15 ;; esac
|
|
[ "$ACTIVITY_POLL_SECS" -lt 1 ] && ACTIVITY_POLL_SECS=1
|
|
MAX_RAW_BYTES="${CE_WORK_MAX_RAW_BYTES:-10485760}"
|
|
case "$MAX_RAW_BYTES" in ''|*[!0-9]*) MAX_RAW_BYTES=10485760 ;; esac
|
|
[ "$MAX_RAW_BYTES" -lt 1 ] && MAX_RAW_BYTES=10485760
|
|
|
|
raw_byte_count() {
|
|
local total=0 bytes file
|
|
for file in "$RAW_STDOUT" "$RAW_STDERR" "$RAW_RESULT"; do
|
|
[ -f "$file" ] || continue
|
|
bytes="$(wc -c < "$file" | tr -d '[:space:]')"
|
|
case "$bytes" in ''|*[!0-9]*) bytes=0 ;; esac
|
|
total=$((total + bytes))
|
|
done
|
|
printf '%s' "$total"
|
|
}
|
|
|
|
ACTIVE_ROUTE_PID=""
|
|
ACTIVITY_PID=""
|
|
terminate_route() {
|
|
[ -n "$ACTIVITY_PID" ] && kill "$ACTIVITY_PID" 2>/dev/null || true
|
|
[ -n "$ACTIVE_ROUTE_PID" ] && kill -TERM "$ACTIVE_ROUTE_PID" 2>/dev/null || true
|
|
[ -n "$ACTIVE_ROUTE_PID" ] && wait "$ACTIVE_ROUTE_PID" 2>/dev/null || true
|
|
rm -rf "$SCRATCH"
|
|
exit 143
|
|
}
|
|
trap 'terminate_route' TERM INT
|
|
|
|
set +e
|
|
(cd "$WORKSPACE" && exec "${MIN_ENV[@]}" "${ARGS[@]}" < "$PROMPT_FILE" > "$RAW_STDOUT" 2> "$RAW_STDERR") &
|
|
ACTIVE_ROUTE_PID=$!
|
|
(
|
|
# A foreground sleep would outlive this subshell's TERM and hold the script's
|
|
# output open, so callers (bun 1.4 spawnSync) would wait out the poll interval.
|
|
# Kill every background job, so a TERM between `sleep &` and `$!` still reaps it.
|
|
trap 'kill $(jobs -p) 2>/dev/null; exit 0' TERM
|
|
previous=0
|
|
while kill -0 "$ACTIVE_ROUTE_PID" 2>/dev/null; do
|
|
current="$(raw_byte_count)"
|
|
if [ "$current" -gt "$MAX_RAW_BYTES" ]; then
|
|
: > "$RAW_LIMIT_MARKER"
|
|
log "activity route=$ROUTE raw-output-limit bytes=$current cap=$MAX_RAW_BYTES"
|
|
kill -TERM "$ACTIVE_ROUTE_PID" 2>/dev/null || true
|
|
break
|
|
fi
|
|
if [ "$current" != "$previous" ]; then
|
|
log "activity route=$ROUTE output-updated"
|
|
previous="$current"
|
|
fi
|
|
sleep "$ACTIVITY_POLL_SECS" &
|
|
wait $!
|
|
done
|
|
) &
|
|
ACTIVITY_PID=$!
|
|
wait "$ACTIVE_ROUTE_PID"
|
|
ROUTE_EXIT=$?
|
|
kill "$ACTIVITY_PID" 2>/dev/null || true
|
|
wait "$ACTIVITY_PID" 2>/dev/null || true
|
|
ACTIVE_ROUTE_PID=""
|
|
ACTIVITY_PID=""
|
|
RAW_BYTES="$(raw_byte_count)"
|
|
[ "$RAW_BYTES" -gt "$MAX_RAW_BYTES" ] && : > "$RAW_LIMIT_MARKER"
|
|
{
|
|
cat "$RAW_STDOUT"
|
|
cat "$RAW_STDERR"
|
|
if [ -f "$RAW_RESULT" ]; then cat "$RAW_RESULT"; fi
|
|
} | redact_stream | cap_stream | write_adapter_log || {
|
|
log "result dir or adapter log identity changed during route"
|
|
exit 2
|
|
}
|
|
LOG_RETAINED=1
|
|
|
|
if [ -f "$RAW_LIMIT_MARKER" ]; then
|
|
publish_unavailable "fixed route raw output exceeded ${MAX_RAW_BYTES} bytes" || exit 2
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$ROUTE_EXIT" -ne 0 ]; then
|
|
publish_unavailable "fixed route exited with exit $ROUTE_EXIT" failed "$ROUTE" || exit 2
|
|
exit 1
|
|
fi
|
|
|
|
SOURCE="$RAW_STDOUT"
|
|
[ "$ROUTE" = codex ] && SOURCE="$RAW_RESULT"
|
|
set +e
|
|
CE_WORK_REDACT_FILE="${CE_WORK_REDACT_FILE:-}" "$PY" - \
|
|
"$SOURCE" "$RAW_STDOUT" "$ROUTE" "$TARGET" "$HARNESS" \
|
|
"$MODEL_REQUESTED" "$EXPECTED_PACKET_DIGEST" "$LOG_FILE" "$ACTIVITY_POSTURE" "$RESTRICTION_POSTURE" "$MODEL_DISPLAY_HINT" "$EFFORT_REQUESTED" <<'PY' | write_result_receipt
|
|
import json, os, re, sys
|
|
source, stream, route, target, harness, requested, packet_digest, log, activity, restriction, display_hint, effort = sys.argv[1:]
|
|
|
|
def redactions():
|
|
p=os.environ.get("CE_WORK_REDACT_FILE", "")
|
|
if not p: return []
|
|
try: return sorted(set(v for v in open(p, encoding="utf-8").read().splitlines() if v), key=lambda value: (-len(value), value))
|
|
except OSError: return []
|
|
|
|
redaction_values=redactions()
|
|
|
|
def redact(value):
|
|
if isinstance(value,str):
|
|
for secret in redaction_values: value=value.replace(secret, "[REDACTED]")
|
|
return value
|
|
if isinstance(value,list): return [redact(child) for child in value]
|
|
if isinstance(value,dict): return {key:redact(child) for key,child in value.items()}
|
|
return value
|
|
|
|
def parse_text(text):
|
|
found=[]
|
|
decoder=json.JSONDecoder()
|
|
def inspect(value):
|
|
if isinstance(value,dict):
|
|
if all(k in value for k in ("terminal_status","summary","changed_files","evidence","scope_expansion")):
|
|
found.append(value)
|
|
for child in value.values(): inspect(child)
|
|
elif isinstance(value,list):
|
|
for child in value: inspect(child)
|
|
elif isinstance(value,str):
|
|
inner=re.sub(r"^```(?:json)?\s*|\s*```$", "", value.strip(), flags=re.S)
|
|
for i,ch in enumerate(inner):
|
|
if ch not in "[{": continue
|
|
try:
|
|
child,_=decoder.raw_decode(inner,i); inspect(child)
|
|
except Exception: pass
|
|
inspect(text)
|
|
for line in text.splitlines():
|
|
try: inspect(json.loads(line))
|
|
except Exception: pass
|
|
return found[-1] if found else None
|
|
|
|
def normalize_served_model(value):
|
|
# Some CLIs have emitted terminal styling inside the JSON model field.
|
|
# Strip complete ANSI control sequences before validating the receipt token;
|
|
# never publish a partially sanitized or otherwise unsafe identity.
|
|
text=str(value)
|
|
text=re.sub(r"\x1b\[[0-?]*[ -/]*[@-~]", "", text)
|
|
text=re.sub(r"\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)", "", text)
|
|
text="".join(ch for ch in text if ord(ch) >= 0x20 and ord(ch) != 0x7f).strip()
|
|
return text if 0 < len(text) <= 128 else "unverified"
|
|
|
|
try: raw=open(source, encoding="utf-8", errors="replace").read()
|
|
except OSError: raw=""
|
|
if route == "opencode":
|
|
parts=[]
|
|
for line in raw.splitlines():
|
|
try: event=json.loads(line)
|
|
except Exception: continue
|
|
if not isinstance(event, dict) or event.get("type") != "text":
|
|
continue
|
|
part=event.get("part") if isinstance(event.get("part"), dict) else {}
|
|
chunk=part.get("text") if isinstance(part.get("text"), str) else None
|
|
if chunk:
|
|
parts.append(chunk)
|
|
worker=parse_text("".join(parts)) if parts else None
|
|
else:
|
|
worker=parse_text(raw)
|
|
valid=isinstance(worker,dict)
|
|
worker_fields=("terminal_status", "summary", "changed_files", "evidence", "scope_expansion")
|
|
if valid:
|
|
valid=(set(worker) == set(worker_fields)
|
|
and worker.get("terminal_status") in ("completed","blocked","scope_expansion")
|
|
and isinstance(worker.get("summary"),str) and bool(worker["summary"])
|
|
and isinstance(worker.get("changed_files"),list) and all(isinstance(x,str) and x for x in worker["changed_files"])
|
|
and isinstance(worker.get("evidence"),list) and all(isinstance(x,str) and x for x in worker["evidence"])
|
|
and ((worker["terminal_status"]=="scope_expansion" and isinstance(worker.get("scope_expansion"),dict))
|
|
or (worker["terminal_status"]!="scope_expansion" and worker.get("scope_expansion") is None)))
|
|
|
|
served="unverified"
|
|
if source == stream:
|
|
stream_text=raw
|
|
else:
|
|
try: stream_text=open(stream, encoding="utf-8", errors="replace").read()
|
|
except OSError: stream_text=""
|
|
for line in stream_text.splitlines():
|
|
try: event=json.loads(line)
|
|
except Exception: continue
|
|
if isinstance(event,dict) and event.get("model") and (event.get("subtype")=="init" or event.get("type") in ("init","system")):
|
|
served=normalize_served_model(event["model"]); break
|
|
|
|
if served == "unverified": receipt="unverified"
|
|
elif requested == "auto": receipt="verified"
|
|
else:
|
|
req=requested.lower(); actual=served.lower()
|
|
if route in ("cursor", "composer", "grok-cursor"):
|
|
def model_terms(value):
|
|
value=re.sub(r"\b\d+(?:k|m)\b", " ", value.lower())
|
|
terms=set(re.findall(r"[a-z]+|\d+", value))
|
|
return terms - {"claude", "cursor"}
|
|
expected=model_terms(display_hint or requested)
|
|
receipt="verified" if expected and expected.issubset(model_terms(served)) else "mismatch"
|
|
else:
|
|
family=("claude-fable-" if req=="fable" else "claude-opus-" if req=="opus" else
|
|
"claude-sonnet-" if req=="sonnet" else "claude-haiku-" if req=="haiku" else req)
|
|
normalized=lambda value: re.sub(r"[^a-z0-9]", "", value.lower())
|
|
receipt="verified" if actual.startswith(family) or actual==req or normalized(actual)==normalized(req) else "mismatch"
|
|
|
|
intermediaries=["cursor"] if route in ("composer","grok-cursor") else []
|
|
base={
|
|
"schema_version":1,
|
|
"requested_route":route, "actual_route":route, "target":target, "harness":harness,
|
|
"intermediaries":intermediaries, "model_requested":requested, "model_actual":served,
|
|
"model_receipt_status":receipt, "effort_requested":effort or None, "activity_posture":activity,
|
|
"packet_digest":packet_digest,
|
|
"restriction_posture":restriction,
|
|
"failure_reason":None, "raw_log":log,
|
|
}
|
|
if valid:
|
|
projected={key:worker[key] for key in worker_fields}
|
|
base.update(projected)
|
|
else:
|
|
base.update({"terminal_status":"failed", "summary":"Adapter terminal output failed result schema",
|
|
"changed_files":[], "evidence":[], "scope_expansion":None,
|
|
"failure_reason":"terminal output failed implementation result schema"})
|
|
base=redact(base)
|
|
json.dump(base,sys.stdout,indent=2)
|
|
sys.stdout.write("\n")
|
|
sys.exit(0 if valid else 4)
|
|
PY
|
|
NORMALIZE_STATUSES=("${PIPESTATUS[@]}")
|
|
NORMALIZE_EXIT="${NORMALIZE_STATUSES[0]}"
|
|
PUBLISH_EXIT="${NORMALIZE_STATUSES[1]}"
|
|
if [ "$PUBLISH_EXIT" -ne 0 ]; then exit 2; fi
|
|
if [ "$NORMALIZE_EXIT" -ne 0 ]; then exit 1; fi
|
|
|
|
TERMINAL_STATUS="$("$PY" -c 'import json,sys; print(json.load(open(sys.argv[1]))["terminal_status"])' "$RESULT_FILE")"
|
|
case "$TERMINAL_STATUS" in
|
|
completed|blocked|scope_expansion) exit 0 ;;
|
|
*) exit 1 ;;
|
|
esac
|