Skip to content

Finish the gha migration and fix the Claude workflow startup failure - #33

Merged
d-morrison merged 4 commits into
mainfrom
chore/finish-gha-migration
Aug 28, 2026
Merged

Finish the gha migration and fix the Claude workflow startup failure#33
d-morrison merged 4 commits into
mainfrom
chore/finish-gha-migration

Conversation

@d-morrison

@d-morrison d-morrison commented Aug 28, 2026

Copy link
Copy Markdown
Member

Closes #32

1. Fixes the Claude Code startup failure

Every Claude Code run on main since #30 concluded startup_failure --- nine
of them, most recently
33132530926.

Both Claude caller stubs pass an ANTHROPIC_API_KEY secret while pinned
@v1, and Morrison-Lab/gha only declares that secret at @v2. GitHub
rejects a workflow_call that passes a secret the callee does not declare,
before any job starts --- which is why the failure has no logs, no annotations,
and no check runs.

Repinned claude.yml, claude-code-review.yml, and news.yaml to @v2,
which is what the gha README says all three should be on anyway.

2. Migrates the remaining workflows gha models

removed replacement
check-spelling.yaml (insightsengineering action in a rocker container) spellcheck.yml@v2
lint-changed-files.yaml (hand-rolled lintr over whole changed files) lint-changed-lines.yml@v2 (changed lines)
version-check.yaml (hand-rolled desc comparison) version-check.yml@v2 + bump-dev-version.yml@v2

version-check inverts the old convention deliberately. A PR must now
leave DESCRIPTION's Version: alone, and bump-dev-version bumps it after
each merge to main --- two PRs both required to bump the same line are
guaranteed to collide. Bypass on a release PR with the no version increment
label (created in this pass, along with no changelog for the bump PR).

The repo already has the two settings that pair needs ("Allow GitHub Actions
to create and approve pull requests", "Allow auto-merge"), and main has no
required status checks, so no WORKFLOW_TOKEN is needed.

Unchanged, because gha models no equivalent: R-CMD-check.yaml,
R-check-docs.yml, check-readme.yaml, pkgdown.yaml, pr-commands.yaml,
copilot-setup-steps.yml, phase0-debug.yaml.

3. Adds the gha capabilities the repo was missing

lint-workflows, lint-yaml, lint-markdown, check-junk-files,
check-typos, check-secrets, check-links, check-phi,
check-new-line-breaks.

The three whole-tree linters start fail: false because this repo has
pre-existing drift; flipping them to blocking is tracked in #32. The rest are
diff-scoped or already clean against the current tree.

Verification

  • actionlint over all 24 workflows: no errors (three pre-existing
    info-level shellcheck notes in copilot-setup-steps.yml and
    phase0-debug.yaml, untouched here).
  • yamllint over every new file: clean.
  • spelling::spell_check_package("."): No spelling errors found after
    adding PHI and gha to inst/WORDLIST.
  • Every uses:, with: input, and secrets: entry checked against the
    Morrison-Lab/gha tree at the current v2 tag (d519c8b).

Deferred to #32

  • test-coverage.yaml migration --- blocked on its CmdStan install/cache
    steps, which gha does not model. Those steps look vestigial (no .stan
    file is tracked on main, cmdstanr is not in DESCRIPTION), but Chapter 2: Stan Model 2 Kronecker simulation (restructure) #13 is
    an open Stan PR, so that is worth settling first.
  • check-non-standard-chars.yml --- would fail today on em-dashes in
    .claude/skills/reprexes/SKILL.md (24 lines) and
    .github/copilot-instructions.md (16 lines), and the workflow has no
    paths-ignore input.
  • check-ai-tells --- needs threshold tuning against this repo's research
    prose.

d-morrison and others added 2 commits August 27, 2026 18:25
Repin claude.yml, claude-code-review.yml, and news.yaml from @v1 to @v2.
Both Claude callers pass an ANTHROPIC_API_KEY secret that Morrison-Lab/gha
only declares at @v2, so every Claude Code run since #30 was rejected before
any job started (startup_failure, no logs, no annotations).

Migrate the three remaining workflows gha models:

  check-spelling.yaml      -> spellcheck.yml@v2
  lint-changed-files.yaml  -> lint-changed-lines.yml@v2
  version-check.yaml       -> version-check.yml@v2 + bump-dev-version.yml@v2

version-check inverts the old convention on purpose: PRs stop touching
DESCRIPTION's Version:, and bump-dev-version bumps it after each merge to
main. The repo already allows Actions to open PRs and allows auto-merge, and
main has no required status checks, so no WORKFLOW_TOKEN is needed.

Add the gha capabilities the repo was missing: lint-workflows, lint-yaml,
lint-markdown, check-junk-files, check-typos, check-secrets, check-links,
check-phi, check-new-line-breaks. The three whole-tree linters start
warn-only because the repo has pre-existing drift.

Refs #32

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn
@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Adversarial review finding: gha's check-typos and check-new-line-breaks
derive their base from the pull_request event and, with no base to diff
against, skip and report success. A push trigger therefore put a green check
on main that examined nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn
@d-morrison
d-morrison marked this pull request as ready for review August 28, 2026 01:34
@d-morrison

Copy link
Copy Markdown
Member Author

Adversarial review (codex CLI, GPT-5.1)

Reviewed commit: 69fb691 (before ca61080).
Dispatched headless against git diff origin/main...HEAD, with the
Morrison-Lab/gha checkout available for verification. Published as received;
findings and verdict are the reviewer's wording.

Findings

  1. .github/workflows/check-junk-files.yml:14 --- check-junk-files.yml does
    not exist anywhere in Morrison-Lab/gha at tag v2; when triggered, GitHub
    rejects the reusable-workflow call and the junk-file check never runs.
  2. .github/workflows/check-typos.yml:17 --- check-typos.yml does not exist
    anywhere in Morrison-Lab/gha at tag v2; every push, pull request, or
    manual invocation fails before performing typo detection.
  3. .github/workflows/check-new-line-breaks.yml:7 --- the push and
    workflow_dispatch triggers cannot supply the PR base SHA required by the
    callee, whose implementation explicitly skips with exit code 0 when
    base-ref is empty; a direct push to main containing malformed semantic
    line breaks therefore reports success without checking anything.

Verdict: needs work

Posted by Claude Code (AI agent) --- not written by a human.

@d-morrison

Copy link
Copy Markdown
Member Author

Dispositions

1 and 2 --- Rebutted. Both workflows do exist at v2. The reviewer read a
stale local tag; v2 had moved and needed git fetch --tags --force. Against
the current v2 (d519c8b, 2026-08-27), all sixteen reusable workflows this
PR calls resolve:

$ for w in check-junk-files check-typos check-secrets check-phi check-links \
    check-new-line-breaks lint-workflows lint-yaml lint-markdown \
    lint-changed-lines spellcheck version-check bump-dev-version check-news \
    claude claude-code-review; do
    git cat-file -e "v2:.github/workflows/$w.yml" && echo "OK $w"
  done
OK check-junk-files
OK check-typos
... (16/16)

Every with: input and secrets: entry the callers pass was re-derived
against that same tag.

3 --- Addressed, in ca61080, and extended to check-typos.yml, which has
the same shape. Both are now pull_request-only. The reviewer is right that a
push run reports success having examined nothing --- gha's own callee comment
says so explicitly ("on push there's no base to diff against, so the check is
skipped") --- so the push trigger was adding a green check on main that
measured nothing. This deviates from gha's example stub deliberately; a push
trigger becomes meaningful once base-ref: all is viable, which needs the
existing tree cleaned first.

Posted by Claude Code (AI agent) --- not written by a human.

Two CI failures at ca61080:

roxygen2 8.1.0 (2026-08-04) records its version in Config/roxygen2/version
rather than RoxygenNote, so `roxygenise()` rewrote DESCRIPTION on every run and
docs-check went red. Pre-existing environmental drift rather than anything this
branch changed -- it last passed on main on 2026-07-28 -- but it blocks this PR,
so fix it here.

gha's new lint-markdown flagged a real defect in this branch's own NEWS entry:
a list item starting directly on the line after another item's continuation,
with no blank line between.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Claude finished reviewView run


This confirms the PR's technical claim exactly: roxygen2 8.1.0 released 2026-08-04, matching the commit message's stated root cause for the docs-check failure. Nothing hallucinated here.

I have enough to finalize the review.

Code Review — UCD-SERG/shigella PR #33

Prior verdict: Ready for merge posted 2026-08-28T01:38:29Z, reviewing commit ca61080. That round found no defects and confirmed the migration's core claims (v1→v2 secret-declaration fix, all 16 reusable-workflow paths resolving at gha@v2, the diff-only-check trigger fix).

What changed since that round

One additional commit landed after ca61080: f2a328f ("Fix docs-check and the NEWS list-item splice"), touching only DESCRIPTION and NEWS.md:

  • DESCRIPTION: replaces RoxygenNote: 8.0.0 with Config/roxygen2/version: 8.1.0.
  • NEWS.md: inserts a blank line before the "Moved the Claude, Claude-review..." bullet (fixing a list-item splice) and adds a new bullet documenting the roxygen2 change.

Verification performed on the new commit

  • roxygen2 field-rename claim. Verified via web search against Posit's official roxygen2 8.0.0 and 8.1.0 release notes: roxygen2 8.0.0 introduced Config/roxygen2/version to replace RoxygenNote (issue Plan transition from RoxygenNote to Config/Roxygen/... r-lib/roxygen2#1328), and roxygen2 auto-migrates the field on the next document()/roxygenise() run. roxygen2 8.1.0 was released 2026-08-04 — three weeks before this PR, and after this session's knowledge cutoff, which is why it wasn't already known; it is a real release, not a hallucination. This exactly matches the PR's stated root cause ("roxygen2 8.1.0 records its version in Config/roxygen2/version... roxygenise() rewrote DESCRIPTION on every run and docs-check went red").
  • NEWS.md fix correctness. Diffed ca61080f2a328fd directly (git diff ca61080 f2a328fd -- NEWS.md) to confirm the actual single-commit change rather than inferring it from the cumulative PR diff: a blank line was inserted between the two multi-line bullets, which is the correct CommonMark fix for a list-item continuation immediately followed by a new item marker.
  • Live CI confirmation, not just static review: gh pr checks 33 at the current head shows docs-check and lint / lint-markdown both passing, along with every other check (spellcheck, all three new lint-* callers, check-junk-files, check-typos, check-secrets, check-phi, check-new-line-breaks, link-checker, version-check, Check Changelog Action). This confirms both claimed fixes actually work, not merely that they look plausible.
  • Re-read the full cumulative diff (.claude-review-pr.diff) end to end to make sure no other file changed in this round beyond the two above — confirmed.

Findings

None. The new commit is a small, correctly-targeted fix for two CI failures that were introduced by the previously-reviewed commit, both fixes are technically accurate (verified against upstream roxygen2 release notes) and confirmed working by passing CI, and no new workflow, input, or permissions concern was introduced.

Verdict

Ready for merge — the prior round's "Ready for merge" verdict (comment posted 2026-08-28T01:38:29Z, reviewing ca61080) stands and is reinforced: the one commit added since then fixes two real CI failures with a correct and verified change, all checks are now green, and no new issues were found.

Reviewed commit: f2a328f

@github-actions

Copy link
Copy Markdown
Contributor

💰 Cost: $0.7219 (review) — run

@d-morrison

Copy link
Copy Markdown
Member Author

Fully clean at f2a328f

  • 27/27 checks green, including review / claude-review and require-review.
  • Review verdict: Ready for merge, at this exact head. Two rounds; the
    second independently re-verified the first rather than inheriting it.
  • mergeable: MERGEABLE, mergeStateStatus: CLEAN, zero unresolved threads.

The motivating bug is confirmed fixed by observation, not just by argument:
review / claude-review ran on this PR. Every Claude Code run on main
since #30 had concluded startup_failure before any job started.

Two failures surfaced on the first pushed head and were fixed in f2a328f:

  • docs-check --- roxygen2 8.1.0 (2026-08-04) records its version in
    Config/roxygen2/version rather than RoxygenNote, so roxygenise()
    rewrote DESCRIPTION on every run. Pre-existing environmental drift, not
    this branch's doing (it last passed on main on 2026-07-28), but it blocked
    this PR, so it is fixed here.
  • lint / lint-markdown --- the newly-added linter caught a real list-item
    merge splice in this branch's own NEWS.md entry. Note that fail: false
    does not cover it: the splice, long-code-block, and table-split companion
    checks each have their own toggle.

Not merging --- that is the repository owner's call.

Posted by Claude Code (AI agent) --- not written by a human.

@d-morrison
d-morrison merged commit 83910f6 into main Aug 28, 2026
27 checks passed
@d-morrison
d-morrison deleted the chore/finish-gha-migration branch August 28, 2026 02:19
d-morrison added a commit that referenced this pull request Aug 28, 2026
Resolves three conflicts introduced by #33 landing on main:

DESCRIPTION -- both sides independently migrated RoxygenNote to
Config/roxygen2/version (roxygen2 8.1.0), in different positions. Kept main's
placement and dropped the duplicate; DESCRIPTION is now byte-identical to
main's, which also satisfies the new version-check convention.

NEWS.md -- kept both sides. Neither entry supersedes the other.

inst/WORDLIST -- union of both sides, re-sorted in the file's existing
codepoint order (194 entries).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn
d-morrison added a commit that referenced this pull request Aug 28, 2026
check-typos is new on main as of #33 and found 58 items in this PR's added
lines. All 58 are false positives, and running typos 1.49.1 locally over the
merged tree reproduces the CI count exactly, so the fix is verifiable here.

_typos.toml excludes the two file classes that cannot meaningfully be
spellchecked -- .bib exports (author surnames; "Leroux-Roels" alone is three
findings) and inst/WORDLIST, whose entire purpose is to hold unusual words --
and accepts five domain abbreviations the model code and manuscripts use
deliberately: lik, lod, mis, nd, pn.

One genuine fix rather than a suppression: an ALL-CAPS emphasis in a comment
in inst/scripts/ch3/11_coverage.R ran "OVERestimates" together, which typos
splits into OVE + Restimates. Hyphenating it keeps the author's emphasis and
lets the checker see two real words.

_typos.toml is added to .Rbuildignore alongside the other root config files.

typos now exits 0 over the whole tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn
d-morrison added a commit that referenced this pull request Aug 28, 2026
The claude-review bot on #33 reported it directly: "No CLAUDE.md exists
anywhere in this repo, so compliance was judged solely against the SERG lab
manual." Every automated review here has been running without repo-specific
context.

Adopts UCD-SERG/serocalculator's shape rather than ucdavis/bcs's or
Morrison-Lab/gha's. Those carry 10-20 KB in each of AGENTS.md and CLAUDE.md,
which triplicates the content across three files -- and one of them drifting
is precisely the problem this commit also has to fix. So
.github/copilot-instructions.md stays the single source of truth, and the two
new files are short orientation that defers to it.

copilot-instructions.md was stale: its Continuous Integration section still
listed lint-changed-files.yaml and check-spelling.yaml as required checks,
both removed in #33. It now describes what actually runs, separates the
hand-maintained workflows from the Morrison-Lab/gha callers, and records the
lint-changed-lines backlog as pre-existing.

Three conventions that govern every PR here were written down nowhere:

  - Version: must not change in a PR. version-check inverted on 2026-08-27
    and bump-dev-version now owns the bump, so older branches and habit both
    point the wrong way. Added to the NEVER list too.
  - inst/WORDLIST and _typos.toml are separate accept-lists with different
    owners; adding a word to the wrong one silently fails.
  - gha caller pins, and the fact that a caller passing a secret the pinned
    tag does not declare fails with no logs, no annotations, and no check run.

.claude/settings.json adds a read-only permissions allowlist, as four of the
five configured peer repos carry.

Prose deliberately does not assert that _typos.toml exists: that file arrives
with #31, which is still open, so both files describe where such terms belong
rather than pointing at a path this branch does not have.

Verified locally: gha's own check-new-line-breaks over the added lines,
typos, spelling::spell_check_package(), and every relative link resolved.

Closes #35

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn
d-morrison added a commit that referenced this pull request Aug 28, 2026
…ns.md (#37)

* start: add AGENTS.md and CLAUDE.md (closes #35)

* Add AGENTS.md and CLAUDE.md; correct the stale copilot-instructions.md

The claude-review bot on #33 reported it directly: "No CLAUDE.md exists
anywhere in this repo, so compliance was judged solely against the SERG lab
manual." Every automated review here has been running without repo-specific
context.

Adopts UCD-SERG/serocalculator's shape rather than ucdavis/bcs's or
Morrison-Lab/gha's. Those carry 10-20 KB in each of AGENTS.md and CLAUDE.md,
which triplicates the content across three files -- and one of them drifting
is precisely the problem this commit also has to fix. So
.github/copilot-instructions.md stays the single source of truth, and the two
new files are short orientation that defers to it.

copilot-instructions.md was stale: its Continuous Integration section still
listed lint-changed-files.yaml and check-spelling.yaml as required checks,
both removed in #33. It now describes what actually runs, separates the
hand-maintained workflows from the Morrison-Lab/gha callers, and records the
lint-changed-lines backlog as pre-existing.

Three conventions that govern every PR here were written down nowhere:

  - Version: must not change in a PR. version-check inverted on 2026-08-27
    and bump-dev-version now owns the bump, so older branches and habit both
    point the wrong way. Added to the NEVER list too.
  - inst/WORDLIST and _typos.toml are separate accept-lists with different
    owners; adding a word to the wrong one silently fails.
  - gha caller pins, and the fact that a caller passing a secret the pinned
    tag does not declare fails with no logs, no annotations, and no check run.

.claude/settings.json adds a read-only permissions allowlist, as four of the
five configured peer repos carry.

Prose deliberately does not assert that _typos.toml exists: that file arrives
with #31, which is still open, so both files describe where such terms belong
rather than pointing at a path this branch does not have.

Verified locally: gha's own check-new-line-breaks over the added lines,
typos, spelling::spell_check_package(), and every relative link resolved.

Closes #35

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn

* Apply semantic line breaks and unsplice the added list items

Correcting my own claim on the parent commit. It said the added lines had
been verified with gha's check-new-line-breaks locally. That run was
vacuous: the checker diffs `<base>...HEAD`, and I ran it with the work
staged but not yet committed, so it examined an empty range and reported
"No lines missing semantic breaks" over 200-odd added lines. CI, running
the identical script at @v2, found ten. The tell was there to be read --
a clean result over that much new prose is not plausible -- and I did not
read it.

Re-run after committing, the same script reproduces CI exactly. Fixed:

  - 10 lines packing more than one sentence, now one sentence per line.
  - 6 list items merged onto a previous item's continuation line with no
    blank line between, which lint-markdown flags separately. Note that
    lint-markdown's `fail: false` does not cover this: the splice,
    code-block-length, and table-split companions each have their own
    toggle, and those default to failing.

copilot-instructions.md is wrapped at 72 columns throughout, so the added
prose is now stylistically distinct from the rest of the file. That is the
intended direction -- check-new-line-breaks is diff-scoped precisely so a
repository can adopt it without a whole-corpus reflow first.

Verified post-commit: check-new-line-breaks, check_list_item_splices.mjs,
check_table_splits.mjs, check_code_block_length.mjs, typos, and
spelling::spell_check_package() all clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn

* Address review round 2: correct false repo-state claims

Four blocking findings, all real, all accepted.

1 and 2 are the same mistake, and it is the one worth naming: I wrote the
layout and the "known-failing checks" sections from the PR #31 worktree
rather than from this branch. `inst/scripts/` and every `.stan` file exist
only on the chapter branches -- `git ls-files inst` on `main` returns
`inst/WORDLIST` and `inst/extdata/model.jags.r`, and nothing else. So this
PR asserted a directory layout that is not in the tree it ships to, and told
future readers to treat a `lint-changed-lines` failure there as a known
backlog when that check passes on `main`.

Both files now describe `main` as the thin skeleton it is, say that the
chapter code arrives with the feature branches, and tell the reader to derive
a layout with `git ls-files` rather than from prose. The backlog note is kept
but scoped to the branches that actually carry it.

That also exposed pre-existing errors in copilot-instructions.md that this PR
is the right place to fix: four references to `inst/stan/`, a directory that
has never existed. Stan models live in `inst/extdata/`.

4. `.claude/settings.json` was too loose for a list framed as read-only.
Dropped `gh api:*`, which permits `-X POST` and `-X DELETE`; dropped
`devtools::*`, which is R namespace syntax that can never match a Bash
invocation and was already covered by `Rscript -e`; narrowed `git branch:*`
to `git branch --list:*`, since the wide form permits `-D` and `-m`.

5. The version rule contradicts the lab manual, whose quality-assurance
checklist still lists "Version number has been incremented" -- and both new
files declare that manual authoritative. Verified against the source
(`coding-practices/quality-assurance-checklist.qmd:11`). Both files now name
the conflict, say the checklist predates `bump-dev-version`, and say the
manual still governs everything else.

Also linked `{spelling}` per the manual's package-link convention.

`.Rbuildignore` still does not ignore `_typos.toml`; that file arrives with
#31, which adds the entry, and duplicating it here would collide.

Verified post-commit against the real diff: check-new-line-breaks,
check_list_item_splices.mjs, check_table_splits.mjs, typos, and
spelling::spell_check_package() all clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn

* AGENTS.md: state CLAUDE.md's role as it describes itself

Round 3 non-blocking nit. AGENTS.md said CLAUDE.md 'says the same things',
while CLAUDE.md says it points here and adds only Claude-specific material.
The second is the accurate one, and it is the framing the whole
one-source-two-pointers shape depends on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HYDWsGL8cYC3ptLEL4Wayn

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Finish the gha migration, and fix the ANTHROPIC_API_KEY/@v1 startup failure in claude.yml

1 participant