Guidance for Claude Code when working in this repository.
Central, reusable GitHub Actions for d-morrison / UCD-SERG / ucdavis R-package
and Quarto repositories (see README.md). Each capability ships as a
composite action plus a workflow_call reusable workflow. Consumers pin to @v1.
- Per-capability composite-action directories at the repo root, each with an
action.ymland, for R/Python capabilities, a language-specific helper script — e.g.check-bibliography-dois/(R),check-non-standard-chars/andcheck-phi/(Python).check-links/bundleslychee.default.toml;preview/,quarto-publish/, andopen-sync-pr/are action-only (the last is the shared push-and-open-PR helper used bybump-submoduleandsync-shared-fragments). .github/workflows/— theworkflow_callreusable workflows that wrap the composites (one per consumer-facing capability — the shared internalopen-sync-prcomposite has no wrapper), plus theclaude.ymlandclaude-code-review.ymlreusable wrappers, and_selftest.yml, which exercises composites on every PR — local./refs for pre-release capabilities, and@v1through the reusable-workflow wrappers for stable ones.claude-bot.ymlandclaude-review.ymlare event-triggered workflows that run the Claude bot in this repo, notworkflow_callwrappers.- Several workflows have no corresponding root composite:
check-news.yml,summary.yml, andpreview-deploy.ymlareworkflow_callreusable workflows that wrap external actions;cleanup-pr-previews.ymlis a self-containedworkflow_callreusable workflow (inline shell logic, no external composite);bump-submodule.ymlandsync-shared-fragments.ymlareworkflow_callreusable workflows that call the shared internalopen-sync-prcomposite;slide-major-tag.ymlis push- and dispatch-triggered and runs only in this repo. .github/actions/checkout-submodules/— a small shared composite reused by the reusable workflows.examples/— caller stubs consumers copy into their own repos.README.md,CHANGELOG.md— top-level project docs;REVDEPS.md— lists registered downstream consumer repos.
When editing a consumer-facing capability, change the composite (<name>/action.yml,
plus its helper script if one exists) and keep the wrapping reusable workflow and its
examples/<name>.yml stub in sync. Internal-only composites (like open-sync-pr)
have no wrapper or example stub to update. New .github/workflows/ changes are
exercised by _selftest.yml; because brand-new actions aren't at the @v1 tag
yet, the selftest runs them via the local ./<name> ref until release.
check-phi/tests/test_detectors.py is a pytest suite pinning each PHI detector's
positive and negative behavior. Run it with python3 -m pytest check-phi/tests/ -q;
CI runs it as the phi-tests job in _selftest.yml. There's no broader unit-test
harness — most capabilities are validated end-to-end by _selftest.yml, running
against this repo itself or small throwaway fixtures (stable capabilities via
@v1, pre-release ones from local source).
Claude Code on the web (and other remote/CI sessions) runs in a sandbox where the
gh and glab CLIs are not installed and there is no direct GitHub API
access. Skills and built-in commands that tell you to "use gh" — /review,
/code-review --comment, /security-review, /verify, PR babysitting, PR
creation — only work if their GitHub steps are translated to the GitHub MCP tools
(mcp__github__*). When a skill or command instructs a gh/glab command in
such a session, substitute the equivalent MCP tool below. (In a local session
where gh is on PATH, use gh as the skill describes.)
This repo is d-morrison/gha, so MCP calls use owner: d-morrison, repo: gha.
Operation / gh/glab command |
GitHub MCP equivalent |
|---|---|
gh pr list |
mcp__github__list_pull_requests |
gh pr view <n> |
mcp__github__pull_request_read (method: get) |
gh pr diff <n> |
mcp__github__pull_request_read (method: get_diff) |
| changed files in a PR | mcp__github__pull_request_read (method: get_files) |
gh pr status / gh pr checks |
mcp__github__pull_request_read (method: get_status / get_check_runs) |
gh pr create |
mcp__github__create_pull_request |
| read PR conversation comments | mcp__github__pull_request_read (method: get_comments) |
| read inline review comments | mcp__github__pull_request_read (method: get_review_comments) — also returns threadIds |
| post a top-level PR comment | mcp__github__add_issue_comment |
| post inline review comments | mcp__github__pull_request_review_write (method: create, no event) → mcp__github__add_comment_to_pending_review per comment → mcp__github__pull_request_review_write (method: submit_pending) |
| reply to a review comment | mcp__github__add_reply_to_pull_request_comment |
| approve / request changes | mcp__github__pull_request_review_write (method: create with event) |
| resolve a review thread | mcp__github__pull_request_review_write (method: resolve_thread, threadId: <id from get_review_comments>) |
gh issue list / gh issue view <n> |
mcp__github__list_issues / mcp__github__issue_read |
| read a file / repo contents | mcp__github__get_file_contents |
| CI runs & job logs | mcp__github__actions_list, mcp__github__actions_get, mcp__github__get_job_logs |
| watch / stop watching PR activity | mcp__github__subscribe_pr_activity / mcp__github__unsubscribe_pr_activity |
glab mr ... (GitLab) |
N/A — this repo is on GitHub; use the tools above |
Posting inline comments requires a pending review to already exist before
mcp__github__add_comment_to_pending_review; create the pending review first, add
each comment, then submit once at the end. Watch and respond to PR activity with
mcp__github__subscribe_pr_activity / mcp__github__unsubscribe_pr_activity (not
gh pr checks --watch).
A task often needs files from a sibling repo (e.g. d-morrison/qwt) that the
session's GitHub MCP tools aren't scoped to — those calls fail with
Access denied: repository … is not configured for this session. Don't report
the repo as inaccessible from that alone. First try the raw HTTP URL directly:
any public repo's files are fetchable with curl (or WebFetch) at
https://raw.githubusercontent.com/<owner>/<repo>/<branch>/<path>, which works
even when gh and the MCP tools don't. (This is how qwt's standalone workflows
were obtained to port them faithfully into the reusable workflows for #44/#45.)
Only fall back to "can't access it" — or to whatever session tooling can add a
repo to scope, if any — after the raw fetch also fails (private repo, or the
network policy blocks the host).
When reviewing a pull request (e.g. via /review, /code-review, or as a Claude
PR bot), evaluate the diff against both of the following, in addition to
correctness:
The UCD-SERG lab manual is the lab's authority on coding conventions. Hold changes to its standards, especially:
- Coding style —
object naming, line breaks/formatting, function documentation, comments,
message/communication style, and Quarto code-reference conventions (backticked
pkg::fn(), markdown package links — no raw HTML in.qmd). - Coding practices —
function decomposition and length limits, testing requirements, the QA
checklist, documentation,
{here}for paths, and tidyverse idioms. - Code repositories — repository organization and version-control practices.
The manual defers to the tidyverse style guide
for R; prefer tidyverse idioms and the native |> pipe.
Above all, code should be highly modular and idiomatic:
- Modular / decomposed. Favor small, single-purpose functions over long monolithic blocks. Flag duplicated logic (DRY), functions that do too much, deep nesting, and steps that should be extracted and named. In workflows and composite actions, factor shared logic into reusable units rather than copying it between files.
- Idiomatic. Code should read like the surrounding code and like the ecosystem's conventions — idiomatic R (tidyverse), idiomatic YAML/GitHub Actions, idiomatic shell. Prefer the standard, well-known way over a clever or bespoke one. Match existing naming, structure, and formatting in the file.
- Keep these front-of-mind: surface modularity and idiom issues even when the code is otherwise correct.
Be specific and cite the relevant manual section or principle when raising a point. Distinguish blocking issues from optional suggestions.