fix(ci): re-pin the watchdog and file its tracking issue in medley - #319
Conversation
…ley as its tracking-issue repo The watchdog has failed 254 of 254 runs since 2026-07-22 — never once succeeded. Detection was never the problem; the issue-filing identity was. The reusable's second token mint had no `repositories` input, so it defaulted to the calling repository, `melodic-software/standards` — the sync source, deliberately outside the sync App's 8-repo selected access — and 404'd on `GET /repos/melodic-software/standards/installation` before the scan could report anything. ci-workflows#346 added the required `tracking-issue-repository` input that fixes it, but this caller pins by SHA, so that merge changed nothing here. This is the change that closes the defect. `medley` is the destination: private, inside the App's selected access, and not the public repo whose alert body would otherwise republish four private targets' repository names and PR URLs. The runner-policy contract gains an entry for the new SHA rather than replacing the old one — older entries stay for consumers still pinning them, and `8202e03f` remains live for `sync.yml`'s separate workflow key. Its `allowedInputs` is the first in this family to actually grow. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
`medley` is one of the eight scanned targets — the header's own motivating incident, medley#1619, is a medley sync PR. The destination sentence carried the old wording's shape over and inherited a claim that was true of the calling repo but is false of medley. What is actually true is that the issue goes to ONE named repository rather than being scattered across the targets; the privacy rationale for choosing a private one is unaffected. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Claude finished @kyle-sexton's task in 3m 6s —— View job Code reviewReviewed the three changed files for correctness and alignment with No blocking or nit findings. This is a clean, internally consistent fix. What I checked and confirmed:
Nothing to add beyond what the PR body already documents (including the deliberately-left-open #274 rationale and the pin-comment-date limitation, which are appropriately scoped as follow-up rather than blockers here). |
|
Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
The parenthetical's antecedent could be read as `medley` — the noun the sentence opens on — inverting the claim into "medley is not App-installed", which is the opposite of why it was chosen. Name the calling repo outright. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary
standards-sync-stuck-automerge-alerthas failed 254 of 254 runs since2026-07-22. Not mostly — every one. Detection was never the problem; the
issue-filing identity was. The reusable's second token mint carried no
repositoriesinput, soactions/create-github-app-tokendefaulted to thecalling repository and 404'd on
GET /repos/melodic-software/standards/installation.standardsis the syncsource, deliberately not a target, and therefore outside the sync App's
8-repo selected access. A watchdog that dies before it can report is worse than
no watchdog: its silence reads as "all clear".
ci-workflows#346 merged the fix — a required
tracking-issue-repositoryinput — at
ed6d410c1fe10d9deb40241bbe46428b31fafd57. That merge changednothing here on its own, because this caller pins by SHA. This PR is what
actually closes the defect.
The destination is
medley, and the reason is disclosure, not convenienceThe alert body builds a per-PR table embedding each reported PR's repository
name, number, and URL.
standardsis PUBLIC; four of the eight scannedtargets are PRIVATE (
dotfiles,github-iac,medley,provisioning).Filing the issue here would republish private repository names and PR URLs in
public, every hour, for as long as the condition held.
medleyis private, isinside the App's selected access, and is where the reusable's own header
already imagines this alert living.
medleyis also one of the scanned targets — it may end up reporting on itsown sync PRs. That is incidental, not the reason it was chosen, and the file
header now says so rather than implying the destination sits outside the scan.
Why the App installation is not widened instead
Adding
standardsto the sync App's installation would "fix" the 404 and breakeverything else:
sync.yml'sattestjob requires the installation's selectedset to equal the derived target set, so any addition fails the sync for
every target.
distribution/sync-manifest.ymlstates the position directly —standardsis "manifest source, not a target". Closed on design grounds. Thisis the reason issue #274's suggested fix is not the one taken; see Related.
Three files, and why the second two are not optional
.github/workflows/standards-sync-stuck-automerge-alert.yml8202e03f→ed6d410c; passtracking-issue-repository: medley; correct the now-false header prose.components/runner-policy/policy.jsoned6d410c,allowedInputsgrown bytracking-issue-repository.components/runner-policy/README.mdrunner" becomes false with this change.The runner-policy contract entry is a hard gate, not bookkeeping: without
it,
npm run lint:runner-policyrejects both the unknown SHA and the input thecaller now passes. The entry is added, not replaced — this map retains
superseded revisions (six
standards-sync.ymlSHAs, and the alert's own43bc8d0fand8202e03f, are all still present) so consumers still pinning anolder SHA keep a contract.
8202e03fadditionally remains live forsync.ymlunder a different workflow key.
allowedInputsis exactly the reusable's fiveworkflow_callinputs ated6d410c— no input the caller passes is missing, and no input the reusabledoes not define is claimed.
The value must be a bare name
tracking-issue-repository: medley, nevermelodic-software/medley. Thereusable's first step — before the checkout, so a malformed destination fails
early rather than confusingly late — rejects anything outside
^[A-Za-z0-9._-]+$, plus the literal.and... Anowner/repovalue mintsa token fine and then breaks downstream, which is precisely the failure the
guard exists to pre-empt.
No caller-side permission change is needed: the reusable mints its own
issue-scoped token, so this workflow's ambient
GITHUB_TOKENstill needs onlycontents: read.Test plan
Actual output from this branch, not a description of what would run:
Verified from primary sources rather than assumed:
gh pr view 346 --repo melodic-software/ci-workflows→state MERGED,mergeCommit.oid ed6d410c1fe10d9deb40241bbe46428b31fafd57,mergedAt 2026-08-04T02:07:30Z; reachable fromci-workflowsorigin/main.medleyis in the App's selected access.sync.ymlrun30870837177,attestjob:EXPECTED_REPOSITORIESlists all eight targets includingmelodic-software/medley, and the job passed — attest requires equality,so this is proof of the whole set, and proof
standardsis outside it.gh api orgs/melodic-software/installations→melodic-standards-synccarriesissues: write,repository_selection: selected, unsuspended. The mint is satisfiable.ed6d410c, not from asummary:
tracking-issue-repositoryistype: string,required: true, andthe first-step guard's accepted/rejected forms are as described above.
gh repo viewper repo:standardsPUBLIC;dotfiles,github-iac,medley,provisioningPRIVATE.An independent fresh-context agent re-derived all of the above with the
author's reasoning withheld, and found a defect that is fixed in this
branch: the header first claimed the destination was "neither this repo nor
any scanned target", which is false of
medley. Commit9d3fcedcorrects it.Its one remaining note is recorded below.
Known limitation of the pin-comment date
The comment reads
# ed6d410 2026-08-04, the commit's UTC date, matchingmergedAt. The convention incomponents/pin-comment-convention/fixes theform (
YYYY-MM-DD) but never says whose date, and the repo's own precedent isgenuinely split —
31a5b76 2026-07-21used UTC,f2d5e06 2026-07-14used thecommit's local-offset date. The machine check accepts either, so no claim of
"matches precedent" would be honest in either direction. UTC is chosen as the
observer-independent timestamp. Pinning this down belongs in the convention
component, not in this PR.
Related
Closes #273.
#274 is deliberately left open, not closed by this PR, and that is a
judgement call worth stating rather than burying:
resolve that symptom.
standardsto the App's selected-repositorieslist" (items 1 and 2) — is rejected on design grounds, not merely
unimplemented. The
attestequality check makes that change break the syncfor all eight targets. Closing fix(ci): standards-sync-stuck alert fails hourly — App token minting 404s on /standards/installation #274 with a keyword would record it as
"fixed as suggested", which is the opposite of what happened.
next occurrence is visible without someone reading run history — is a
genuine, still-unaddressed residual. This PR removes the specific cause of
the current 404; it does not add alerting on the alarm's own failure. That
residual is exactly the reason the defect went 254 runs unnoticed, and it
deserves to survive as tracked work rather than being auto-closed.
Recommended follow-up for a human: rescope #274 to its item 3, and close it as a
duplicate of #273 only if that residual is retracted or refiled elsewhere.
Delivers ci-workflows#346 to this consumer. Does not touch
distribution/sync-manifest.yml— standards#315 landed there at2026-08-04T02:07:15Z and this branch is built on that main.
After merge, the next
17 * * * *run is the first that can succeed. Nothingelse is required to stop the hourly failures.
What to expect after merge — green, and quiet
Two effects, worth stating so neither reads as a regression:
automerge: falseon all eight targets, so the never-armed half is inert by design, and the
armed-but-BLOCKED half has nothing to find —
gh pr list --author app/melodic-standards-sync --state openreturns no open sync PR anywhere inthe fleet right now. A green empty scan is the correct outcome, not evidence
the fix did not take. The first real exercise of the issue-filing path comes
when
automerge: trueis restored and a PR actually wedges.runner-policycomponent is sync-managed, so merging this cascadespolicy.jsonto all eight targets as ordinary sync PRs. Adding a contractentry (rather than replacing one) is what keeps that cascade safe: a target
still pinning
8202e03fkeeps its contract and its lint stays green.Because the empty-scan case cannot distinguish "fixed" from "still broken by
some later step", the honest verification after merge is a
workflow_dispatchrun confirming the token mint step itself now succeeds — the step that has
been 404ing — rather than inferring it from a green run.
Co-authored-by: Claude Opus 5 (1M context) noreply@anthropic.com