---
name: github-workflows
description: "Umbrella for GitHub repository, authentication, issue, PR, code-review, and codebase-inspection workflows via gh/git."
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
  hermes:
    tags: [github, gh, git, pull-requests, issues, code-review, repositories, auth]
---

# GitHub Workflows

Use this umbrella for GitHub work: authentication, repository setup, issue triage, pull requests, code reviews, releases, and quick codebase inspection.

## Prerequisites and discovery

```bash
gh auth status
git status --short --branch
gh repo view --json nameWithOwner,defaultBranchRef,url
```

Do not assume the active repo/remote. Confirm the repository and branch before mutating remote state.

## Authentication

Use `gh auth status` first when `gh` is installed. For HTTPS GitHub token setup, SSH key setup, or account switching, follow the preserved auth notes. Copilot API auth is not the same as `gh auth login`.

If `gh` is unavailable but a token is present in environment (`GITHUB_TOKEN` / similar), do not print the token. Use a temporary credential helper for probes and pushes, for example:

```bash
git -c credential.helper='!f() { echo username=x-access-token; echo password=$GITHUB_TOKEN; }; f' \
  ls-remote --heads origin <branch>
```

Different failure meanings matter:

- `could not read Username` → no usable HTTPS credential reached Git.
- `Invalid username or token` → credential was supplied but rejected.
- `Write access to repository not granted` / HTTP 403 → token exists but lacks write access to that repository; ask for a token with repo contents read/write or use an authorized SSH key.

When the user provides or rotates a repository PAT, store it as a file under `~/.hermes/secrets/<repo>_github_token` with mode `600`, and optionally create a companion env file that reads the token from disk rather than embedding it inline:

```bash
# ~/.hermes/secrets/<repo>.env
export <REPO>_GITHUB_TOKEN="$(cat "$HOME/.hermes/secrets/<repo>_github_token")"
export GITHUB_TOKEN="$<REPO>_GITHUB_TOKEN"
```

Verification must prove access without exposing the token: report permissions/length only, then use a temporary credential helper for `git ls-remote` or `gh repo view` with `GITHUB_TOKEN` sourced from the secret file. Do not print token contents, token hashes, or command traces containing the secret. Do not assume a generic `GITHUB_PAT` belongs to the active repo just because it exists; inspect the active `origin` owner/name and any `GITHUB_REPO`/credential metadata, then prove behavioral access to that exact repository/branch. A PAT that works for another repo can still return `Write access to repository not granted` for the current remote.

If the user asks to “update the repo” when the tree is dirty, preserve work in this order: run the relevant tests, commit coherent staged changes, attempt push with a token-safe one-shot credential helper, and if push is blocked by permissions, create a verified `git format-patch` or `git bundle` backup before final reporting. Do not treat a local commit alone as sufficient preservation when the remote push failed. Report clearly: local commit SHA, branch, tests, backup path/checksum, and exact remote permission blocker.

When a push is blocked but local work must be preserved, create and verify a Git bundle as an immediate backup:

```bash
mkdir -p ~/backups
git bundle create ~/backups/<repo>_<branch>_$(date +%Y%m%d_%H%M%S).bundle <branch>
git bundle verify ~/backups/<repo>_<branch>_*.bundle
```

If GitHub rejects a push because a token lacks `workflow` scope for `.github/workflows/*`, do not claim the repo push is impossible. Preserve CI as a documented template (for example `docs/github-actions-ci.yml`), remove/amend the workflow path from the commit, push the rest, and report that enabling Actions requires copying the file back with a token that has `workflow` scope.

For fine-grained PATs, make the missing permission explicit: normal code pushes need repository **Contents: Read and write**, PR work may need **Pull requests: Read and write**, but creating/updating `.github/workflows/*.yml` additionally requires repository **Workflows: Read and write**. Reading workflow-run history through the GitHub Actions API may still require **Actions: Read** even after the workflow file push succeeds; distinguish "workflow file is remote" from "can list run status via API." Fine-grained PATs commonly return no `x-oauth-scopes` header from the GitHub API; infer token family from the `github_pat_` prefix and prove permissions behaviorally with `ls-remote`, a normal code push if needed, and a workflow-file push attempt. For classic PATs, the equivalent is `workflow` in addition to `repo`.

When the user says a PAT was rotated, **reload it from the canonical secret file first** and explicitly bypass stale credentials before testing: unset local/global `credential.helper` where safe, run `git credential-cache exit`, avoid embedded credentials in `origin`, avoid `gh auth` unless intentionally using it, and use a one-shot `git -c credential.helper=...` command. Never rely on a previously exported shell variable or credential cache after token rotation.

If a generic PAT or existing `.git-credentials` entry gets `Write access to repository not granted` but the user provides a repo-specific token file, switch to a temporary `GIT_ASKPASS` reader for that file and verify only existence/mode/length, never token contents. See `references/repo-specific-token-askpass.md`.

Report clearly whether the state is only local/bundle-backed or actually remote-backed. When verifying a pushed feature branch, do not rely on `git ls-remote origin HEAD` alone: that reports the remote default branch HEAD, not necessarily the branch just pushed. Capture `BR=$(git branch --show-current)` and verify `git ls-remote origin "refs/heads/$BR"` matches `git rev-parse HEAD`; optionally also report remote default `HEAD` separately.

## Repository management

Use for clone/fork/create/remote/release flows. Check existing remotes and default branch before creating or pushing. Avoid force pushes unless explicitly requested.

### Local repo discovery when the remote is empty or inaccessible

When the user asks whether a named GitHub repository also exists locally, do not stop at the remote probe. Search the filesystem for the project name and likely variants, then inspect local Git remotes. A good discovery pass includes:

1. Filename/directory searches for the exact repo name and lowercase/substring variants.
2. Content searches for the repo name if filename search is empty.
3. Enumeration of local Git repositories under common roots (`~/projects`, `~/Projekte`, `~/workspace`, `~/agent`, and `~` with noisy directories pruned), checking both folder names and `git remote -v` output for the repo/owner/name.
4. A short report listing searched locations, matched repositories, and whether each match was name-based, remote-based, or content-based.

If GitHub returns `403` or requires credentials, do not conclude the remote is empty or missing. Say that the remote state is unverified unless a valid credential returns an empty ref list successfully.

For turning an already-existing local prototype into a clean remote-backed repo, use `references/local-project-initial-push-hygiene.md`: inspect ignored artefacts, add README/env example/dependency manifest, remove hardcoded machine paths, externalize local model/service names, run a minimal syntax/lint smoke, push with a token-file credential helper when `gh` is unavailable, and verify the exact branch ref after push.

### Uploading an existing local project to a new/empty GitHub repository

When the user asks to load an existing project into an empty GitHub repo:

1. Resolve and verify the local source directory first. Check the exact path and obvious variants (`~/agent/...`, `~/Projekte/...`, `~/projects/...`) before initializing or pushing anything.
2. Verify remote access without exposing credentials: use `git ls-remote` or the GitHub API with a one-shot credential helper / token file, and report only behavioral permission evidence.
3. Confirm the remote state (`size`, default branch, existing refs). If the repo is empty, expect `git ls-remote` to return no refs with exit `0`.
4. Inspect the local project before upload: identify stack/dependencies, read top-level docs/config, check current `git status` if already a repo, and run a secret/artifact hygiene pass (`.env`, token files, build/cache dirs, generated media, local DBs) before commit.
5. If the local source path cannot be found, stop before creating commits or placeholder content. Report exactly which paths/searches were checked and what remote access was verified, then ask for the correct path or source.
6. Push with a clean initial commit on the repository default branch unless the user requested a different branch, then verify remote refs after push.

## Issues

Use `gh issue list/view/create/edit/comment` or GraphQL for triage, labels, assignments, and project metadata. When creating issues, include reproduction steps, expected/actual behavior, and acceptance criteria.

## GitHub Actions CI

For mixed Python + Node repositories where `make verify` includes backend tests plus Vite/dashboard tests/build, load `references/github-actions-mixed-python-node-verify.md`. Key pitfall: a fresh GitHub runner has no `node_modules`; add `actions/setup-node@v4` plus `npm ci` with the dashboard lockfile before `make verify`, keep Playwright/E2E/live-smoke steps out of normal verify CI, and do not claim CI is green if Actions/Checks APIs return 403 despite a successful push.

## Pull requests

Standard loop:

1. Create/update a branch.
2. Commit coherent changes.
3. Open/update PR with summary and test evidence.
4. Watch CI and address failures.
5. Merge only when explicitly requested and policy allows.

## Code review

Review diffs, not intent. Prioritize correctness/security/regression risks, cite file paths and line ranges, and avoid commenting on unchanged code unless it is directly implicated.

## Codebase inspection

Use quick LOC/language/dependency inspection to orient before larger reviews or migration estimates. Prefer `pygount`/language-aware tools where available.

## Preserved source details

Full absorbed source skills are preserved in `references/absorbed-*.md` for command examples and specialized workflows.
