feat: implement issue #2081 — CI check: fail when the dev-lead retry sweep sends a client_payload field the pinned channel's intent parser does not read
Summary
This PR adds scripts/check-retry-payload-fields.sh and runs it as the retry-payload-fields job in lint.yml. The check fails when the dev-lead retry sweep sends a top-level client_payload field that scripts/dev-lead-intent.sh does not read at some channel of the pinned major (dev-lead/v<N>-{next,ring0,ring1,stable}).
Rework (68beeeb, at the maintainer's request). The first version scanned the scripts with text patterns, and that kept leaving gaps: comments counted as field reads, punctuation inside quoted values broke the parsing, and a failed tag fetch fell back to a stale local tag. The check now reads both sides structurally:
- Sent fields. Every function in the sweep, and in the libs it sources, that POSTs to
/dispatchesis executed withghstubbed to capture the request. The top-levelclient_payloadkeys are read from the captured JSON with jq. Both the--input -form and the-f/-F client_payload[key]=form are captured. A dispatcher that sends nothing for the probe call is exit 2, never a pass. - Read fields. At each channel tag, the intent parser and the libs it sources are first parsed by bash: each file is wrapped in a function and printed back with
declare -f. That drops comments and keeps strings verbatim. Then theclient_payload.<key>reads are collected. - Which channels. Since #2083 the sweep runs at this repo's pin, so the remaining skew is a target repo on an older channel (#2086). The check therefore compares against every channel of the major:
- the pinned tag must resolve;
- a missing other channel is skipped with a warning;
- in CI, a tag that exists upstream but can't be fetched fails closed (exit 2).
main is merged in. The AGENTS.md conflict with #2083's rewrite of the same rule keeps main's text and adds a reference to the check.
Problem
From #2081, the follow-up to #2050's AC2. When a sweep sends a field before the parser at a consumer's channel reads it, every dispatched run fails or misroutes. That happened in #2050, where comment_node_id broke every fix-bot-comment retry.
Risk
Low. This is a new CI check plus its tests; runtime behaviour doesn't change. On today's main it passes: every channel of v139 reads every field the sweep sends.
Test plan
tests/test_retry_payload_fields.bats: 13 tests, all passing.- Includes one test per review finding: comment-as-read, quoted punctuation, the
-fform, sourced libs, stale tag in CI, a dispatcher that sends nothing, an indirectly built payload. - 11 of the 13 fail against the previous scanner.
- Includes one test per review finding: comment-as-read, quoted punctuation, the
CI=true bash scripts/check-retry-payload-fields.shon the real repo printsOKagainstdev-lead/v139-{next,ring0,ring1,stable}.shellcheck --severity=warning scripts/*.sh scripts/lib/*.shandbash scripts/dev-lead-lint.sh: clean.
Rollback
Revert this PR. There are no non-revertible side effects.
Monitoring
The retry-payload-fields job in Lint. A failure names the field, the dispatcher that sends it, and the channel whose parser doesn't read it.
Closes #2081
🤖 Generated with Claude Code