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

Merged
DO
7d ago
+735-0

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 /dispatches is executed with gh stubbed to capture the request. The top-level client_payload keys 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 the client_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 -f form, sourced libs, stale tag in CI, a dispatcher that sends nothing, an indirectly built payload.
    • 11 of the 13 fail against the previous scanner.
  • CI=true bash scripts/check-retry-payload-fields.sh on the real repo prints OK against dev-lead/v139-{next,ring0,ring1,stable}.
  • shellcheck --severity=warning scripts/*.sh scripts/lib/*.sh and bash 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

https://claude.ai/code/session_019K6UsD7r25pAcRjJL3G6Kx