fix: increase execution limits and pass them to server dispatch #2

Closed
rileyseaburg wants to merge 5 commits from fix/silent-partial-completion into main
rileyseaburg commented 2026-04-30 21:20:33 +00:00 (Migrated from github.com)

Problem

Server-dispatched tasks were running out of execution budget before pushing commits. Issue #505 on spotlessbinco completed (status: completed) but output was truncated mid-sentence and branch was never pushed.

Changes

  • max_steps: 30 → 50 (now documented as applying to both local AND server mode)
  • task_wait_seconds: 1800 → 3600 (30min → 1 hour)
  • server.sh build_metadata_json(): Pass max_steps and task_timeout_seconds in the task dispatch metadata so the server-side agent uses the caller's execution budget instead of server defaults

Test Plan

  • Re-trigger issue #505 processing on spotlessbinco
  • Verify task output is not truncated
  • Verify branch is pushed and PR is created
## Problem Server-dispatched tasks were running out of execution budget before pushing commits. Issue #505 on spotlessbinco completed (status: completed) but output was truncated mid-sentence and branch was never pushed. ## Changes - **max_steps**: 30 → 50 (now documented as applying to both local AND server mode) - **task_wait_seconds**: 1800 → 3600 (30min → 1 hour) - **server.sh build_metadata_json()**: Pass `max_steps` and `task_timeout_seconds` in the task dispatch metadata so the server-side agent uses the caller's execution budget instead of server defaults ## Test Plan - Re-trigger issue #505 processing on spotlessbinco - Verify task output is not truncated - Verify branch is pushed and PR is created
gemini-code-assist[bot] (Migrated from github.com) reviewed 2026-04-30 21:22:12 +00:00
gemini-code-assist[bot] (Migrated from github.com) left a comment

Code Review

This pull request significantly enhances the CodeTether GitHub Action by introducing robust logging, artifact persistence, and a "fail closed" mechanism. It adds a local-mode issue handler that automates the branch-edit-commit-push-PR workflow and improves error handling across both local and server modes. Key additions include a log directory for artifact uploads, structured logging functions, and a job summary written to GITHUB_STEP_SUMMARY. Feedback focuses on improving the reliability of the shell scripts: logging functions should output to stderr to prevent polluting captured stdout in subshells, and temporary files for API responses should use mktemp to avoid collisions. Additionally, suggestions were made to handle empty API responses safely when piping to jq and to use character-aware parameter expansion for string truncation to prevent splitting multi-byte UTF-8 characters.

## Code Review This pull request significantly enhances the CodeTether GitHub Action by introducing robust logging, artifact persistence, and a "fail closed" mechanism. It adds a local-mode issue handler that automates the branch-edit-commit-push-PR workflow and improves error handling across both local and server modes. Key additions include a log directory for artifact uploads, structured logging functions, and a job summary written to GITHUB_STEP_SUMMARY. Feedback focuses on improving the reliability of the shell scripts: logging functions should output to stderr to prevent polluting captured stdout in subshells, and temporary files for API responses should use mktemp to avoid collisions. Additionally, suggestions were made to handle empty API responses safely when piping to jq and to use character-aware parameter expansion for string truncation to prevent splitting multi-byte UTF-8 characters.
@ -39,6 +39,12 @@ mkdir -p "${CODETETHER_ARTIFACT_DIR}"
# Touch the log file so it always exists
: > "${CODETETHER_LOG_FILE}"
gemini-code-assist[bot] (Migrated from github.com) commented 2026-04-30 21:22:12 +00:00

high

Logging functions should direct their output to stderr. Currently, log_info and the ::error:: command in log_error output to stdout. If these functions are called within a subshell whose stdout is captured (for example, resp=$(github_api_post ...)), the log messages will be included in the captured variable, which will likely cause subsequent JSON parsing with jq to fail.

log_info()  { local msg="[$(date -Iseconds)] INFO: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; }
log_warn()  { local msg="[$(date -Iseconds)] WARN: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; }
log_error() { local msg="[$(date -Iseconds)] ERROR: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; echo "::error::$*" >&2; }
![high](https://www.gstatic.com/codereviewagent/high-priority.svg) Logging functions should direct their output to stderr. Currently, `log_info` and the `::error::` command in `log_error` output to stdout. If these functions are called within a subshell whose stdout is captured (for example, `resp=$(github_api_post ...)`), the log messages will be included in the captured variable, which will likely cause subsequent JSON parsing with `jq` to fail. ```suggestion log_info() { local msg="[$(date -Iseconds)] INFO: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; } log_warn() { local msg="[$(date -Iseconds)] WARN: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; } log_error() { local msg="[$(date -Iseconds)] ERROR: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; echo "::error::$*" >&2; } ```
gemini-code-assist[bot] (Migrated from github.com) commented 2026-04-30 21:22:12 +00:00

medium

Using a fixed path like /tmp/codetether-gh-response.json for API responses can lead to collisions or permission issues if multiple instances of the action run in the same environment. It is safer to use mktemp to create a unique temporary file and ensure it is removed after use.

  local http_code tmp_resp
  tmp_resp=$(mktemp)
  http_code=$(curl -sS -o "$tmp_resp" -w "%{http_code}" \
    -X POST \
    -H "Authorization: token ${GITHUB_TOKEN}" \
    -H "Accept: application/vnd.github.v3+json" \
    "https://api.github.com${path}" \
    -d "$payload" 2>> "${CODETETHER_LOG_FILE}") || :
  [ -z "$http_code" ] && http_code="000"
  if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
    log_error "${desc} failed (HTTP ${http_code}): $(cat "$tmp_resp" 2>/dev/null || echo 'no response body')"
    rm -f "$tmp_resp"
    return 1
  fi
  cat "$tmp_resp"
  rm -f "$tmp_resp"
![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg) Using a fixed path like `/tmp/codetether-gh-response.json` for API responses can lead to collisions or permission issues if multiple instances of the action run in the same environment. It is safer to use `mktemp` to create a unique temporary file and ensure it is removed after use. ```suggestion local http_code tmp_resp tmp_resp=$(mktemp) http_code=$(curl -sS -o "$tmp_resp" -w "%{http_code}" \ -X POST \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com${path}" \ -d "$payload" 2>> "${CODETETHER_LOG_FILE}") || : [ -z "$http_code" ] && http_code="000" if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then log_error "${desc} failed (HTTP ${http_code}): $(cat "$tmp_resp" 2>/dev/null || echo 'no response body')" rm -f "$tmp_resp" return 1 fi cat "$tmp_resp" rm -f "$tmp_resp" ```
gemini-code-assist[bot] (Migrated from github.com) commented 2026-04-30 21:22:12 +00:00

medium

If the response variable is empty (e.g., if the API call failed), echo "$response" will produce a newline, which causes jq to fail with a parse error. Using ${response:-{}} provides a safe default for jq to process.

  actual_sha=$(echo "${response:-{}}" | jq -r '.commit.sha // empty' 2>/dev/null) || true
![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg) If the `response` variable is empty (e.g., if the API call failed), `echo "$response"` will produce a newline, which causes `jq` to fail with a parse error. Using `${response:-{}}` provides a safe default for `jq` to process. ```suggestion actual_sha=$(echo "${response:-{}}" | jq -r '.commit.sha // empty' 2>/dev/null) || true ```
@ -0,0 +42,4 @@
local ec=$?
checkpoint "handle_issue_local: AFTER run_local_codetether — exit_code=${ec}"
local review_text
review_text=$(head -c 65000 "$output_file")
gemini-code-assist[bot] (Migrated from github.com) commented 2026-04-30 21:22:13 +00:00

medium

Using head -c to truncate output can split multi-byte UTF-8 characters, which may result in invalid strings that the GitHub API might reject. A safer way to truncate strings in Bash (which is character-aware) is using parameter expansion.

  review_text=$(cat "$output_file")
  review_text="${review_text:0:65000}"
![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg) Using `head -c` to truncate output can split multi-byte UTF-8 characters, which may result in invalid strings that the GitHub API might reject. A safer way to truncate strings in Bash (which is character-aware) is using parameter expansion. ```suggestion review_text=$(cat "$output_file") review_text="${review_text:0:65000}" ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-04-30 21:24:25 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Updates the CodeTether GitHub Action to reduce server-mode truncation/timeouts by increasing execution budgets and ensuring those budgets are passed through in server task dispatch metadata. It also adds more robust diagnostics/log persistence and improves failure handling for local/server flows.

Changes:

  • Increase default execution limits (max_steps to 50, task_wait_seconds to 3600) and document applicability to server+local.
  • Pass max_steps and task_timeout_seconds in server dispatch metadata and improve server polling/dispatch logging + artifact capture.
  • Add “fail closed” behavior and push verification, plus a new local-mode issue→branch→commit→push→PR workflow.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
action/lib/server.sh Adds structured logging/artifacts, improves curl error handling, and includes execution budgets in dispatch metadata.
action/lib/local.sh Adds artifact persistence and stricter failure handling; adjusts prompt formatting.
action/lib/issue.sh New local-mode issue handler that creates a branch, runs codetether, pushes, and opens a PR.
action/lib/github.sh Adds GitHub API helpers for POST/PR creation and push verification.
action/lib/common.sh Introduces persistent logs/artifacts and a run finalization summary helper.
action/entrypoint.sh Adds issue handling flow, fail-closed server behavior, and task_id output wiring.
action.yml Updates defaults/docs, adds fail_on_error input and task_id output, uploads logs artifact.
.gitignore Ignores .codetether-agent/.
Comments suppressed due to low confidence (1)

action/lib/server.sh:150

  • poll_task_result now returns from each branch, but the export TASK_STATUS after the if/elif/else is unreachable. Removing the dead code (or moving the export before returning) will make the control flow clearer.
  fi

  export TASK_STATUS
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull request overview Updates the CodeTether GitHub Action to reduce server-mode truncation/timeouts by increasing execution budgets and ensuring those budgets are passed through in server task dispatch metadata. It also adds more robust diagnostics/log persistence and improves failure handling for local/server flows. **Changes:** - Increase default execution limits (`max_steps` to 50, `task_wait_seconds` to 3600) and document applicability to server+local. - Pass `max_steps` and `task_timeout_seconds` in server dispatch metadata and improve server polling/dispatch logging + artifact capture. - Add “fail closed” behavior and push verification, plus a new local-mode issue→branch→commit→push→PR workflow. ### Reviewed changes Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | action/lib/server.sh | Adds structured logging/artifacts, improves curl error handling, and includes execution budgets in dispatch metadata. | | action/lib/local.sh | Adds artifact persistence and stricter failure handling; adjusts prompt formatting. | | action/lib/issue.sh | New local-mode issue handler that creates a branch, runs codetether, pushes, and opens a PR. | | action/lib/github.sh | Adds GitHub API helpers for POST/PR creation and push verification. | | action/lib/common.sh | Introduces persistent logs/artifacts and a run finalization summary helper. | | action/entrypoint.sh | Adds issue handling flow, fail-closed server behavior, and task_id output wiring. | | action.yml | Updates defaults/docs, adds `fail_on_error` input and `task_id` output, uploads logs artifact. | | .gitignore | Ignores `.codetether-agent/`. | </details> <details> <summary>Comments suppressed due to low confidence (1)</summary> **action/lib/server.sh:150** * `poll_task_result` now returns from each branch, but the `export TASK_STATUS` after the `if/elif/else` is unreachable. Removing the dead code (or moving the export before returning) will make the control flow clearer. ``` fi export TASK_STATUS } ``` </details> --- 💡 <a href="/rileyseaburg/codetether-action/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
@ -39,6 +39,12 @@ mkdir -p "${CODETETHER_ARTIFACT_DIR}"
# Touch the log file so it always exists
: > "${CODETETHER_LOG_FILE}"
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-30 21:24:24 +00:00

log_error emits a GitHub Actions workflow command (::error::) using the raw message. If the message contains newlines, %, or sequences like ::add-mask:: (which can come from untrusted issue/PR content or server responses), this can break log formatting or enable workflow-command injection. Escape the message per GitHub command spec (%, \r, \n) before printing ::error::..., or avoid emitting workflow commands for untrusted text.

github_actions_escape() {
  local msg="$1"
  msg="${msg//'%'/'%25'}"
  msg="${msg//$'\r'/'%0D'}"
  msg="${msg//$'\n'/'%0A'}"
  printf '%s' "$msg"
}

log_info()  { local msg="[$(date -Iseconds)] INFO: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}"; }
log_warn()  { local msg="[$(date -Iseconds)] WARN: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; }
log_error() {
  local raw_msg="$*"
  local msg="[$(date -Iseconds)] ERROR: $raw_msg"
  echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2
  echo "::error::$(github_actions_escape "$raw_msg")"
}
`log_error` emits a GitHub Actions workflow command (`::error::`) using the raw message. If the message contains newlines, `%`, or sequences like `::add-mask::` (which can come from untrusted issue/PR content or server responses), this can break log formatting or enable workflow-command injection. Escape the message per GitHub command spec (%, \r, \n) before printing `::error::...`, or avoid emitting workflow commands for untrusted text. ```suggestion github_actions_escape() { local msg="$1" msg="${msg//'%'/'%25'}" msg="${msg//$'\r'/'%0D'}" msg="${msg//$'\n'/'%0A'}" printf '%s' "$msg" } log_info() { local msg="[$(date -Iseconds)] INFO: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}"; } log_warn() { local msg="[$(date -Iseconds)] WARN: $*"; echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2; } log_error() { local raw_msg="$*" local msg="[$(date -Iseconds)] ERROR: $raw_msg" echo "$msg" | tee -a "${CODETETHER_LOG_FILE}" >&2 echo "::error::$(github_actions_escape "$raw_msg")" } ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-30 21:24:23 +00:00

GitHub API branch endpoints require URL-encoding branch names. Using /branches/${branch} will fail for common branch names that contain / (e.g. feature/foo or codetether/issue-123), causing push verification to report a mismatch even when the push succeeded. URL-encode branch before building the API path (or use an API that accepts refs safely).

  local encoded_branch
  local ref_response
  encoded_branch=$(jq -rn --arg v "$branch" '$v|@uri')
  ref_response=$(curl -sS -o /dev/null -w "%{http_code}" \
    -H "Authorization: token ${GITHUB_TOKEN}" \
    -H "Accept: application/vnd.github.v3+json" \
    "https://api.github.com/repos/${REPO_FULL_NAME}/branches/${encoded_branch}" 2>> "${CODETETHER_LOG_FILE}") || :
GitHub API branch endpoints require URL-encoding branch names. Using `/branches/${branch}` will fail for common branch names that contain `/` (e.g. `feature/foo` or `codetether/issue-123`), causing push verification to report a mismatch even when the push succeeded. URL-encode `branch` before building the API path (or use an API that accepts refs safely). ```suggestion local encoded_branch local ref_response encoded_branch=$(jq -rn --arg v "$branch" '$v|@uri') ref_response=$(curl -sS -o /dev/null -w "%{http_code}" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/${REPO_FULL_NAME}/branches/${encoded_branch}" 2>> "${CODETETHER_LOG_FILE}") || : ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-30 21:24:24 +00:00

Same URL-encoding issue here: /repos/.../branches/${branch} will 404 for branches with /, and the function will then compare an empty actual_sha and fail verification. Encode branch (or fetch the ref via git ls-remote / an API endpoint where the ref is a query parameter) before calling github_api_get.

  local encoded_branch
  encoded_branch=$(jq -nr --arg v "$branch" '$v|@uri' 2>/dev/null) || encoded_branch="$branch"
  local response
  response=$(github_api_get "/repos/${REPO_FULL_NAME}/branches/${encoded_branch}" 2>/dev/null) || true
Same URL-encoding issue here: `/repos/.../branches/${branch}` will 404 for branches with `/`, and the function will then compare an empty `actual_sha` and fail verification. Encode `branch` (or fetch the ref via `git ls-remote` / an API endpoint where the ref is a query parameter) before calling `github_api_get`. ```suggestion local encoded_branch encoded_branch=$(jq -nr --arg v "$branch" '$v|@uri' 2>/dev/null) || encoded_branch="$branch" local response response=$(github_api_get "/repos/${REPO_FULL_NAME}/branches/${encoded_branch}" 2>/dev/null) || true ```
@ -24,13 +27,14 @@ run_local_codetether() {
# ── Gather PR diff, truncated to MAX_DIFF_LINES ──────────────────
gather_diff() {
echo "::group::Fetching PR diff"
checkpoint "local: BEFORE gather_diff"
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-30 21:24:25 +00:00

The review prompt now embeds triple backticks (```diff) inside a double-quoted string. In bash, backticks trigger command substitution even inside double quotes, so this can try to execute the contents between backticks and/or break the assignment. Use escaped backticks (```) again, or switch to a heredoc (cat <<'EOF' ... EOF) to include literal backticks safely.

The review prompt now embeds triple backticks (```diff) inside a double-quoted string. In bash, backticks trigger command substitution even inside double quotes, so this can try to execute the contents between backticks and/or break the assignment. Use escaped backticks (\`\`\`) again, or switch to a heredoc (cat <<'EOF' ... EOF) to include literal backticks safely.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-30 21:24:25 +00:00

build_metadata_json uses jq --argjson for max_steps and task_timeout_seconds, but these values come from action inputs (strings) and will cause jq to fail if a user supplies a non-integer (e.g. "50\n" or "1h"). Consider validating/coercing to an integer (e.g. tonumber) and/or failing with a clear error message before dispatching.

normalize_non_negative_integer() {
  local value="$1"
  local field_name="$2"
  local normalized

  normalized="$(printf '%s' "$value" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"

  if [[ ! "$normalized" =~ ^[0-9]+$ ]]; then
    log_error "${field_name} must be a non-negative integer, got: ${value}"
    return 1
  fi

  printf '%s\n' "$normalized"
}

# ── Build metadata JSON for task dispatch ────────────────────────
build_metadata_json() {
  local pr_number="${PR_NUMBER:-0}"
  local steps="${INPUT_MAX_STEPS:-50}"
  local timeout="${TASK_WAIT_SECONDS:-3600}"
  local normalized_steps
  local normalized_timeout

  normalized_steps="$(normalize_non_negative_integer "${steps}" "max_steps")" || return 1
  normalized_timeout="$(normalize_non_negative_integer "${timeout}" "task_timeout_seconds")" || return 1

  jq -n \
    --arg source "github-actions" \
    --arg repo "${REPO_FULL_NAME}" \
    --argjson pr_num "${pr_number:-0}" \
    --argjson max_steps "${normalized_steps}" \
    --argjson task_timeout_seconds "${normalized_timeout}" \
`build_metadata_json` uses `jq --argjson` for `max_steps` and `task_timeout_seconds`, but these values come from action inputs (strings) and will cause `jq` to fail if a user supplies a non-integer (e.g. "50\n" or "1h"). Consider validating/coercing to an integer (e.g. `tonumber`) and/or failing with a clear error message before dispatching. ```suggestion normalize_non_negative_integer() { local value="$1" local field_name="$2" local normalized normalized="$(printf '%s' "$value" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')" if [[ ! "$normalized" =~ ^[0-9]+$ ]]; then log_error "${field_name} must be a non-negative integer, got: ${value}" return 1 fi printf '%s\n' "$normalized" } # ── Build metadata JSON for task dispatch ──────────────────────── build_metadata_json() { local pr_number="${PR_NUMBER:-0}" local steps="${INPUT_MAX_STEPS:-50}" local timeout="${TASK_WAIT_SECONDS:-3600}" local normalized_steps local normalized_timeout normalized_steps="$(normalize_non_negative_integer "${steps}" "max_steps")" || return 1 normalized_timeout="$(normalize_non_negative_integer "${timeout}" "task_timeout_seconds")" || return 1 jq -n \ --arg source "github-actions" \ --arg repo "${REPO_FULL_NAME}" \ --argjson pr_num "${pr_number:-0}" \ --argjson max_steps "${normalized_steps}" \ --argjson task_timeout_seconds "${normalized_timeout}" \ ```
rileyseaburg commented 2026-04-30 21:30:11 +00:00 (Migrated from github.com)

🔍 Debug Checkpoints Added (ce51f47)

This commit adds 88 checkpoint calls across all shell scripts to create a detailed breadcrumb trail in the GitHub Actions logs.

What was added

Core infrastructure (common.sh):

  • checkpoint() function — logs timestamp, elapsed seconds, remaining time budget at every step
  • emergency_push_and_exit() — force-pushes current state when time budget is exhausted
  • CODETETHER_START_EPOCH / CODETETHER_TIME_BUDGET — shared timing state
  • Final checkpoint in finalize_run() with total elapsed time

Coverage (88 checkpoints total):

File Checkpoints Key coverage points
entrypoint.sh 29 startup, routing, server dispatch/poll, comment posting
issue.sh 26 branch creation, codetether run, git add/commit/push, PR creation
github.sh 8 API calls, push verification, commit verification
server.sh 7 dispatch curl, poll loop (every 50s), result fetch
local.sh 16 codetether run, diff gathering, fix application

What each checkpoint shows

[2026-04-30T21:29:45+00:00] CHECKPOINT: handle_issue_local: AFTER git commit — sha=ce51f478 | elapsed=142s | budget=1658s remaining

Time budget alerts

  • Warning when <60s remaining: "Consider prioritizing push"
  • Error when budget exceeded: "Push whatever you have NOW"

This should make it immediately obvious where the action spends its time and where it gets stuck or times out.

## 🔍 Debug Checkpoints Added (`ce51f47`) This commit adds **88 checkpoint calls** across all shell scripts to create a detailed breadcrumb trail in the GitHub Actions logs. ### What was added **Core infrastructure** (`common.sh`): - `checkpoint()` function — logs timestamp, elapsed seconds, remaining time budget at every step - `emergency_push_and_exit()` — force-pushes current state when time budget is exhausted - `CODETETHER_START_EPOCH` / `CODETETHER_TIME_BUDGET` — shared timing state - Final checkpoint in `finalize_run()` with total elapsed time **Coverage (88 checkpoints total)**: | File | Checkpoints | Key coverage points | |------|-------------|-------------------| | `entrypoint.sh` | 29 | startup, routing, server dispatch/poll, comment posting | | `issue.sh` | 26 | branch creation, codetether run, git add/commit/push, PR creation | | `github.sh` | 8 | API calls, push verification, commit verification | | `server.sh` | 7 | dispatch curl, poll loop (every 50s), result fetch | | `local.sh` | 16 | codetether run, diff gathering, fix application | ### What each checkpoint shows ``` [2026-04-30T21:29:45+00:00] CHECKPOINT: handle_issue_local: AFTER git commit — sha=ce51f478 | elapsed=142s | budget=1658s remaining ``` ### Time budget alerts - **Warning** when <60s remaining: "Consider prioritizing push" - **Error** when budget exceeded: "Push whatever you have NOW" This should make it immediately obvious where the action spends its time and where it gets stuck or times out.
rileyseaburg commented 2026-04-30 21:51:37 +00:00 (Migrated from github.com)

Closing this PR — it has merge conflicts with main (PR #1 was squash-merged, creating a divergent base). Also the CI run failed due to a shellcheck parse error in the CODETETHER_TIME_BUDGET arithmetic expression. I've created a clean replacement branch that resolves both issues.

Closing this PR — it has merge conflicts with main (PR #1 was squash-merged, creating a divergent base). Also the CI run failed due to a shellcheck parse error in the CODETETHER_TIME_BUDGET arithmetic expression. I've created a clean replacement branch that resolves both issues.

Pull request closed

Sign in to join this conversation.
No description provided.