Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/workflows/review-swarm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Review swarm

on:
pull_request:
types: [opened, reopened, synchronize, ready_for_review]

permissions:
contents: read
pull-requests: write

concurrency:
group: review-swarm-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
review:
# Ordering invariant: job 75m > poll 65m > swarm 60m.
timeout-minutes: 75
runs-on: ubuntu-latest
steps:
- name: Check out the reviewed PR
uses: actions/checkout@v4
with:
path: reviewed
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0

# The PR cannot change the workflow or scripts that judge it. Only this
# separate main checkout supplies the gate files that execute below.
- name: Check out the immutable gate
uses: actions/checkout@v4
with:
path: gate
ref: main
fetch-depth: 1

- name: Validate cloud authentication
env:
RELAY_WORKSPACE_KEY: ${{ secrets.RELAY_WORKSPACE_KEY }}
run: |
if [ -z "$RELAY_WORKSPACE_KEY" ]; then
echo "RELAY_WORKSPACE_KEY secret not configured; see README § Review swarm cloud authentication" >&2
exit 1
fi

- name: Install Agent Relay
run: npm install --global agent-relay

- name: Prepare review target on the authenticated host
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_REPO: ${{ github.repository }}
run: |
bash gate/.github/workflows/scripts/swarm-prepare.sh \
reviewed gate/.github/workflows/scripts/swarm-post.sh

- name: Launch immutable review swarm
id: launch
working-directory: reviewed
env:
RELAY_WORKSPACE_KEY: ${{ secrets.RELAY_WORKSPACE_KEY }}
run: |
response=$(agent-relay cloud run ../gate/workflows/review-swarm.yaml --sync-code --json)
printf '%s\n' "$response"
run_id=$(printf '%s' "$response" | python3 -c 'import json,sys; print(json.load(sys.stdin)["runId"])')
echo "run_id=$run_id" >> "$GITHUB_OUTPUT"

- name: Wait for terminal cloud status
id: wait
env:
RELAY_WORKSPACE_KEY: ${{ secrets.RELAY_WORKSPACE_KEY }}
RUN_ID: ${{ steps.launch.outputs.run_id }}
run: |
# Ordering invariant: poll 3900s (65m) < job 75m and > swarm 60m.
deadline=$((SECONDS + 3900))
status=timed_out
while [ "$SECONDS" -lt "$deadline" ]; do
status=$(agent-relay cloud status "$RUN_ID" --json |
python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])') || status=status_error
case "$status" in
completed|failed|cancelled) break ;;
esac
sleep 15
done
echo "swarm_status=$status" >> "$GITHUB_OUTPUT"
exit 0

- name: Sync evidence and update PR comments
if: always() && steps.launch.outputs.run_id != ''
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
RUN_ID: ${{ steps.launch.outputs.run_id }}
SWARM_STATUS: ${{ steps.wait.outputs.swarm_status }}
RELAY_WORKSPACE_KEY: ${{ secrets.RELAY_WORKSPACE_KEY }}
run: bash gate/.github/workflows/scripts/swarm-post.sh post reviewed

- name: Enforce successful terminal status
if: steps.wait.outputs.swarm_status != 'completed'
env:
SWARM_STATUS: ${{ steps.wait.outputs.swarm_status }}
run: |
echo "Review swarm did not complete successfully: ${SWARM_STATUS:-missing}" >&2
exit 1
134 changes: 134 additions & 0 deletions .github/workflows/scripts/swarm-post.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/bin/sh
set -eu

lenses="maintainability history structure"

latest_transcript() {
review_dir=$1
pr=$2
lens=$3
find "$review_dir" -maxdepth 1 -type f -name "*-pr${pr}-${lens}.md" \
-printf '%f\n' 2>/dev/null | LC_ALL=C sort | tail -n 1
}

transcript_verdict() {
file=$1
token=$(awk 'NF { last=$NF } END { print last }' "$file")
case "$token" in
REVIEW_PASSED) printf '%s\n' PASSED ;;
REVIEW_FAILED) printf '%s\n' FAILED ;;
*) printf '%s\n' UNCLEAR ;;
esac
}

collect_verdicts() {
root=$1
pr=$2
started_file="$root/.review-target/sync-start"
review_dir="$root/ops/reviews"
overall=PASSED

if [ ! -f "$started_file" ]; then
echo "MISSING|sync-start|MISSING"
return 1
fi
started=$(cat "$started_file")

for lens in $lenses; do
name=$(latest_transcript "$review_dir" "$pr" "$lens")
if [ -z "$name" ]; then
echo "$lens||MISSING"
overall=FAILED
continue
fi
file="$review_dir/$name"
modified=$(stat -c %Y "$file")
if [ "$modified" -lt "$started" ]; then
verdict=STALE
else
verdict=$(transcript_verdict "$file")
fi
[ "$verdict" = PASSED ] || overall=FAILED
echo "$lens|$file|$verdict"
done
[ "$overall" = PASSED ]
}

run_verdict() {
root=${1:-.}
pr=$(tr -dc '0-9' < "$root/.review-target/pr-number")
verdicts=$(collect_verdicts "$root" "$pr") && overall=PASSED || overall=FAILED
printf '%s\n' "$verdicts"
echo "OVERALL|$overall"
[ "$overall" = PASSED ]
}

upsert_comment() {
anchor=$1
body_file=$2
comment_id=$(gh api --paginate "repos/$GH_REPO/issues/$PR_NUMBER/comments" \
--jq ".[] | select(.body | contains(\"$anchor\")) | .id" | tail -n 1)
if [ -n "$comment_id" ]; then
gh api --method PATCH "repos/$GH_REPO/issues/comments/$comment_id" \
--raw-field "body=$(cat "$body_file")" >/dev/null
else
gh api --method POST "repos/$GH_REPO/issues/$PR_NUMBER/comments" \
--raw-field "body=$(cat "$body_file")" >/dev/null
fi
}

post_results() {
root=${1:-.}
: "${RUN_ID:?RUN_ID is required}"
: "${SWARM_STATUS:?SWARM_STATUS is required}"
: "${GH_REPO:?GH_REPO is required}"
: "${PR_NUMBER:?PR_NUMBER is required}"

sync_status=ok
agent-relay cloud sync "$RUN_ID" --dir "$root" || sync_status=failed
verdicts=$(run_verdict "$root") && overall=PASSED || overall=FAILED
[ "$SWARM_STATUS" = completed ] || overall=FAILED
[ "$sync_status" = ok ] || overall=FAILED

temp_dir=$(mktemp -d)
trap 'rm -rf "$temp_dir"' EXIT HUP INT TERM
printf '%s\n' "$verdicts" | while IFS='|' read -r lens file verdict; do
case "$lens" in
maintainability|history|structure) ;;
*) continue ;;
esac
body="$temp_dir/$lens.md"
printf '<!-- swarm-lens: %s -->\n### Review swarm: %s — %s\n\n' \
"$lens" "$lens" "$verdict" > "$body"
if [ -n "$file" ] && [ -f "$file" ]; then
cat "$file" >> "$body"
else
echo "No current transcript was produced." >> "$body"
fi
upsert_comment "<!-- swarm-lens: $lens -->" "$body"
done

marker="$temp_dir/marker.md"
cat > "$marker" <<EOF
<!-- review-swarm -->
### Review swarm: $overall

Cloud run: \`$RUN_ID\`
Terminal status: \`$SWARM_STATUS\`
Evidence sync: \`$sync_status\`

Gate contract: (1) judge files come from main; (2) one verdict implementation;
(3) auth is preflighted; (4) marker and lens comments are sticky; (5) every PR
is reviewed; (6) PR data is fetched on the launching host; (7) timeouts obey
75m > 65m > 60m; (8) terminal status is recorded before always-post and gating;
(9) all three transcripts must be newer than the cloud sync start.
EOF
upsert_comment '<!-- review-swarm -->' "$marker"
[ "$overall" = PASSED ]
}

case ${1:-} in
verdict) shift; run_verdict "$@" ;;
post) shift; post_results "$@" ;;
*) echo "usage: $0 {verdict [root]|post [root]}" >&2; exit 64 ;;
esac
30 changes: 30 additions & 0 deletions .github/workflows/scripts/swarm-prepare.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh
set -eu

worktree=${1:-.}
gate_script=${2:-}
: "${PR_NUMBER:?PR_NUMBER is required}"
: "${GH_REPO:?GH_REPO is required}"

case "$PR_NUMBER" in
*[!0-9]*|'') echo "PR_NUMBER must be numeric" >&2; exit 64 ;;
esac

mkdir -p "$worktree/.review-target"
if [ -z "$gate_script" ] || [ ! -f "$gate_script" ]; then
echo "immutable swarm-post.sh is required" >&2
exit 64
fi
mkdir -p "$worktree/.github/workflows/scripts"
cp "$gate_script" "$worktree/.github/workflows/scripts/swarm-post.sh"
printf '%s\n' "$PR_NUMBER" > "$worktree/.review-target/pr-number"
gh pr diff "$PR_NUMBER" --repo "$GH_REPO" > "$worktree/.review-target/pr.diff"
gh pr view "$PR_NUMBER" --repo "$GH_REPO" \
--json headRefName,headRefOid,title,url > "$worktree/.review-target/pr.json"

git -C "$worktree" add -f .review-target/pr-number \
.review-target/pr.diff .review-target/pr.json \
.github/workflows/scripts/swarm-post.sh
git -C "$worktree" ls-files --error-unmatch \
.review-target/pr-number .review-target/pr.diff .review-target/pr.json \
.github/workflows/scripts/swarm-post.sh >/dev/null
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ dist/
.env
.agentworkforce/
.cargo-home/
.review-target

# Toolchains materialize inside the workspace in a cloud sandbox and must never
# be committed or delivered. Run f18ec684's patch carried .rustup-home/ files;
# ops/deliver-run.sh scrubs them too, but ignoring them is the durable fix.
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ Nine gates, in `docs/RFC-0001` §3. Gate 1 first: a relayflow can run — the he
ladder survives `kill -9` at every boundary.

Private while we build. YC 2026-09-15 runs on this base.

## Review swarm cloud authentication

The `review-swarm.yml` GitHub Actions workflow requires a repository Actions
secret named `RELAY_WORKSPACE_KEY`. Obtain a workspace key from the Agent Relay
cloud workspace settings, then add it under **Settings → Secrets and variables
→ Actions → New repository secret**. The workflow fails before launch when the
secret is absent; it never falls back to interactive device login.
12 changes: 12 additions & 0 deletions ops/NEEDS_HUMAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Gate 3 delivery blocker

The gate-3 review-swarm implementation and its executable definition-of-done
checks pass, including `cd sdk && npm test` (15 test files, 203 tests).

The run cannot satisfy the required final `git status --porcelain`: this
workspace's `.git` file points to `/home/daytona/.project-git`, which does not
exist. The workspace contained that dangling pointer before implementation;
no Git object database or authenticated GitHub remote is available locally to
recover it without fabricating repository state. Reattach the worktree's Git
metadata, then rerun the definition-of-done commands and make
`git status --porcelain` the last action.
Loading
Loading