chore: update tend workflows (0.1.14 → 0.1.17) - #85
Conversation
cargo-affected-bot
left a comment
There was a problem hiding this comment.
Verified this is a faithful regeneration rather than a hand-edit: I installed the 0.1.15 generator from the upstream tag and ran tend init against this repo's .config/tend.yaml into a scratch tree, and the eight files come out byte-identical to this PR's. All eight parse as YAML. Nothing on the adopter side is missing for the new machinery — .config/tend.yaml carries none of the four secrets.* name overrides 0.1.15 removes, so there is no config migration to do; every gh call in the generated steps runs under TEND_BOT_TOKEN rather than the job's GITHUB_TOKEN, so the unchanged permissions: block does not need statuses: write for the new tend-review/<pr> stamp; and run_issue_ensure_label creates the tend-rate-limit label the two new if: guards reference. No defect found in the diff itself.
One consequence worth deciding before this lands, and it cuts against the obvious reading. #80 adds three review-runs corrections to the local overlay, and 0.1.15 carries two of them upstream nearly verbatim: the predecessor-anchored window with the 49h floor and /tmp/review-runs-since (tend#939), and the paginated census with updated_at windowing plus the .total_count cross-check (tend#886). Those two become duplicates once the pin moves — #80's own body names this pin bump as the trigger to drop one of them.
The evidence-log selector section does not become redundant, and the upstream version is the weaker of the two. 0.1.15's review-runs resolves the log with test("^## Run [0-9]"), but jq's ^ anchors to the start of the string, not the line, so a rollover comment — which opens with the appended entry's own blank line or --- separator, not the heading — fails it. Measured against the live trackers just now:
tracker #62 (rolled over) ^## Run [0-9] (^|\n)## Run [0-9]
4852429465 "## Run 28505825777 — 202" 50513B true true
4933725185 "\n## Run 29081041973 — 20" 49882B false true
5020367025 "\n\n---\n\n## Run 2972877" 53815B false true
5115269072 "\n\n---\n\n## Run 3043648" 14314B false true <- the live one
So on #62 the upstream filter keeps only the oldest comment — the 50513-byte one that was superseded precisely because it was near GitHub's 65536-byte body limit — and | last then appends there. On the current tracker #73 every log comment happens to start at offset 0, so upstream's selector picks correctly today; the divergence surfaces at the next rollover, silently, since the PATCH returns 200 either way. #80's (^|\n)## Run form selects all four.
Net: after this merges, the right disposition for #80 is to keep the evidence-log section and drop the other two, not to close it as superseded.
How this was verified
Regeneration fidelity — installed generator/ from max-sixty/tend at tag 0.1.15 into a venv, copied this repo's .config/tend.yaml into a scratch dir, ran tend init, then diff -ru against .github/workflows/ excluding the repo-owned ci.yaml and release.yaml: no differences.
jq anchoring — jq-1.7: '"x\n\n---\n\n## Run 123"' | jq 'test("^## Run [0-9]")' → false; the same input with test("(^|\n)## Run [0-9]") → true.
Tracker shapes — gh api --paginate "repos/max-sixty/cargo-affected/issues/{62,73}/comments?per_page=100", projecting {id, size, head, anchored, lineanchored} per bot comment.
Upstream coverage — plugins/tend-ci-runner/skills/review-runs/SKILL.md at 0.1.15: line 97 (selector), lines 148–154 (PREV_START / FLOOR / /tmp/review-runs-since), lines 176–179 (--paginate + per_page=100 + updated_at filter), line 184 (.total_count cross-check).
Token wiring — claude/action.yaml at 0.1.15 sets GITHUB_TOKEN: ${{ inputs.github_token }} on every step that shells out; the generated workflows pass github_token: ${{ secrets.TEND_BOT_TOKEN }}.
Label creation — shared/steps/lib/run-issue.sh, run_issue_ensure_label(): gh label create ... 2>/dev/null || true, called by rate-limit-preflight.sh with PAUSE_LABEL="tend-rate-limit".
cargo-affected-bot
left a comment
There was a problem hiding this comment.
Re-verified against 0.1.17, since the earlier review on this PR was stamped at 0.1.15 and two releases have landed on the branch since. Installing the generator from the upstream 0.1.17 tag and running tend init against this repo's .config/tend.yaml in a scratch tree reproduces all eight files byte-identically; each parses as YAML; tend check at 0.1.17 reports all eight checks PASS here, which is the claim the description makes about #34.
Two corrections, both to the description rather than the diff — I've applied them to the body.
The pre-check rewrite is not a widening. The description claimed bot review, APPROVED, empty body, with fresh (non-reply) inline comments, on a bot-authored PR flipped from should_run=false to true. That input is unreachable: GitHub refuses a self-approval, so a bot APPROVED review on a bot-authored PR never exists — and no bot-authored PR in this repo's last 25 carries one. Walking every other reachable input through both gate orders gives the same answer before and after, which is what tend#965 means by "outward behavior is unchanged". Worth having got right: a claimed behavior change in a security-adjacent gate is the kind of thing that gets audited later against a diff that doesn't contain it.
#80 is now fully superseded, not superseded in part. The earlier review measured #80's three review-runs corrections against 0.1.15 and concluded the evidence-log selector section should be kept, because 0.1.15's test("^## Run [0-9]") anchors to the start of the string and so misses a rollover comment opening with a blank line or ---. 0.1.16 fixed exactly that (tend#963) — 0.1.17 ships test("(^|\n)## Run [0-9]"). With the predecessor-anchored window and the paginated census already carried at 0.1.15, all three sections become duplicates when this pin moves, so #80 can be closed rather than trimmed.
How this was verified
Regeneration fidelity — pip install of generator/ from max-sixty/tend at tag 0.1.17 into a venv; scratch dir with this repo's .config/tend.yaml and an origin remote pointing at this repo; tend init; then diff -u per file against .github/workflows/: eight of eight identical. tend check run from the repo checkout under the bot's token: branch-protection:main, bot-permission, environment, environment-deployments, credential-environments, secrets, claude-auth, repo-secret-allowlist all PASS.
Gate equivalence — enumerated the pull_request_review inputs across both orders. 0.1.15: empty-body-APPROVED gate → inline @-mention → reply-only container gate → contentless-approval gate → PR_AUTHOR short-circuit → author-keyed bot-review gate. 0.1.17: inline @-mention → contentless-approval gate → bot-review gate (PR_AUTHOR == BOT && (body || FRESH_INLINE > 0)) → PR_AUTHOR short-circuit. Bot review on a human PR: false both. Bot review on a bot PR with a body, or with a fresh inline comment: true both. Reply-only container: false both (0.1.15 via the container gate, 0.1.17 via FRESH_INLINE == 0). Empty body and no inline comments: false both. Non-bot reviews are untouched — the contentless-approval gate is author-agnostic in both. Only the APPROVED leg diverges, and it is the unreachable one. Self-approval absence checked with gh api repos/max-sixty/cargo-affected/pulls/<n>/reviews over the last 25 bot-authored PRs, filtering state == "APPROVED" and user.login == "cargo-affected-bot": no rows.
Selector fix — plugins/tend-ci-runner/skills/review-runs/SKILL.md at each tag: 0.1.15 line 97 test("^## Run [0-9]"), 0.1.16 line 102 and 0.1.17 line 102 test("(^|\n)## Run [0-9]"). tend#963's changelog entry names the same mechanism the earlier review measured on tracker #62. The one residual delta from #80 is that upstream fetches the tracking issue's comments unpaginated where #80 passes per_page=100; the monthly trackers hold 3–5 comments each (#30, #44, #62, #73), so page 1 covers them.
Eyes machinery — the add/remove pairs are conditioned on the same predicate on both sides: tend-triage unconditional within the job plus if: always(); tend-review both on steps.gate.outputs.should_run == 'true'; tend-mention both on the mention arms, with handle gated on the same should_run that gates the verify-side add. always() runs on cancellation, so a cancelled session releases the reaction rather than stranding it. TARGET resolves to issues/comments/{id} only for issue_comment and to pulls/comments/{id} otherwise; verify's job-level if admits only repository_dispatch, issues, and issue_comment, and the react step's own if requires either github.event.comment (present only for issue_comment among those) or a relayed pull_request_review_comment, so both arms address the endpoint that owns the comment. gh api --silent is a real flag on the runner's gh 2.97.0.
Nightly regeneration of the tend workflow files. This PR now carries three releases — it opened on 0.1.15, the 2026-08-14 nightly folded 0.1.16 in, and tonight's run adds 0.1.17.
tend version: 0.1.14 → 0.1.17
Notable changes in 0.1.17
tend-review.yamlandtend-triage.yamleach gain a "React with eyes" step before the agent and anif: always()"Remove the eyes reaction" step after it, andtend-mention.yaml's existing pair is rewritten to address the comment through a single precomputedTARGETinstead of trying theissuesandpullsendpoints in sequence.tend checkreads the bot's own bypass verdict when the ruleset's actor list is withheld (check: read the bot's own bypass verdict where the actor list is withheld tend#976) — the path this repo'sbranch-protection:maincheck goes through.tend checkreports all-PASShere tonight, which is why tend check: configuration drift on max-sixty/cargo-affected #34 is now closed.Notable changes in 0.1.14 → 0.1.16 (carried from the earlier commits on this branch)
tend-reviewno longer cancels itself on a push. The job moves tocancel-in-progress: falseand gains an examined-HEAD gate: a push mid-review is folded into the running session, which stamps each commit it examined, and the queued replacement run exits without booting an agent when the live HEAD is already covered (feat(review): queue pushes behind an examined-HEAD gate instead of cancelling tend#903, fix(review): re-review after a force-push instead of trusting the re-anchored review SHA tend#884, fix(running-in-ci): batch pushes so the author doesn't cancel its own reviewer tend#868)./code-reviewsecond pass now runs unconditionally rather than at the agent's discretion (fix(review): submit the review before pushing a fix tend#834, fix(review): make the code-review second pass unconditional tend#937).tend checkis more honest about what it can't read — an unreadable ruleset bypass list reports as unknown rather than ungated, andcredential-environmentsstops pointing at a setting it rejects (check: report an unreadable ruleset bypass list as unknown, not ungated tend#825, fix(check): stop pointing credential-environments at the setting it rejects tend#900).tend-mention's pre-check is rewritten and shrinks by ~120 lines: the self-summons gates are collapsed into one and the bot login is read from a newBOT_NAMEenv var instead of being interpolated as a literal in eight places (simplify: coarser mention gates, tested poll scripts, anchor-based run window tend#965, test(mention): run the verify gate instead of matching its text tend#970). Judged on its own — the 0.1.15 gate order against the 0.1.17 one — that rewrite is behavior-neutral, for the reason the previous revision of this bullet gave: the single input where the two orders disagree (bot review,APPROVED, empty body, fresh non-reply inline comments, bot-authored PR) is unreachable, since GitHub refuses a self-approval and no such review exists across the 40 most recent PRs here. What merging this PR does is a different question, because the span starts at the 0.1.14 gatemainactually runs, and there behavior does change. Two reachable inputs move, both fromshould_run=truetofalse, and both are the intended effect of gates this PR brings in: (1) a bot review on a bot-authored PR carrying no body and no fresh inline comment — the synthetic container GitHub wraps around the bot's own inline reply — stops booting a session; that gate arrives at 0.1.15 as the tend-mention: an inline reply's synthetic review container starts a full session — the empty-body skip only covers APPROVED tend#866 fix, and review-runs-tracking: 2026-08 #73 records it starting no-op sessions on five separate days before then; (2) a bot review on a human-authored PR that isn't a bare empty-body approval — the bodiedCOMMENTthis workflow posts whenever it has findings — stops booting one at all, on the reasoning that the review session already did whatever the review warranted. Both earlier revisions of this bullet got the merge-level claim wrong in opposite directions (first "widening", then "neutral"); each was written by diffing the increment that run had just added rather thanmain, which is the mismatch filed as running-in-ci: PR-description edits are scoped to the whole PR, but the run's diff is scoped to LAST_REVIEW_SHA tend#991.review-runsanchors its evidence-log selector with(^|\n)rather than^(fix(review-runs): line-anchor the evidence-log selector tend#963), joining the predecessor-anchored window (fix(review-runs): anchor the census window on the predecessor run, not now-24h tend#939) and the paginated census (fix(review-runs): page the run census, so a day's window isn't the last hour tend#886) already carried at 0.1.15. Those are all three of the corrections skills(running-tend): correct three review-runs recipes the pinned tend release still ships broken #80 holds in the local overlay, so skills(running-tend): correct three review-runs recipes the pinned tend release still ships broken #80 is fully superseded once this lands — not superseded in part, as the earlier review on this PR concluded against 0.1.15.tend-weeklystops trusting a re-anchored approval on a rebased dependency PR (skills: gate self-initiated fixes on cost, not just evidence tend#960, fix(weekly): don't trust a re-anchored approval on a rebased dependency PR tend#890).claude_version2.1.226,actions/cachev6,astral-sh/setup-uvv9,actions/setup-nodev7.Full diff between releases: max-sixty/tend@0.1.14...0.1.17