Skip to content
Merged
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
304 changes: 275 additions & 29 deletions sgt

Large diffs are not rendered by default.

121 changes: 121 additions & 0 deletions test_ralph_live_polecat_lane_accounting.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env bash
# test_ralph_live_polecat_lane_accounting.sh — Ralph active lanes must require a live polecat on the issue.

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")" && pwd)"
SGT_SCRIPT="$REPO_ROOT/sgt"
TMP_ROOT="$(mktemp -d)"
trap 'rm -rf "$TMP_ROOT"' EXIT

extract_fn() {
local name="$1"
awk -v n="$name" '
$0 ~ "^" n "\\(\\) \\{" {in_fn=1}
in_fn {print}
in_fn && $0 == "}" {exit}
' "$SGT_SCRIPT"
}

eval "$(extract_fn _escape_quotes)"
eval "$(extract_fn _polecat_start_grace_secs)"
eval "$(extract_fn _polecat_counts_as_active)"
eval "$(extract_fn _active_polecat_issue_numbers)"
eval "$(extract_fn _plan_state_path)"
eval "$(extract_fn _plan_file_path)"
eval "$(sed -n '/^_plan_ralph_snapshot()/,/^_president_last_action_snapshot()/p' "$SGT_SCRIPT" | sed '$d')"

export SGT_ROOT="$TMP_ROOT/root"
export SGT_CONFIG="$SGT_ROOT/.sgt"
export SGT_POLECATS="$SGT_CONFIG/polecats"
export SGT_PLAN_STATE_DIR="$SGT_CONFIG/plan-state"
export SGT_LOG="$TMP_ROOT/sgt.log"
mkdir -p "$SGT_POLECATS" "$SGT_PLAN_STATE_DIR" "$SGT_ROOT/rigs/pmkb" "$TMP_ROOT/worktrees/stale" "$TMP_ROOT/worktrees/live"
: > "$SGT_LOG"

log_event() {
printf '%s\n' "${1:-}" >> "$SGT_LOG"
}

rig_path() {
printf '%s/rigs/%s\n' "$SGT_ROOT" "$1"
}

TMUX_LIVE=1
tmux() {
if [[ "${1:-}" == "has-session" && "${3:-}" == "sgt-pmkb-live" && "$TMUX_LIVE" == "1" ]]; then
return 0
fi
return 1
}

cat > "$SGT_POLECATS/pmkb-stale" <<STATE
RIG=pmkb
REPO=https://github.com/acme/pmkb
ISSUE=1300
BRANCH=sgt/pmkb-stale
WORKTREE=$TMP_ROOT/worktrees/stale
SESSION=sgt-pmkb-stale
CREATED=2026-04-02T00:00:00Z
STATUS=running
STATE

cat > "$SGT_POLECATS/pmkb-live" <<STATE
RIG=pmkb
REPO=https://github.com/acme/pmkb
ISSUE=1301
BRANCH=sgt/pmkb-live
WORKTREE=$TMP_ROOT/worktrees/live
SESSION=sgt-pmkb-live
CREATED=2026-04-02T00:00:00Z
STATUS=running
STATE

cat > "$SGT_ROOT/rigs/pmkb/SGT_PLAN.json" <<'JSON'
{
"version": 1,
"rig": "pmkb",
"ralph": {
"enabled": true,
"condition": "Keep PMKB lanes live",
"target_concurrency": 2
},
"acceptance": { "status": "pending" },
"tasks": [
{ "id": "PK1300", "title": "Stale lane" },
{ "id": "PK1301", "title": "Live lane" }
]
}
JSON

cat > "$SGT_PLAN_STATE_DIR/pmkb.json" <<'JSON'
{
"tasks": {
"PK1300": { "status": "in_progress", "issue_number": "1300" },
"PK1301": { "status": "in_progress", "issue_number": "1301" }
}
}
JSON

snapshot="$(_plan_ralph_snapshot pmkb)"
IFS='|' read -r enabled unmet condition target active underfilled policy <<< "$snapshot"
[[ "$enabled" == "1" ]]
[[ "$unmet" == "1" ]]
[[ "$target" == "2" ]]
[[ "$active" == "1" ]] || {
echo "expected only the live polecat issue to count active, got snapshot=$snapshot" >&2
exit 1
}
[[ "$underfilled" == "1" ]]

TMUX_LIVE=0
rm -rf "$TMP_ROOT/worktrees/live"
snapshot="$(_plan_ralph_snapshot pmkb)"
IFS='|' read -r _enabled _unmet _condition _target active underfilled _policy <<< "$snapshot"
[[ "$active" == "0" ]] || {
echo "expected missing live worktree to remove remaining active lane, got snapshot=$snapshot" >&2
exit 1
}
[[ "$underfilled" == "1" ]]

echo "ALL TESTS PASSED"
5 changes: 5 additions & 0 deletions test_ralph_refill_attach_blocker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ _context_append_acceptance_blocker() { :; }
_context_python_bin() { return 1; }
_context_index_build() { :; }
_wake_mayor() { printf '%s\n' "$1" >> "$WAKE_FILE"; }
_workflow_backend_default() { printf '%s\n' 'github'; }
_forge_issue_comment_add() {
local _backend="$1" repo="$2" issue="$3" body="$4"
gh issue comment "$issue" --repo "$repo" --body "$body"
}
_acceptance_blocker_write() {
printf '%s|%s|%s|%s\n' "$1" "$3" "$4" "blocker-ralph" >> "$BLOCKER_FILE"
printf 'blocker-ralph\n'
Expand Down
69 changes: 69 additions & 0 deletions test_resling_authorization_fallback.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# test_resling_authorization_fallback.sh — Authorization checks should use REST/list fallbacks and classify read failures.

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")" && pwd)"
SGT_SCRIPT="$REPO_ROOT/sgt"

extract_fn() {
local name="$1"
awk -v n="$name" '
$0 ~ "^" n "\\(\\) \\{" {in_fn=1}
in_fn {print}
in_fn && $0 == "}" {exit}
' "$SGT_SCRIPT"
}

eval "$(extract_fn _one_line)"
eval "$(extract_fn _repo_owner_repo)"
eval "$(extract_fn _gh_issue_labels_live)"
eval "$(extract_fn _labels_contain_sgt_authorized)"
eval "$(extract_fn _label_list_one_line)"
eval "$(extract_fn _has_sgt_authorized)"

_workflow_backend_default() { printf '%s\n' 'github'; }
_forge_issue_labels() { return 0; }

gh() {
if [[ "${1:-}" == "api" ]]; then
printf '%s\n' 'sgt-authorized'
printf '%s\n' 'plan'
return 0
fi
echo "unexpected gh call: $*" >&2
return 1
}

_has_sgt_authorized "https://github.com/acme/demo" "1300" || {
echo "expected REST fallback to authorize issue" >&2
exit 1
}
[[ "${_SGT_AUTHZ_LAST_REASON_CODE:-}" == "authorized" ]]
[[ "${_SGT_AUTHZ_LAST_DETAIL:-}" == *"github-rest"* ]]

gh() {
if [[ "${1:-}" == "api" ]]; then
echo "gh api backend unavailable" >&2
return 1
fi
if [[ "${1:-}" == "issue" && "${2:-}" == "list" ]]; then
echo "gh issue list backend unavailable" >&2
return 1
fi
echo "unexpected gh call: $*" >&2
return 1
}

if _has_sgt_authorized "https://github.com/acme/demo" "1301"; then
echo "expected read failure to block authorization" >&2
exit 1
fi
[[ "${_SGT_AUTHZ_LAST_REASON_CODE:-}" == "label-read-failed" ]] || {
echo "expected label-read-failed, got ${_SGT_AUTHZ_LAST_REASON_CODE:-unset}" >&2
exit 1
}
[[ "${_SGT_AUTHZ_LAST_DETAIL:-}" == *"rest_error="* ]]
[[ "${_SGT_AUTHZ_LAST_DETAIL:-}" == *"list_error="* ]]

echo "ALL TESTS PASSED"
4 changes: 2 additions & 2 deletions test_status_json.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ args=" $* "
pr_state="${SGT_TEST_PR_STATE:-OPEN}"
pr_number="${SGT_TEST_PR_NUMBER:-123}"

if [[ "$args" == *" pr list "* ]] && [[ "$args" == *" --json number,state,title "* ]]; then
if [[ "$args" == *" pr list "* ]] && { [[ "$args" == *" --json number,state,title "* ]] || [[ "$args" == *" --json number,state,title,headRefOid "* ]]; }; then
if [[ "$pr_state" == "NONE" ]]; then
echo ""
else
printf '%s\t%s\t%s\n' "$pr_number" "$pr_state" "Mock PR $pr_state"
printf '%s\t%s\t%s\t%s\n' "$pr_number" "$pr_state" "Mock PR $pr_state" "deadbeef"
fi
exit 0
fi
Expand Down
100 changes: 100 additions & 0 deletions test_status_rig_activity_live_accounting.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env bash
# test_status_rig_activity_live_accounting.sh — Status should not relay stale active_polecats from persisted rig activity state.

set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")" && pwd)"
SGT_SCRIPT="$REPO_ROOT/sgt"
TMP_ROOT="$(mktemp -d)"
trap 'rm -rf "$TMP_ROOT"' EXIT

HOME_DIR="$TMP_ROOT/home"
MOCK_BIN="$TMP_ROOT/mockbin"
mkdir -p "$HOME_DIR/.local/bin" "$MOCK_BIN"
cp "$SGT_SCRIPT" "$HOME_DIR/.local/bin/sgt"
chmod +x "$HOME_DIR/.local/bin/sgt"

cat > "$MOCK_BIN/tmux" <<'TMUX'
#!/usr/bin/env bash
set -euo pipefail
exit 1
TMUX
chmod +x "$MOCK_BIN/tmux"

cat > "$MOCK_BIN/gh" <<'GH'
#!/usr/bin/env bash
set -euo pipefail
args=" $* "
if [[ "$args" == *" pr list "* && "$args" == *" --json number "* && "$args" == *" --jq "* ]]; then
echo "0"
exit 0
fi
if [[ "$args" == *" issue list "* && "$args" == *" --json number "* && "$args" == *" --jq "* ]]; then
echo "1"
exit 0
fi
if [[ "$args" == *" pr list "* && "$args" == *" --json number,state,title "* ]]; then
echo ""
exit 0
fi
exit 0
GH
chmod +x "$MOCK_BIN/gh"

ENV_PREFIX=(
env -i
HOME="$HOME_DIR"
PATH="$MOCK_BIN:$HOME_DIR/.local/bin:/usr/local/bin:/usr/bin:/bin"
TERM=dumb
SGT_ROOT="$HOME_DIR/sgt"
)

"${ENV_PREFIX[@]}" bash --noprofile --norc <<'BASH'
set -euo pipefail

sgt init >/dev/null
printf 'https://github.com/acme/demo\n' > "$SGT_ROOT/.sgt/rigs/demo"
mkdir -p "$SGT_ROOT/.sgt/mayor-rig-activity"
cat > "$SGT_ROOT/.sgt/mayor-rig-activity/demo.state" <<'STATE'
STATE=active
LAST_REASON=ralph target=3 active_lanes=3 underfilled=0 plan_rollup=ralph-condition-unmet plan_status=pending open_issues=3 open_prs=0 active_polecats=3 merge_queue=0 pending_plan_requests=0
CHANGED_AT=2026-04-02T05:00:00+02:00
CHANGED_EPOCH=1775106000
HIBERNATION_MODE=none
LAST_MEANINGFUL_AT=2026-04-02T05:00:00+02:00
LAST_MEANINGFUL_EPOCH=1775106000
LAST_MEANINGFUL_REASON=stale active_polecats=3
LAST_WAKE_AT=
LAST_WAKE_REASON=
STATE

sgt status --json > "$SGT_ROOT/status.json"
sgt mayor rig-status demo > "$SGT_ROOT/rig-status.txt"

python3 - "$SGT_ROOT/status.json" <<'PY'
import json
import sys

payload = json.load(open(sys.argv[1], "r", encoding="utf-8"))
rigs = {entry["rig"]: entry for entry in payload.get("mayor_rigs", [])}
demo = rigs.get("demo")
assert demo is not None, payload
reason = demo.get("reason", "")
assert "active_polecats=0" in reason, demo
assert "active_polecats=3" not in reason, demo
assert payload.get("summary", {}).get("polecat_count") == 0, payload
PY

head -n 1 "$SGT_ROOT/rig-status.txt" | grep -q 'active_polecats=0' || {
echo "expected mayor rig-status to use live active_polecats=0" >&2
cat "$SGT_ROOT/rig-status.txt" >&2
exit 1
}
if head -n 1 "$SGT_ROOT/rig-status.txt" | grep -q 'active_polecats=3'; then
echo "rig-status relayed stale active_polecats=3" >&2
cat "$SGT_ROOT/rig-status.txt" >&2
exit 1
fi
BASH

echo "ALL TESTS PASSED"
3 changes: 3 additions & 0 deletions test_sweep_backend_limited_skip.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ log_event() {
_mayor_rig_manually_hibernated() { return 1; }
_repo_owner_repo() { printf '%s\n' "${1#https://github.com/}"; }
_escape_quotes() { printf '%s' "$1"; }
_gh_issue_labels_live() {
gh issue view "$2" --repo "$1" --json labels --jq '.labels[].name'
}
_resling_find_existing_issue_polecat() { return 1; }
_sweep_watchdog_find_open_pr_for_issue() { return 1; }
_ai_backend_default() { echo "codex"; }
Expand Down
15 changes: 15 additions & 0 deletions test_witness_alive_stall_classification.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ eval "$(extract_fn _polecat_created_age_seconds)"
eval "$(extract_fn _polecat_session_root_pid)"
eval "$(extract_fn _polecat_find_busy_child)"
eval "$(extract_fn _polecat_runtime_classify)"
eval "$(extract_fn _polecat_issue_title)"
eval "$(extract_fn _witness_pr_meta)"
eval "$(extract_fn _witness_loop)"
eval "$(extract_fn _mayor_rig_activity_enabled)"
Expand Down Expand Up @@ -70,6 +71,20 @@ rig_path() {
}

_escape_quotes() { printf '%s' "$1"; }
_workflow_backend_default() { echo "github"; }
_forge_pr_find_by_head_tsv() { return 0; }
_forge_issue_field() {
local _backend="$1" _repo="$2" issue="$3" field="$4"
if [[ "$field" == "title" ]]; then
gh issue view "$issue" --repo "$_repo" --json title --jq '.title // ""'
return
fi
return 1
}
_forge_issue_comment_add() {
local _backend="$1" repo="$2" issue="$3" body="$4"
gh issue comment "$issue" --repo "$repo" --body "$body"
}
_write_agent_heartbeat() { :; }
_wake_refinery() { printf '%s\n' "$1|$2" >> "$WAKE_FILE"; }
_ai_backend_default() { echo "codex"; }
Expand Down
19 changes: 19 additions & 0 deletions test_witness_codex_usage_limit_block.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extract_fn() {
}

eval "$(extract_fn _witness_record_backend_limit_followup)"
eval "$(extract_fn _polecat_issue_title)"
eval "$(extract_fn _polecat_output_log_path)"
eval "$(extract_fn _witness_dead_polecat_backend_limit)"
eval "$(extract_fn _witness_pr_meta)"
Expand Down Expand Up @@ -97,6 +98,24 @@ _ensure_labels_exist() {
printf '%s\n' "$*" >> "$LABEL_FILE"
}

_workflow_backend_default() { echo "github"; }
_forge_pr_find_by_head_tsv() { return 0; }
_forge_issue_field() {
local _backend="$1" _repo="$2" issue="$3" field="$4"
if [[ "$field" == "title" ]]; then
gh issue view "$issue" --repo "$_repo" --json title --jq '.title // ""'
return
fi
return 1
}
_forge_issue_add_labels() {
local _backend="$1" _repo="$2" issue="$3" labels="$4"
printf '%s|%s\n' "$issue" "$labels" >> "$GH_EDIT_FILE"
}
_forge_issue_comment_add() {
local _backend="$1" repo="$2" issue="$3" body="$4"
gh issue comment "$issue" --repo "$repo" --body "$body"
}
_write_agent_heartbeat() { :; }
_wake_refinery() { :; }
_pr_head_sha() { echo "deadbeef"; }
Expand Down
Loading
Loading