56f5aac582
Acts on the 2026-07-30 senior review (REVIEW.md findings 1, 2, 4, 5, 7).
Docs (finding 1): CLAUDE.md and AGENTS.md both claimed Design B "has zero
clients - no worker binary exists". cmd/orchestra-worker/main.go is the
deployed worker, and the non-local-herdr guardrail has landed in
Coordinator.adapterFor. Both sections rewritten; AUDIT.md gains a matching
federation-status record. The Phase 5 retention / Phase 6 deletion decision
for Design A is preserved, not flattened.
clients/ un-ignored and tracked, including the .service unit and README:
deployed code belongs in version control. Design A is NOT deleted here.
progress.md (finding 2): the file was deleted after 636ed8a, yet CLAUDE.md
instructed every session to cross-check against it. References removed from
CLAUDE.md, AGENTS.md, internal/orchestrator/rotation_test.go (comment only)
and deploy/hooks/orchestra-codex-poll.sh; AUDIT.md now carries the log role.
web/go.mod (finding 4): a module stub ends the parent package graph at the
directory boundary, so go list ./... no longer yields
web/node_modules/flatted/golang/pkg/flatted. A build tag cannot work - the
package is in the package list before tags are evaluated. Local/CI-only
breakage: Dockerfile.api builds ./cmd/orchestra by explicit path and
.dockerignore already excluded node_modules.
orchestra-worker (finding 5): untracked (8.9MB, mode 100755, still on disk);
both binaries now gitignored.
Token compare (finding 7): cmd/orchestra/main.go:139,582 use
subtle.ConstantTimeCompare, matching the authz.go idiom. The token != ""
guard stays first, so an empty configured token still means auth-disabled
rather than auth-bypass. Three further plain != secret compares remain in
internal/federation/federation.go:343,346,368 - tracked, not fixed here.
Also included from the review pass: orchestrator.go records adapter-resolution
failures in SessionHealth.LastError instead of dropping them on a bare
continue, plus an Observed flag so lease-seeded health is not mistaken for a
live reading, with a covering test. GET /v1/tasks/<id>/health now returns a
record with last_error where it previously returned a bare 404.
REVIEW.md's own second pass claimed every checkable fact held up; four did
not. AUDIT.md never contained the false Design B claim (AGENTS.md was the
second copy), the guardrail is at orchestrator.go:312 not :309, the
progress.md site list missed the codex-poll hook, and only orchestra-worker
was tracked. Verified: go build, go vet, go test, and
go list ./... | grep node_modules all clean with every change applied
together. No live herdr or pane was touched; nothing was deployed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GEugbHVYfAXFpTqDYbByEB
85 lines
3.1 KiB
Bash
Executable File
85 lines
3.1 KiB
Bash
Executable File
#!/bin/sh
|
|
# Codex turn-boundary/completion poller.
|
|
#
|
|
# Unlike Claude Code, Codex has no native Stop hook — nothing calls out at a
|
|
# turn boundary. This script is meant to run as a background loop inside the
|
|
# pane alongside the codex process (AUDIT.md Phase 2 item 4, "Not done:
|
|
# Codex/opencode Stop-hook-equivalent scripts"), polling the same
|
|
# two endpoints the Claude Stop hook (orchestra-stop.sh) calls on every turn:
|
|
# - completion: if the agent has written .orchestra-report.md, POST
|
|
# /v1/harness/complete with harness=codex and the newest active rollout
|
|
# path, then remove the marker.
|
|
# - turn decision: otherwise POST /v1/harness/turn and log (never kill the
|
|
# harness process on "refuse" — there's no turn boundary to refuse at
|
|
# from outside the process the way exit-code-2 works for a real Stop
|
|
# hook; this is advisory-only for codex until app-server integration
|
|
# exists).
|
|
#
|
|
# Requires: ORCHESTRA_TASK_ID, ORCHESTRA_URL, ORCHESTRA_WORKTREE (the pane's
|
|
# cwd) set in the pane's env. Optional: ORCHESTRA_HARNESS_TOKEN,
|
|
# ORCHESTRA_POLL_INTERVAL (seconds, default 60).
|
|
# Needs: jq, find, curl.
|
|
|
|
set -u
|
|
|
|
: "${ORCHESTRA_POLL_INTERVAL:=60}"
|
|
: "${ORCHESTRA_WORKTREE:=$PWD}"
|
|
|
|
[ -z "${ORCHESTRA_TASK_ID:-}" ] && { echo "orchestra-codex-poll: ORCHESTRA_TASK_ID not set" >&2; exit 1; }
|
|
[ -z "${ORCHESTRA_URL:-}" ] && { echo "orchestra-codex-poll: ORCHESTRA_URL not set" >&2; exit 1; }
|
|
|
|
auth_header=""
|
|
if [ -n "${ORCHESTRA_HARNESS_TOKEN:-}" ]; then
|
|
auth_header="Authorization: Bearer ${ORCHESTRA_HARNESS_TOKEN}"
|
|
fi
|
|
|
|
# Newest rollout file under ~/.codex/sessions, matching CodexActiveUsage's
|
|
# own "most recently touched" heuristic (internal/herdr/occupancy.go).
|
|
latest_rollout() {
|
|
find "$HOME/.codex/sessions" -name 'rollout-*.jsonl' -type f -printf '%T@ %p\n' 2>/dev/null \
|
|
| sort -rn | head -n1 | cut -d' ' -f2-
|
|
}
|
|
|
|
report_file="${ORCHESTRA_WORKTREE%/}/.orchestra-report.md"
|
|
|
|
while true; do
|
|
sleep "$ORCHESTRA_POLL_INTERVAL"
|
|
|
|
rollout="$(latest_rollout)"
|
|
[ -z "$rollout" ] && continue
|
|
|
|
if [ -f "$report_file" ]; then
|
|
report="$(cat "$report_file")"
|
|
body="$(jq -n \
|
|
--arg task_id "$ORCHESTRA_TASK_ID" \
|
|
--arg transcript_path "$rollout" \
|
|
--arg report "$report" \
|
|
'{task_id: $task_id, harness: "codex", transcript_path: $transcript_path, report: $report}')"
|
|
|
|
if curl -fsS -X POST "${ORCHESTRA_URL%/}/v1/harness/complete" \
|
|
-H "Content-Type: application/json" \
|
|
${auth_header:+-H "$auth_header"} \
|
|
-d "$body" >/dev/null 2>&1; then
|
|
rm -f "$report_file"
|
|
exit 0
|
|
else
|
|
echo "orchestra-codex-poll: failed to report completion" >&2
|
|
fi
|
|
continue
|
|
fi
|
|
|
|
body="$(jq -n --arg task_id "$ORCHESTRA_TASK_ID" '{task_id: $task_id}')"
|
|
response="$(curl -fsS -X POST "${ORCHESTRA_URL%/}/v1/harness/turn" \
|
|
-H "Content-Type: application/json" \
|
|
${auth_header:+-H "$auth_header"} \
|
|
-d "$body" 2>/dev/null)" || {
|
|
echo "orchestra-codex-poll: failed to reach turn-decision endpoint" >&2
|
|
continue
|
|
}
|
|
|
|
decision="$(printf '%s' "$response" | jq -r '.decision // empty')"
|
|
if [ "$decision" = "refuse" ] || [ "$decision" = "rotate_now" ]; then
|
|
echo "orchestra-codex-poll: turn decision is $decision" >&2
|
|
fi
|
|
done
|