OPER-170
check-ticket-trailer sticky comment never updates: GraphQL node id PATCHed to a REST endpoint
Suggested
Justin Cooke
Body
---
feature_id: FEAT-studio-platform
size: XS
module: platform
verification_cmd: bash scripts/ticket-trailer-selftest.sh
writeSets: [.github/workflows/check-ticket-trailer.yml]
phiInScope: false
---
## Context
`check-ticket-trailer.yml` can never update its sticky comment in place. The
"Post or update sticky comment" step reads the existing comment id with:
gh pr view "$PR_NUMBER" --json comments --jq ".comments[] | ... | .id"
`gh pr view --json comments` is GraphQL-backed, so `.id` is a **node id**
(`IC_kwDOTPz4kM8AAAABThKZmg`). The step then PATCHes the REST endpoint
`repos/$GITHUB_REPOSITORY/issues/comments/$EXISTING`, which requires the
**numeric** REST id (`[REDACTED-PHONE]`). The PATCH 404s and is swallowed by the
step's `|| echo "comment update failed (non-fatal)"` fallback, so the workflow
reports success while the comment is untouched.
Net effect: the first verdict a PR ever gets is the only one it ever shows. A
PR that fails the check, then adds a `ticket/<PROJECT>-N` label and passes the
re-run, keeps a **FAIL** comment on its page forever. The `pass` branch of the
step is dead code — it has never rendered.
Observed on OPER-163's stack. PRs #470 and #471 both carry a sticky
`Ticket trailer check: FAIL` comment; both were labelled `ticket/OPER-163`
seconds later, and both `labeled` re-runs completed **success**
(workflow runs at 2026-09-09T15:57:28Z and 15:57:30Z). The required status
check is green on both, so this is cosmetic to merge gating but actively
misleading to a human reading the PR — it invites a reviewer to "fix" a check
that already passes.
`agent-automerge.yml:102` also calls `gh pr view --json comments`, but only
greps `.comments[].body` for a marker and never PATCHes by id, so it is not
affected. This is the only occurrence.
## Acceptance Criteria
- **Done when:**
- The sticky-comment step resolves the comment id from the REST list
endpoint (`gh api repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments`)
rather than `gh pr view --json comments`, so the id it PATCHes is the id
that endpoint accepts
- A PR that flips fail -> pass has its sticky comment rewritten to
`Ticket trailer check: PASS`, verified on a live PR
- The `|| echo "... (non-fatal)"` fallback no longer hides a 404: a failed
comment write emits a `::warning::` naming the status code, so the next
instance of this bug is visible in the run log instead of silent
- Backfill: the stale FAIL comments on #470 and #471 are corrected or removed
- **Self-test:**
- `scripts/ticket-trailer-selftest.sh` gains a case asserting the id the
step resolves is numeric, so a future revert to the GraphQL node id fails
CI rather than silently disabling the update path again
## Provenance
Found by the OPER-163 agent while verifying CI on the KNUCK-P repair stack
(PRs #470/#471/#472). Not in OPER-163's scope -- OPER-163 is the KNUCK-P
routing-metadata repair job -- so it is filed separately rather than fixed
in-flight. Original gate: OPER-D2 (#69). Decision function extracted to
`scripts/ticket-trailer-eval.sh` under OPER-145 / KNUCK-A032.
Attachments
Loading attachments…
Comments
Loading comments…