Skip to content
Open
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
6 changes: 5 additions & 1 deletion .claude/skills/running-tend/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ Pass extra prefixes when running token reports or listing runs so these
workflows are included:

```bash
"${CLAUDE_PLUGIN_ROOT}/scripts/token-report.sh" 24 "review-"
"${CLAUDE_PLUGIN_ROOT}/scripts/token-report.sh" "${HOURS:-24}" "review-"
TARGET_REPO=max-sixty/tend "${CLAUDE_PLUGIN_ROOT}/scripts/list-recent-runs.sh" "tend-" "review-"
```

Under `review-runs`, `$HOURS` is the lookback derived from its Step 1 anchor —
passing a literal `24` there reopens the window gap that anchor closes. The
default keeps an ad-hoc invocation working.

## Labels

- `claude-behavior` — findings from `review-reviewers`
Expand Down
53 changes: 45 additions & 8 deletions plugins/tend-ci-runner/skills/review-runs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,30 @@ Never replace the body — prior entries contain per-run evidence needed for gat

## Step 1: Find recent runs

List tend CI runs that completed in the past 24 hours (the cron runs daily):
List tend CI runs that completed since the previous `review-runs` run (nominally 24 hours the cron runs daily):
Comment thread
tend-agent marked this conversation as resolved.

```bash
REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
SINCE=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)
# Anchor on the predecessor's start: a `date -d '24 hours ago'` resolves when
# the agent runs it, so the window opens after the predecessor started and
# drops the band in between. Steps 2 and 4 re-read the anchor from the file
# written below; shell variables don't survive between Bash tool calls.
#
# Derive the workflow id from this run rather than assuming the file name;
# exclude this run, because a re-run attempt of it can already read as
# completed and anchoring on itself collapses the window to zero.
# `status=success` reaches past a predecessor that died before its census, so
# that band still gets covered. Clamp a stale or missing anchor (an outage, or
# a fresh repo with no predecessor) so the window can recover one skipped day
# without pulling in a week — Step 5 dedups whatever a widened window sees
# twice.
WF_ID=$(gh api "repos/$REPO/actions/runs/$GITHUB_RUN_ID" --jq '.workflow_id')
PREV_START=$(gh api "repos/$REPO/actions/workflows/$WF_ID/runs?status=success&per_page=10" \
--jq "[.workflow_runs[] | select(.id != ${GITHUB_RUN_ID:-0}) | .created_at] | max // empty")
SINCE=${PREV_START:-$(date -u -d '25 hours ago' +%Y-%m-%dT%H:%M:%SZ)}
FLOOR=$(date -u -d '49 hours ago' +%Y-%m-%dT%H:%M:%SZ)
if [[ "$SINCE" < "$FLOOR" ]]; then SINCE=$FLOOR; fi
Comment thread
tend-agent marked this conversation as resolved.
echo "$SINCE" > /tmp/review-runs-since
# Add the repo's extra prefixes from its `running-tend` skill: any workflow
# running the tend action is in scope, not just the generated `tend-*` ones.
# Step 2 prices the same list.
Expand All @@ -142,15 +161,25 @@ SINCE=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)
# applying it per page is harmless.
PREFIXES=("tend-")
PREFIX_RE="^($(IFS='|'; echo "${PREFIXES[*]}"))"
# Census on *completion*, which is the axis that tiles. A run created before
# `$SINCE` may still have been in progress at the predecessor's census, so
# `status=completed` dropped it there — filtering on `created` here would drop
# it again and nobody would ever see it, and those are the long-running runs
# Step 3 goes on to hunt. So over-fetch by `created` and filter on
# `updated_at`, as `list-recent-runs.sh` does. The floor is a run's whole
# lifetime, not its job cap: `created_at` starts at queue time, and a
# `cancel-in-progress: false` group can hold a run queued for many hours
# before its 6h of execution even begins.
FETCH_FROM=$(date -u -d "$SINCE - 24 hours" +%Y-%m-%dT%H:%M:%SZ)
for workflow in $(gh api --paginate repos/$REPO/actions/workflows --jq ".workflows[] | select(.name | test(\"$PREFIX_RE\")) | .id"); do
gh api --paginate "repos/$REPO/actions/workflows/$workflow/runs?created=>=$SINCE&status=completed&per_page=100" \
--jq '.workflow_runs[] | {databaseId: .id, conclusion, createdAt: .created_at, name: .name}'
gh api --paginate "repos/$REPO/actions/workflows/$workflow/runs?created=>=$FETCH_FROM&status=completed&per_page=100" \
--jq ".workflow_runs[] | select(.updated_at >= \"$SINCE\") | {databaseId: .id, conclusion, createdAt: .created_at, updatedAt: .updated_at, name: .name}"
done
```

If no runs found, report "no runs to review" and exit.

Report the run census as the count this returns. Cross-check any workflow whose count lands on a round page boundary (30, 100) against `.total_count` before trusting it — a count that equals the page size is the signature of a page that was never followed.
Report the run census as the count this returns. `.total_count` counts the wider `FETCH_FROM` fetch, so it bounds the census from above rather than matching it — but a census that lands on a round page boundary (30, 100) is still the signature of a page that was never followed, so check that one against `.total_count` before trusting it.

Then, for each run ID from above, pull its jobs and classify them:

Expand All @@ -175,10 +204,15 @@ After retrieving the timeout cap from the workflow file, flag any job whose dura
Run the token report script to get per-run token counts:

```bash
"${CLAUDE_PLUGIN_ROOT}/scripts/token-report.sh" 24 > /tmp/token-report.json
# Whole hours back to Step 1's anchor, rounded up so the whole band is priced.
# A literal `24` reopens the gap Step 1 closed. The `cat` isn't optional: an
# unset `$SINCE` makes `date -d ""` today's midnight, not an error.
SINCE=$(cat /tmp/review-runs-since)
HOURS=$(( ( $(date -u +%s) - $(date -u -d "$SINCE" +%s) + 3599 ) / 3600 ))
Comment thread
tend-agent marked this conversation as resolved.
"${CLAUDE_PLUGIN_ROOT}/scripts/token-report.sh" "$HOURS" > /tmp/token-report.json
```

Pass the same extra prefixes Step 1 censuses, so the two steps agree on what the fleet is — the repo's `running-tend` skill is the source for both (e.g. `review-` for a `review-reviewers` workflow that uses the tend action but isn't named `tend-*`).
Pass the same extra prefixes Step 1 censuses (after `$HOURS`, which the script reads as its first positional arg), so the two steps agree on what the fleet is — the repo's `running-tend` skill is the source for both (e.g. `review-` for a `review-reviewers` workflow that uses the tend action but isn't named `tend-*`).

Include the totals and per-workflow breakdown in the summary (Step 7). Flag any runs with unusually high token usage for closer inspection in Step 3.

Expand All @@ -200,7 +234,10 @@ For each analyzed run, compare what the bot did against what happened next. The
mention, notifications, weekly, and review-reviewers runs get the same treatment: find the bot's output and check whether it was accepted.

```bash
# Example: check if a bot PR was merged or closed
# Example: check if a bot PR was merged or closed. Re-read Step 1's anchor —
# unset here, an empty string compares less than every non-null `closedAt` and
# the check silently stops being windowed at all.
SINCE=$(cat /tmp/review-runs-since)
gh pr list --author "$BOT_LOGIN" --state all --json number,title,state,closedAt \
--jq '.[] | select(.closedAt > "'$SINCE'")'
```
Expand Down
Loading