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
92 changes: 92 additions & 0 deletions .github/workflows/review-swarm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Review swarm

on:
# The workflow and secret context come from main; PR code is only review data.
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]

permissions:
contents: read
pull-requests: write

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

jobs:
review:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
# Ordering invariant: job 75 min > poll 65 min > swarm 60 min.
timeout-minutes: 75
env:
GH_TOKEN: ${{ github.token }}
RELAY_WORKSPACE_KEY: ${{ secrets.RELAY_WORKSPACE_KEY }}
steps:
- name: Check out PR head
uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
path: target

- name: Check out immutable gate from main
uses: actions/checkout@v4
with:
ref: main
path: gate
sparse-checkout: |
workflows/review-swarm.yaml
.github/workflows/scripts

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

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

- name: Prepare review target on launcher
working-directory: target
run: |
../gate/.github/workflows/scripts/swarm-prepare.sh "${{ github.event.pull_request.number }}"
mkdir -p .github/workflows/scripts
cp ../gate/.github/workflows/scripts/swarm-verdict.sh .github/workflows/scripts/swarm-verdict.sh
git add -f .github/workflows/scripts/swarm-verdict.sh

- name: Launch immutable review swarm
id: launch
working-directory: target
run: |
response=$(agent-relay cloud run ../gate/workflows/review-swarm.yaml --json)
run_id=$(printf '%s' "$response" | jq -er '.runId // .run_id // .id')
echo "run_id=$run_id" >> "$GITHUB_OUTPUT"

- name: Wait for terminal status
id: wait
if: steps.launch.outputs.run_id != ''
run: |
# Ordering invariant: job 75 min > this 3900s (65 min) > swarm 60 min.
deadline=$((SECONDS + 3900))
swarm_status=timed_out
while [ "$SECONDS" -lt "$deadline" ]; do
status_json=$(agent-relay cloud status "${{ steps.launch.outputs.run_id }}" --json || true)
swarm_status=$(printf '%s' "$status_json" | jq -r '.status // "unknown"' 2>/dev/null || printf unknown)
case "$swarm_status" in completed|failed|cancelled) break ;; esac
sleep 15
done
echo "swarm_status=$swarm_status" >> "$GITHUB_OUTPUT"
exit 0

- name: Post sticky review evidence
if: always() && steps.launch.outputs.run_id != ''
run: gate/.github/workflows/scripts/swarm-post.sh "${{ steps.launch.outputs.run_id }}" "${{ github.event.pull_request.number }}" "$GITHUB_WORKSPACE/target"

- name: Enforce swarm completion
if: steps.wait.outputs.swarm_status != 'completed'
run: |
echo "Review swarm ended with status: ${{ steps.wait.outputs.swarm_status }}" >&2
exit 1
63 changes: 63 additions & 0 deletions .github/workflows/scripts/swarm-post.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/bin/sh
set -u

run_id=${1:?usage: swarm-post.sh RUN_ID PR_NUMBER WORKTREE}
pr_number=${2:?usage: swarm-post.sh RUN_ID PR_NUMBER WORKTREE}
worktree=${3:?usage: swarm-post.sh RUN_ID PR_NUMBER WORKTREE}
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
. "$script_dir/swarm-verdict.sh"

sync_started=$(date +%s)
sync_ok=true
if ! agent-relay cloud sync "$run_id" --dir "$worktree"; then
sync_ok=false
fi

verdict_file=$(mktemp)
trap 'rm -f "$verdict_file"' EXIT
if [ "$sync_ok" = true ]; then
swarm_overall_verdict "$worktree/ops/reviews" "$pr_number" "$sync_started" \
> "$verdict_file" || true
else
for lens in $swarm_lenses; do printf '%s\tMISSING\t\n' "$lens"; done > "$verdict_file"
printf 'overall\tFAILED\n' >> "$verdict_file"
fi

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

while IFS="$(printf '\t')" read -r lens verdict name; do
[ "$lens" != overall ] || continue
body=$(mktemp)
{
printf '{"body":'
{ printf '<!-- swarm-lens: %s -->\n### Review swarm: %s — %s\n\n' "$lens" "$lens" "$verdict"
if [ -n "$name" ] && [ -f "$worktree/ops/reviews/$name" ]; then
cat "$worktree/ops/reviews/$name"
else
printf 'No fresh transcript was produced by run `%s`.\n' "$run_id"
fi
} | jq -Rs .
printf '}\n'
} > "$body"
upsert_comment "<!-- swarm-lens: $lens -->" "$body"
rm -f "$body"
done < "$verdict_file"

overall=$(awk -F '\t' '$1 == "overall" { print $2 }' "$verdict_file")
marker=$(mktemp)
printf '<!-- review-swarm -->\n### Review swarm: %s\n\nRun `%s`; all three lenses must pass.\n' \
"$overall" "$run_id" | jq -Rs '{body: .}' > "$marker"
upsert_comment '<!-- review-swarm -->' "$marker"
rm -f "$marker"
15 changes: 15 additions & 0 deletions .github/workflows/scripts/swarm-prepare.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh
set -eu

pr_number=${1:?usage: swarm-prepare.sh PR_NUMBER}
case "$pr_number" in *[!0-9]*|'') echo "invalid PR number: $pr_number" >&2; exit 2 ;; esac

mkdir -p .review-target
printf '%s\n' "$pr_number" > .review-target/pr-number
gh pr diff "$pr_number" > .review-target/pr.diff
gh pr view "$pr_number" --json headRefName,headRefOid,title,url > .review-target/pr.json

# cloud run uploads git ls-files, so these launcher-produced inputs must be staged.
git add -f .review-target/pr-number .review-target/pr.diff .review-target/pr.json
git ls-files --error-unmatch .review-target/pr-number .review-target/pr.diff \
.review-target/pr.json >/dev/null
45 changes: 45 additions & 0 deletions .github/workflows/scripts/swarm-verdict.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/sh

swarm_lenses="maintainability history structure"

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

swarm_lens_verdict() {
transcript=$1
sync_started=$2
[ -n "$transcript" ] && [ -f "$transcript" ] || {
printf '%s\n' MISSING
return
}
[ "$(stat -c %Y "$transcript")" -ge "$sync_started" ] || {
printf '%s\n' STALE
return
}
token=$(awk 'NF { token=$NF } END { print token }' "$transcript")
case "$token" in
REVIEW_PASSED) printf '%s\n' PASSED ;;
REVIEW_FAILED) printf '%s\n' FAILED ;;
*) printf '%s\n' UNCLEAR ;;
esac
}

swarm_overall_verdict() {
review_dir=$1
pr_number=$2
sync_started=$3
overall=PASSED
for lens in $swarm_lenses; do
name=$(swarm_transcript "$review_dir" "$pr_number" "$lens")
verdict=$(swarm_lens_verdict "$review_dir/$name" "$sync_started")
[ "$verdict" = PASSED ] || overall=FAILED
printf '%s\t%s\t%s\n' "$lens" "$verdict" "$name"
done
printf 'overall\t%s\n' "$overall"
[ "$overall" = PASSED ]
}
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@ 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.

## Cloud review swarm

The `Review swarm` GitHub Actions workflow requires the repository Actions
secret `RELAY_WORKSPACE_KEY`. A workspace owner can print the key from an
authenticated machine with `agent-relay workspace key default
--reveal-secrets` (replace `default` with the workspace name), then add it under
**Settings → Secrets and variables → Actions → New repository secret**. The
workflow fails in preflight when the secret is absent, before starting
`agent-relay` or its interactive authentication fallback.
Loading