From 5e18f795e3557f70ca2153d26dd37d3f34fecf30 Mon Sep 17 00:00:00 2001 From: tend-agent <270458913+tend-agent@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:25:52 +0000 Subject: [PATCH 1/4] skills(review-reviewers): sweep the window repo-wide before trusting a silent survey --- .../skills/review-reviewers/SKILL.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md index 764ddbb1..58b9694d 100644 --- a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md +++ b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md @@ -228,6 +228,19 @@ Use a cheap subagent (e.g. Haiku / gpt-mini) and a prompt like: > 1. Did the bot produce visible output (review, comment, issue action, commit)? > 2. If yes, was the output accepted or rejected? > +> **Sweep the window repo-wide before mapping any run, and report the row counts.** The per-run mapping below walks run → branch → PR → endpoint; a break anywhere in that chain returns empty for *every* run at once, and uniform silence reads as a quiet hour rather than as a broken query. These three calls take no run ID, so they fail independently of it: +> +> ```bash +> WINDOW_START= +> gh api "repos/$ARGUMENTS/issues/comments?since=$WINDOW_START&per_page=100" \ +> --jq "[.[] | select(.user.login == \"$BOT_LOGIN\")] | length" +> gh api "repos/$ARGUMENTS/pulls/comments?since=$WINDOW_START&per_page=100" \ +> --jq "[.[] | select(.user.login == \"$BOT_LOGIN\")] | length" +> gh -R $ARGUMENTS pr list --state all --search "updated:>$WINDOW_START" --json number --jq '[.[].number]' +> ``` +> +> The first two are the bot's conversation and inline-review comments. The third is the candidate list for the review and body queries further down, which have no `since` parameter of their own. Report all three counts at the top of your summary. If the sweep returns rows that your per-run walk did not reach, the walk is wrong — re-map from the PR numbers the sweep found rather than reporting those runs as silent. +> > **How to map runs to outputs:** > - `tend-review`: `gh -R $ARGUMENTS run view --json headBranch` → find PR via > `gh -R $ARGUMENTS pr list --head --state all` → check bot reviews via @@ -303,7 +316,7 @@ Use a cheap subagent (e.g. Haiku / gpt-mini) and a prompt like: > > ``` -Review the subagent's summary. If all outputs are accepted and no sanity-check flags, skip to Step 6 (summary). If concerning outcomes exist, continue to Step 3. +Review the subagent's summary. A report of little or no bot output is only usable if it carries the repo-wide sweep counts — without them, run the three sweep calls yourself before believing it, because a silent window and a broken per-run walk produce the same summary. Absence is also not a finding on its own: don't reason from it toward a conclusion the sweep would contradict. If all outputs are accepted and no sanity-check flags, skip to Step 6 (summary). If concerning outcomes exist, continue to Step 3. ## Step 3: Investigate concerning outcomes via cheap subagent From 2fcf4ac9e6082b11e492a9831ad22a22cd93f1bb Mon Sep 17 00:00:00 2001 From: tend-agent <270458913+tend-agent@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:39:56 +0000 Subject: [PATCH 2/4] skills(review-reviewers): bound the sweep counts to the window --- .../skills/review-reviewers/SKILL.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md index 58b9694d..4bbca13c 100644 --- a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md +++ b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md @@ -232,14 +232,17 @@ Use a cheap subagent (e.g. Haiku / gpt-mini) and a prompt like: > > ```bash > WINDOW_START= -> gh api "repos/$ARGUMENTS/issues/comments?since=$WINDOW_START&per_page=100" \ -> --jq "[.[] | select(.user.login == \"$BOT_LOGIN\")] | length" -> gh api "repos/$ARGUMENTS/pulls/comments?since=$WINDOW_START&per_page=100" \ -> --jq "[.[] | select(.user.login == \"$BOT_LOGIN\")] | length" +> WINDOW_END= +> IN_WINDOW="[.[] | select(.user.login == \"$BOT_LOGIN\") +> | select(.created_at >= \"$WINDOW_START\" and .created_at <= \"$WINDOW_END\")] | length" +> gh api "repos/$ARGUMENTS/issues/comments?since=$WINDOW_START&per_page=100" --jq "$IN_WINDOW" +> gh api "repos/$ARGUMENTS/pulls/comments?since=$WINDOW_START&per_page=100" --jq "$IN_WINDOW" > gh -R $ARGUMENTS pr list --state all --search "updated:>$WINDOW_START" --json number --jq '[.[].number]' > ``` > -> The first two are the bot's conversation and inline-review comments. The third is the candidate list for the review and body queries further down, which have no `since` parameter of their own. Report all three counts at the top of your summary. If the sweep returns rows that your per-run walk did not reach, the walk is wrong — re-map from the PR numbers the sweep found rather than reporting those runs as silent. +> Filter both comment calls on `created_at` at both ends. `since` is an `updated_at` floor with no ceiling, so unfiltered it also returns comments written days earlier and merely edited in the window, plus everything posted between the window end and now — this skill starts 20–40 min after its tick, so on a busy repo that is most windows. Those are rows the per-run walk was right not to reach, and a check that contradicts a correct walk every run stops being believed. Leave the third call unbounded above: `updated:` matches the PR's own `updated_at`, so a range drops any PR that got bot output inside the window and was touched after it, and over-inclusion in a candidate list costs nothing. +> +> The first two counts cover conversation and inline-review comments only — neither endpoint returns review submissions, so a window whose sole output was a review reads zero there, and reviews are reachable only through the third call's PR list. Report all three at the top of your summary. If the sweep found in-window rows your per-run walk did not reach, the walk is wrong — re-map from the PR numbers the sweep found rather than reporting those runs as silent. > > **How to map runs to outputs:** > - `tend-review`: `gh -R $ARGUMENTS run view --json headBranch` → find PR via @@ -316,7 +319,9 @@ Use a cheap subagent (e.g. Haiku / gpt-mini) and a prompt like: > > ``` -Review the subagent's summary. A report of little or no bot output is only usable if it carries the repo-wide sweep counts — without them, run the three sweep calls yourself before believing it, because a silent window and a broken per-run walk produce the same summary. Absence is also not a finding on its own: don't reason from it toward a conclusion the sweep would contradict. If all outputs are accepted and no sanity-check flags, skip to Step 6 (summary). If concerning outcomes exist, continue to Step 3. +A report of little or no bot output is only usable if it carries the repo-wide sweep counts — without them, run the three sweep calls yourself before believing it, because a silent window and a broken per-run walk produce the same summary. Absence is not a finding on its own either: don't reason from it toward a conclusion the sweep would contradict. + +Review the subagent's summary. If all outputs are accepted and no sanity-check flags, skip to Step 6 (summary). If concerning outcomes exist, continue to Step 3. ## Step 3: Investigate concerning outcomes via cheap subagent From 30f276830aa1c8c7e99fe60be855bc4455cfda7c Mon Sep 17 00:00:00 2001 From: tend-agent <270458913+tend-agent@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:42:16 +0000 Subject: [PATCH 3/4] skills(review-reviewers): add the in-window review count and raise the pr list limit --- .../skills/review-reviewers/SKILL.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md index 4bbca13c..27de557a 100644 --- a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md +++ b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md @@ -228,21 +228,29 @@ Use a cheap subagent (e.g. Haiku / gpt-mini) and a prompt like: > 1. Did the bot produce visible output (review, comment, issue action, commit)? > 2. If yes, was the output accepted or rejected? > -> **Sweep the window repo-wide before mapping any run, and report the row counts.** The per-run mapping below walks run → branch → PR → endpoint; a break anywhere in that chain returns empty for *every* run at once, and uniform silence reads as a quiet hour rather than as a broken query. These three calls take no run ID, so they fail independently of it: +> **Sweep the window repo-wide before mapping any run, and report the row counts.** The per-run mapping below walks run → branch → PR → endpoint; a break anywhere in that chain returns empty for *every* run at once, and uniform silence reads as a quiet hour rather than as a broken query. These calls take no run ID, so they fail independently of it: > > ```bash > WINDOW_START= > WINDOW_END= > IN_WINDOW="[.[] | select(.user.login == \"$BOT_LOGIN\") -> | select(.created_at >= \"$WINDOW_START\" and .created_at <= \"$WINDOW_END\")] | length" +> | select((.created_at // .submitted_at) >= \"$WINDOW_START\" +> and (.created_at // .submitted_at) <= \"$WINDOW_END\")] | length" +> > gh api "repos/$ARGUMENTS/issues/comments?since=$WINDOW_START&per_page=100" --jq "$IN_WINDOW" > gh api "repos/$ARGUMENTS/pulls/comments?since=$WINDOW_START&per_page=100" --jq "$IN_WINDOW" -> gh -R $ARGUMENTS pr list --state all --search "updated:>$WINDOW_START" --json number --jq '[.[].number]' +> +> CANDIDATES=$(gh -R $ARGUMENTS pr list --state all --limit 100 \ +> --search "updated:>$WINDOW_START" --json number --jq '.[].number') +> echo "$CANDIDATES" +> for pr in $CANDIDATES; do +> gh api "repos/$ARGUMENTS/pulls/$pr/reviews?per_page=100" --jq "$IN_WINDOW" +> done | jq -s add > ``` > -> Filter both comment calls on `created_at` at both ends. `since` is an `updated_at` floor with no ceiling, so unfiltered it also returns comments written days earlier and merely edited in the window, plus everything posted between the window end and now — this skill starts 20–40 min after its tick, so on a busy repo that is most windows. Those are rows the per-run walk was right not to reach, and a check that contradicts a correct walk every run stops being believed. Leave the third call unbounded above: `updated:` matches the PR's own `updated_at`, so a range drops any PR that got bot output inside the window and was touched after it, and over-inclusion in a candidate list costs nothing. +> Filter the comment calls on `created_at` at both ends. `since` is an `updated_at` floor with no ceiling, so unfiltered it also returns comments written days earlier and merely edited in the window, plus everything posted between the window end and now — this skill starts 20–40 min after its tick, so on a busy repo that is most windows. Those are rows the per-run walk was right not to reach, and a check that contradicts a correct walk every run stops being believed. Leave `CANDIDATES` unbounded above: `updated:` matches the PR's own `updated_at`, so a range drops any PR that got bot output inside the window and was touched after it, and over-inclusion in a candidate list costs nothing. `--limit 100` is load-bearing — `gh pr list` defaults to 30 and truncates silently. > -> The first two counts cover conversation and inline-review comments only — neither endpoint returns review submissions, so a window whose sole output was a review reads zero there, and reviews are reachable only through the third call's PR list. Report all three at the top of your summary. If the sweep found in-window rows your per-run walk did not reach, the walk is wrong — re-map from the PR numbers the sweep found rather than reporting those runs as silent. +> The comment endpoints cover conversation and inline-review comments only; neither returns review submissions, and an empty-body `APPROVE` is `tend-review`'s most common output. Without the fourth count an approvals-only window reports `0, 0` and satisfies the gate below with two zeros carrying no signal. Report all four numbers at the top of your summary. If the sweep found in-window rows your per-run walk did not reach, the walk is wrong — re-map from the PR numbers the sweep found rather than reporting those runs as silent. > > **How to map runs to outputs:** > - `tend-review`: `gh -R $ARGUMENTS run view --json headBranch` → find PR via From 6c276a41f2ccba13f9838de57b79d1d11dc22815 Mon Sep 17 00:00:00 2001 From: tend-agent <270458913+tend-agent@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:50:24 +0000 Subject: [PATCH 4/4] skills(review-reviewers): point the gate at the sweep block, not three calls --- plugins/tend-ci-runner/skills/review-reviewers/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md index 27de557a..733130ef 100644 --- a/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md +++ b/plugins/tend-ci-runner/skills/review-reviewers/SKILL.md @@ -327,7 +327,7 @@ Use a cheap subagent (e.g. Haiku / gpt-mini) and a prompt like: > > ``` -A report of little or no bot output is only usable if it carries the repo-wide sweep counts — without them, run the three sweep calls yourself before believing it, because a silent window and a broken per-run walk produce the same summary. Absence is not a finding on its own either: don't reason from it toward a conclusion the sweep would contradict. +A report of little or no bot output is only usable if it carries the repo-wide sweep counts — without them, run the sweep block yourself before believing it, because a silent window and a broken per-run walk produce the same summary. Absence is not a finding on its own either: don't reason from it toward a conclusion the sweep would contradict. Review the subagent's summary. If all outputs are accepted and no sanity-check flags, skip to Step 6 (summary). If concerning outcomes exist, continue to Step 3.